使用OpenCV消除OCR的背景噪声

5

我正在尝试使用tesseract进行OCR,为了获得更好的结果,我想在将其发送到tessseract之前去除背景噪声。

我已经知道文本具有固定的颜色,并使用cv2.inrange来消除噪声背景,但问题是背景噪声与文本颜色相似,所以我陷入了困境。

这是我要处理的原始测试图像:

img.png

我尝试过:

  • 使用cv2.inRange通过过滤内部文本颜色(颜色代码:#d7d4cf,类似白色但不是白色,略带灰色),但有很多背景噪声。结果图像使用白色。

1

  • 使用cv2.inRange通过过滤黑色类似的颜色(#171510),效果看起来更好,但仍不如我所希望的好。结果图像使用黑色。

2

  • 我还尝试使用位与(bitwise_and)将白色和黑色合并在一起,但得到了类似的结果,也不是很好。

有人可以帮助我或向我推荐任何东西吗?谢谢您提前。


    from PIL import Image
    from pytesseract import *
    import cv2
    import numpy as np

    def img_hsv_mask_white(img):
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)           
        # for hsv, OpenCV uses H: 0-179, S: 0-255, V: 0-255
        lower_hsv = np.array([0,0,185])           
        upper_hsv = np.array([179,17,235])
        mask = cv2.inRange(hsv, lower_hsv, upper_hsv)
        blur = cv2.blur(mask,(3,3))
        img2 = cv2.bitwise_and(img, img, mask = blur)
        #cv2.imshow("mask", mask)
        #cv2.waitKey (0)
        return img2

    def img_hsv_mask_black(img):
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)           
        # for hsv, OpenCV uses H: 0-179, S: 0-255, V: 0-255
        lower_hsv = np.array([0,0,0])
        upper_hsv = np.array([60,80,70])
        mask = cv2.inRange(hsv, lower_hsv, upper_hsv)

        blur = cv2.blur(mask,(8,8))
        #return blur
        img2 = cv2.bitwise_and(img, img, mask = blur)
        #cv2.imshow("mask", mask)
        #cv2.waitKey (0)
        return img2

    def immerge(img1, img2):
        img = cv2.bitwise_and(img1,img2)
        return img

    #require module: numpy, opencv-python, Pillow, pytesseract

    if __name__ == "__main__":
        pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract'
        #print(pytesseract.get_tesseract_version())
        for x in range(1,9):
            file = str.format("0711/{0}.png",x)
            srcimg = cv2.imread(file,cv2.IMREAD_UNCHANGED)
            white = img_hsv_mask_white(srcimg)
            black = img_hsv_mask_black(srcimg)
            merged = immerge(white, black)
            #cv2.imwrite("result.png",mask)
            code = pytesseract.image_to_string(merged, lang ='eng')
            print(code)
            cv2.imshow(file, merged)
            cv2.waitKey(0)
            #break


我认为你的文本字符太小且间距过小,即使你能去除背景,也无法获得良好的OCR结果。 - fmw42
1个回答

4

从第一个结果开始,您可以去除以下噪声:

  • 太大或太小而无法成为字母

  • 与其余文本的垂直中心不对齐

import cv2 as cv
import numpy as np

im = cv.imread('ocr.png')
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)

def size_threshold(bw, minimum, maximum):
    retval, labels, stats, centroids = cv.connectedComponentsWithStats(bw)
    for val in np.where((stats[:, 4] < minimum) + (stats[:, 4] > maximum))[0]:
      labels[labels==val] = 0
    return (labels > 0).astype(np.uint8) * 255

def y_centroid_threshold(bw, minimum, maximum):
    retval, labels, stats, centroids = cv.connectedComponentsWithStats(bw)
    for val in np.where((centroids[:, 1] < minimum) + (centroids[:, 1] > maximum))[0]:
      labels[labels==val] = 0
    return (labels > 0).astype(np.uint8) * 255

sized = size_threshold(thresh, 60, 300)
centered = y_centroid_threshold(sized, 40, 63)
cv.imwrite('ocr_out.png', centered)

你好,我花了一个小时尝试将你的Python代码翻译成C#,但没有成功。你知道如何用C#的方式编写np.where((stats[:, 4] < minimum) + (stats[:, 4] > maximum))和(labels > 0).astype(np.uint8) * 255吗?谢谢。 - Caden.Z
我不熟悉C#,但是对于标签>0,您可以使用opencv阈值操作: cv.threshold(np.random.randint(0, 1000, (150,150), np.uint16), 1, 255, cv.THRESH_BINARY)我想您可以在for循环中迭代stats[:, 4]。 - shortcipher3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接