Python Opencv:过滤图像以进行文本检测

问题描述 投票:2回答:2

unfiltered image

[我具有要降低噪声的这些图像集以便在上运行OCR:

我正在尝试从图像中读取1973。

我已经尝试过

import cv2,numpy as np


img=cv2.imread('uxWbP.png',0)
img = cv2.resize(img, (0, 0), fx=2, fy=2)
copy_img=np.copy(img)
#adaptive threshold as the image has different lighting conditions in different areas
thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 2)

contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#kill small contours
for i_cnt, cnt in enumerate(sorted(contours, key=lambda x: cv2.boundingRect(x)[0])):
    _area = cv2.contourArea(cnt)
    x, y, w, h = cv2.boundingRect(cnt)
    x_y_area = w * h
    if 10000 < x_y_area and x_y_area < 400000:
        pass
        # cv2.rectangle(copy_img, (x, y), (x + w, y + h), (255, 0, 255), 2)
        # cv2.putText(copy_img, str(int(x_y_area)) + ' , ' + str(w) + ' , ' + str(h), (x, y + 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
        # cv2.drawContours(copy_img, [cnt], 0, (0, 255, 0), 1)
    elif 10000 > x_y_area:
        #write over small contours
        cv2.drawContours(thresh, [cnt], -1, 255, -1)

cv2.imshow('img',copy_img)
cv2.imshow('thresh',thresh)
cv2.waitKey(0)

将图像显着改善为:

filtered image

关于如何对图像进行充分过滤的任何建议,无论是对过滤图像的改进,还是从一开始就完全更改,我都可以在上面运行OCR或某些ML检测脚本?我想将数字分开进行检测,但是也可以使用其他方法。

python opencv machine-learning computer-vision contour
2个回答
2
投票

我的第一个想法是对一种“不清晰的滤镜”进行高斯模糊处理。 @eldesgraciado指出了频率方面的内容,这基本上就是我们在这里所做的。我会讲一些代码和解释。您将需要弄乱参数。这可能不起作用,但这是我想到的第一件事。

>>> import cv2
>>> im_0 = cv2.imread("FWM8b.png")
>>> cv2.imshow("FWM8b.png", im_0)
>>> cv2.waitKey(0)
## Press any key.
>>> ## Here's where we get to frequency. We'll use a Gaussian Blur.
    ## We want to take out the "frequency" of changes from white to black
    ## and back to white that are less than the thickness of the "1973"
>>> k_size = 0 ## This is the kernal size - the "width frequency",
               ## if you will. Using zero gives a width based on sigmas in
               ## the Gaussian function.
               ## You'll want to experiment with this and the other
               ## parameters, perhaps trying to run OCR over the image
               ## after each combination of parameters.
               ## Hint, avoid even numbers, and think of it as a radius
>>> gs_border = 3
>>> im_blurred = cv2.GaussianBlur(im_0, (k_size, k_size), gs_border)
>>> cv2.imshow("gauss", im_blurred)
>>> cv2.waitKey(0)

Gaussian blur with kernel size determined by sigmas

好吧,我的参数可能还不够模糊。您想摆脱的单词部分并不是很模糊。我怀疑您会不会发现与原始版本有很大的不同,但希望您会明白。

我们将原始图像乘以一个值,将模糊图像乘以一个值,然后从value*blurry中减去value*orig。我希望代码会更清晰。

>>> orig_img_multiplier = 1.5
>>> blur_subtraction_factor = -0.5
>>> gamma = 0
>>> im_better = cv2.addWeighted(im_0, orig_img_multiplier, im_blurred, blur_subtraction_factor, gamma)
>>> cv2.imshow("First shot at fixing", im_better)

First attempted fix

是的,没有太大的不同。弄乱参数,在执行自适应阈值之前尝试进行模糊处理,然后尝试其他方法。我不能保证它会起作用,但希望它能使您开始前进。

编辑:将需要其他一些锐化类型。我刚意识到我将1.5和-0.5乘数应用于通常具有非常接近0或255的像素,这意味着我可能只是在锐化后恢复了原始图像。我欢迎对此提出任何反馈。

也来自@eldesgracio的评论:

有人可能比我使用的算法更好。对其进行足够的模糊处理,并可能对n×n网格(像素密度)上的平均值设置阈值。我对整个自适应阈值然后轮廓的事情不了解。也许在模糊之后可以重做...


只是给您一些想法...

[k_size = 5有点模糊

The Gaussian-blurred image

[k_size = 25有点模糊

enter image description here

请注意,这些是BLURS,而不是修复程序。您可能需要根据频率来弄乱orig_img_multiplierblur_subtraction_factor(我不记得具体如何,所以我真的不能告诉你它是如何完成的。)不要犹豫,[ C0],gs_border以及您可能在文档中找到的关于我显示的方法的任何其他内容。

祝你好运。>>

顺便说一下,频率更多是基于2-D快速傅立叶变换,甚至可能基于内核细节。我只是自己弄弄这些东西-绝对不是专家,并且如果有人想提供更多细节也绝对很高兴-但我希望我已经给出了一个基本的想法。添加一些抖动噪声(上下或左右模糊,而不是基于半径的抖动)也可能会有所帮助。


0
投票

另一项尝试与模糊分开或组合使用的是gamma

© www.soinside.com 2019 - 2024. All rights reserved.