噪音我在这里有一个图像与表。在右边的列中的背景充满了噪音OpenCV的 - 去除图像
如何与噪音检测领域?我只想在有噪音的部件上应用某种过滤器,因为我需要对其进行OCR,任何类型的过滤器都会降低总体识别度。
什么样的过滤器最适合去除背景噪音图片?
至于说我需要做OCR图像
噪音我在这里有一个图像与表。在右边的列中的背景充满了噪音OpenCV的 - 去除图像
如何与噪音检测领域?我只想在有噪音的部件上应用某种过滤器,因为我需要对其进行OCR,任何类型的过滤器都会降低总体识别度。
什么样的过滤器最适合去除背景噪音图片?
至于说我需要做OCR图像
我在OpenCV中尝试了一些过滤器/操作,它似乎工作得很好。
第1步:扩张图像 -
kernel = np.ones((5, 5), np.uint8)
cv2.dilate(img, kernel, iterations = 1)
正如你看到的,噪声消失,但角色很轻,所以我被侵蚀的形象。
第2步:侵蚀图像 -
kernel = np.ones((5, 5), np.uint8)
cv2.erode(img, kernel, iterations = 1)
正如你所看到的,噪声却走了另列的一些字符被打破。我建议只在嘈杂的列上运行这些操作。您可能想要使用HoughLines来查找最后一列。然后,您只能提取该列,运行扩张+侵蚀并将其替换为原始图像中的相应列。 此外,扩张+侵蚀实际上是一种称为结束的操作。这个你可以直接调用使用 -
cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
由于@Ermlg建议,medianBlur以3内核还奇妙的作品。
cv2.medianBlur(img, 3)
可供选择的步骤
正如你可以看到所有这些过滤器工作,但它是,如果你只在噪声是部分实现这些过滤器更好。要做到这一点,使用以下命令:
edges = cv2.Canny(img, 50, 150, apertureSize = 3) // img is gray here
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, 1000, 50) // last two arguments are minimum line length and max gap between two lines respectively.
for line in lines:
for x1, y1, x2, y2 in line:
print x1, y1
// This gives the start coordinates for all the lines. You should take the x value which is between (0.75 * w, w) where w is the width of the entire image. This will give you essentially **(x1, y1) = (1896, 766)**
然后,您可以提取这部分只喜欢:
extract = img[y1:h, x1:w] // w, h are width and height of the image
然后,在此图像中实现滤波器(中位数或关闭) 。去除噪点后,您需要将此滤波图像替换为原始图像中的模糊部分。 图像[Y1:H,X1:W] =中值
这是C++直接:
extract.copyTo(img, new Rect(x1, y1, w - x1, h - y1))
最终结果与替代方法
你有一个代码示例,可以用噪声检测的最后一列..像你说的你自己。无论你申请什么过滤器 - 文本将始终难以辨认。所以我只想与噪音 – clarkk
适用于图像的部分过滤器是我做的,给我一段时间和我会将其添加到答案中。 –
添加了检测最后一列的方法。让我知道它是否回答你的问题。 –
上据我所知中值滤波是降低噪音的最佳解决方案。我会建议使用3x3窗口的中值过滤器。请参阅功能cv::medianBlur()。
但是在使用OCR同时使用任何噪音过滤时要小心。它可能导致识别准确度降低。
另外我会建议尝试使用一对函数(cv :: erode()和cv :: dilate())。但我不敢保证它会最好的解决方案,然后cv :: medianBlur()与窗口3x3。
我会去中位模糊(可能是5 * 5内核)。
如果您打算应用OCR图像。我会建议您以下几点:
更快的解决方案:
尝试像这样阈值化图像。确保你的src
灰度。这种方法将只保留强度在150和255之间的像素。
threshold(src, output, 150, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
当您试图取消灰色像素时,您可能想要反转图像。手术后,再次将其反转以获得您想要的结果。
如果您在输入图像中的像素仔细看,你会看到,这里的输入已经是二值图像,与像素无论是在0或255 – Antonio
我的解决方案是基于阈值,以4个步骤得到结果图像。通过OpenCV 3.2.0
GaussianBlur()
来平滑图像,尤其是灰色区域。该代码在Python 2.7
。它可以很容易地更改为C++
。
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
# read Danish doc image
img = cv2.imread('./imagesStackoverflow/danish_invoice.png')
# apply GaussianBlur to smooth image
blur = cv2.GaussianBlur(img,(5,3), 1)
# threshhold gray region to white (255,255, 255) and sets the rest to black(0,0,0)
mask=cv2.inRange(blur,(0,0,0),(150,150,150))
# invert the image to have text black-in-white
res = 255 - mask
plt.figure(1)
plt.subplot(121), plt.imshow(img[:,:,::-1]), plt.title('original')
plt.subplot(122), plt.imshow(blur, cmap='gray'), plt.title('blurred')
plt.figure(2)
plt.subplot(121), plt.imshow(mask, cmap='gray'), plt.title('masked')
plt.subplot(122), plt.imshow(res, cmap='gray'), plt.title('result')
plt.show()
以下是通过代码绘制图片供参考。
这里是在2197 X 3218像素结果图像。
这仍然应用过滤器的整体形象上。我需要只用噪音 – clarkk
@clarkk确定适用零件上的过滤器的解决方案。噪音区域是否固定并已知?像附加的样本图像一样?如果没有,还有更多的样本文件要显示? – thewaywewere
如果您非常担心去除可能会损害您的OCR检测像素。不添加人工制品,尽可能使其纯粹。然后你应该创建一个blob过滤器。并删除任何小于n像素左右的斑点。
不打算编写代码,但我知道这很好,因为我自己使用这个,虽然我不使用openCV(我写了我自己的多线程blobfilter超速的原因)。抱歉,但我不能在这里分享我的代码。只是描述如何去做。
如果处理时间不是问题,在这种情况下,一个非常有效的方法将计算所有黑色连通分量,并去除那些小于几个像素的分量。它会去除所有嘈杂的点(除了接触有效的组件),但保留所有字符和文档结构(线等)。
要使用的函数将是connectedComponentWithStats(在您可能需要生成负像之前,threshold函数将在此情况下起作用),绘制白色矩形,其中找到小的连接组件。实际上,这种方法可以用来查找字符,将字符定义为给定最小和最大尺寸的连通分量,并且在给定范围内具有纵横比。
我之前消化了 – user3800527
@ user3800527没错,我错过了。我的回答为opencv实现添加了一些提示。 – Antonio
我已经面临同样的问题,并得到了最好的解决方案。 将源图像转换为灰度图像并应用fastNIMeanDenoising函数然后应用阈值。
这样 - fastNlMeansDenoising(gray,dst,3.0,21,7); 阈值(dst,finaldst,150,255,THRESH_BINARY);
也使用可以调整门槛accorsing你的背景噪音图像。 EG-阈值(DST,finaldst,200255,THRESH_BINARY);
注意 - 如果您的列线得到了删除...您可以采取的列线屏蔽来自源图像,并且可以适用于使用像AND,OR,XOR位操作去噪导致图像。
您可能想要删除您样本图像“个人”的信息。 – cwap
你能告诉文档图像中的语言吗? – thewaywewere
其丹麦..... – clarkk