Типичные методы удаления линий - использование горизонтальных / вертикальных ядер или cv2.HoughLinesP()
, но эти методы работают, только если линии прямые. В этом случае линии не являются прямыми, поэтому идея состоит в том, чтобы использовать диагональное ядро, морфологические преобразования и контурную фильтрацию для удаления линий из текста. Я буду использовать подход предыдущего ответа, найденный в удалении горизонтальных линий в изображении , но с диагональным ядром
Мы начнем с преобразования изображения в оттенки серого и выполним порог Оцу, чтобы получитьдвоичное изображение. Затем мы создаем диагональное ядро, затем выполняем морфологическое закрытие, чтобы обнаружить / отфильтровать диагональные линии. Поскольку cv2.getStructuringElement()
не имеет встроенного диагонального ядра, мы создаем свое собственное
# Read in image, grayscale, and Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Create diagonal kernel
kernel = np.array([[0, 0, 1],
[0, 1, 0],
[1, 0, 0]], dtype=np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
Изображение изолировало основные диагональные линии, но онотакже включены небольшие строки из текста. Чтобы удалить их, мы находим контуры и фильтруем, используя область контура. Если контур проходит через наш фильтр, мы эффективно удаляем шум, «заполняя» контур с помощью cv2.drawContours()
. Это оставляет нам желаемые диагональные линии для удаления
# Find contours and filter using contour area to remove noise
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area < 500:
cv2.drawContours(opening, [c], -1, (0,0,0), -1)
Отсюда мы просто cv2.bitwise_xor()
с исходным изображением, чтобы получить наш результат
# Bitwise-xor with original image
opening = cv2.merge([opening, opening, opening])
result = cv2.bitwise_xor(image, opening)
Примечания: Трудно удалить строки, не затрагивая текст, хотя это возможно и потребует некоторых хитрых уловок, чтобы «исправить» текст. Взгляните на удаление границ с изображения, но оставьте текст написанным на границах , чтобы найти способ восстановить отсутствующий текст. Другим методом выделения диагональных линий может быть противоположный подход;вместо того, чтобы пытаться обнаружить диагностические линии, почему бы не попытаться определить, что не является диагностической линией. Возможно, вы могли бы сделать это с помощью простых методов фильтрации. Для создания динамических диагональных ядер вы можете использовать np.diag()
для различной ширины диагональной линии
Полный код для полноты
import cv2
import numpy as np
# Read in image, grayscale, and Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Create diagonal kernel
kernel = np.array([[0, 0, 1],
[0, 1, 0],
[1, 0, 0]], dtype=np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
# Find contours and filter using contour area to remove noise
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area < 500:
cv2.drawContours(opening, [c], -1, (0,0,0), -1)
# Bitwise-xor with original image
opening = cv2.merge([opening, opening, opening])
result = cv2.bitwise_xor(image, opening)
cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('result', result)
cv2.waitKey()