从图像中删除嘈杂的线条

tes*_*est 9 python opencv image-processing noise-reduction

我有一些随机行的图片,如下所示:
在此输入图像描述
我想在它们上面应用一些预处理,以消除不必要的噪声(扭曲写入的线条),以便我可以将它们与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)
Run Code Online (Sandbox Code Playgroud)

不幸的是,扩张效果不佳,噪声线仍然存在.

在此输入图像描述
我尝试改变内核形状,但情况变得更糟:写入被部分或完全删除.
我还找到了一个答案,说可以删除这些行

将具有两个或更少相邻黑色像素的所有黑色像素转换为白色.

这对我来说似乎有点复杂,因为我是计算机视觉和opencv的初学者.
任何帮助将不胜感激,谢谢.

Cri*_*ngo 8

检测这样的线路是开发路径的原因.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'})
Run Code Online (Sandbox Code Playgroud)

在这里,我们首先将图像反转,因为这使得其他事情变得更容易 如果不反转,请使用路径关闭.该lines图像:

线

接下来我们减去线条.小区域开口移除了由路径开口过滤掉的线路中的少数孤立像素:

text = img - lines
text = dip.AreaOpening(text, filterSize=5)
Run Code Online (Sandbox Code Playgroud)

文本

但是,我们现在已经在文本中留下了空白.填补这些并不是微不足道的.这是一个快速而肮脏的尝试,您可以将其作为起点:

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

最后结果

  • @测试:太棒了!您应该也可以直接使用 PyDIP 中 OpenCV 读取的图像,无需先保存它。只需使用 OpenCV `imread` 而不是 pyplot `imread`。 (2认同)

sin*_*ium 7

您可以使用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)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明
代码的下一部分将仅删除长度超过 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)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

好吧,它不能与当前图像完美配合,但它可能会为不同的图像提供更好的结果。您可以调整要删除的线的长度和要绘制的白线的粗细,以代替已删除的线。
我希望它有帮助。