Удалить шумные линии с изображения - PullRequest
0 голосов
/ 03 января 2019

У меня есть изображения, которые зашумлены некоторыми случайными линиями, такими как следующая:
enter image description here
Я хочу применить к ним некоторую предварительную обработку, чтобы удалить нежелательный шум (линии, которые искажают запись)так что я могу использовать их с OCR (Tesseract).
Идея, которая пришла мне в голову, состоит в том, чтобы использовать расширение для удаления шума, а затем использовать эрозию для исправления недостающих частей записи на втором этапе.
Длячто, я использовал этот код:

import cv2
import numpy as np

img = cv2.imread('linee.png', cv2.IMREAD_GRAYSCALE)
kernel = np.ones((5, 5), np.uint8)
img = cv2.dilate(img, kernel, iterations=1)
img = cv2.erode(img, kernel, iterations=1)
cv2.imwrite('delatedtest.png', img)

К сожалению, расширение не работает хорошо, шумовые линии все еще существуют.

enter image description here
Я пытался изменить форму ядра, но стало хуже: запись была частично или полностью удалена.
Я также нашел ответ , говорящий, что этоможно удалить строки,

, превратив все черные пиксели с двумя или менее смежными черными пикселями в белый.

Это кажется мне немного сложным, так как я новичок в области компьютерного зрения и opencv.
Буду признателен за любую помощь, спасибо.

Ответы [ 2 ]

0 голосов
/ 06 января 2019

Вы можете сделать это, используя createLineSegmentDetector(), функцию из opencv

import cv2

#Read gray image
img = cv2.imread("lines.png",0)

#Create default parametrization LSD
lsd = cv2.createLineSegmentDetector(0)

#Detect lines in the image
lines = lsd.detect(img)[0] #Position 0 of the returned tuple are the detected lines

#Draw the detected lines
drawn_img = lsd.drawSegments(img,lines)

#Save the image with the detected lines
cv2.imwrite('lsdsaved.png', drawn_img)

enter image description here
Следующая часть кода удалит только те строки, длина которых превышает 50 пикселей:

for element in lines:

#If the length of the line is more than 50, then draw a white line on it
if (abs(int(element[0][0]) - int(element[0][2])) > 50 or abs(int(element[0][1]) - int(element[0][3])) > 50): 

#Draw the white line
cv2.line(img, (int(element[0][0]), int(element[0][1])), (int(element[0][2]), int(element[0][3])), (255, 255, 255), 12)

#Save the final image
cv2.imwrite('removedzz.png', img)

enter image description here

Что ж, с текущим изображением оно не работает идеально, но может дать лучшие результаты для разных изображений. Вы можете настроить длину удаляемых линий и толщину белых линий, чтобы рисовать вместо удаленных линий.
Надеюсь, это поможет.

0 голосов
/ 03 января 2019

Обнаружение подобных линий - это то, для чего было изобретено открытие пути . PyDIP имеет реализацию (раскрытие: я реализовал ее там; также обратите внимание, что вам придется устанавливать PyDIP из источников, так как мы еще не создали бинарный дистрибутив).В качестве альтернативы вы можете попробовать использовать реализацию авторами статьи, которую я связал выше.Эта реализация не имеет «ограниченного» режима , который я использую ниже.

Вот краткая демонстрация того, как вы можете его использовать:

import PyDIP as dip
import matplotlib.pyplot as pp

img = 1 - pp.imread('/home/cris/tmp/DWRTF.png')
lines = dip.PathOpening(img, length=300, mode={'constrained'})

Здесь мысначала перевернул изображение, потому что это делает другие вещи позже легче.Если не инвертировать, используйте вместо этого закрытие пути.Изображение lines:

lines

Далее вычитаем линии.Небольшое открытие области удаляет несколько изолированных пикселей линии, которые были отфильтрованы с помощью открытия пути:

text = img - lines
text = dip.AreaOpening(text, filterSize=5)

text

Однако мысейчас сделаны пробелы в тексте.Заполнение их не тривиально.Вот быстрая и грязная попытка, которую вы можете использовать в качестве отправной точки:

lines = lines > 0.5
text = text > 0.5
lines -= dip.BinaryPropagation(text, lines, connectivity=-1, iterations=3)
img[lines] = 0

final result

...