【问题标题】:Opencv, Python - How to remove the gray pixels around the date textOpencv,Python - 如何删除日期文本周围的灰色像素
【发布时间】:2020-12-31 05:09:17
【问题描述】:

我正在尝试使用 Python/OpenCV 去除日期周围的灰色“噪音”,以帮助 OCR(光学字符识别)识别日期。

原图如下:https://static.mothership.sg/1/2017/03/10-Feb-MC-1.jpg

我尝试的 python 脚本如下所示。但是,我有其他类似的图像,其中的对比度或照明条件会有所不同。

import cv2
import numpy as np

img = cv2.imread("mc.jpeg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

alpha = 3.5
beta = -2

new = alpha * img + beta
new = np.clip(new, 0, 255).astype(np.uint8)

cv2.imwrite("cleaned.png", new)

我还尝试了Thresholding 和/或adaptiveThresholding,有一段时间,我能够将日期与灰色背景区分开来。有时这是非常具有挑战性的。我想知道是否有一种自动确定阈值的方法?

以下是我希望实现的示例。

模糊图像:

【问题讨论】:

    标签: python opencv image-segmentation image-thresholding


    【解决方案1】:

    Otsu 的二值化自动根据图像直方图计算阈值。

    # Otsu's thresholding after Gaussian filtering
    blur = cv2.GaussianBlur(img,(5,5),0)
    ret,Otsu = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    
    cv2.imwrite("Otsu's_thresholding", Otsu)
    

    看到这个link

    【讨论】:

    • 谢谢。它不太奏效。一些图像变得太暗,一些变得太亮。
    【解决方案2】:

    您可以尝试构建一个背景模型,然后按该模型对每个输入像素进行加权。 输出增益在大部分图像中应该是相对恒定的。以下是此方法的步骤:

    1. 应用软中值模糊滤镜以去除小噪点
    2. 通过局部最大值获取背景模型。应用一个非常强的close 操作,使用一个大的structuring element(我正在使用大小为15 的矩形内核)
    3. 通过在每个局部最大像素之间划分255 来执行增益调整。使用每个输入图像像素加权此值。
    4. 你应该得到一个很好的图像,其中背景照明几乎标准化threshold这个图像得到文本的二进制掩码

    这是代码:

    import numpy as np
    import cv2
    
    # image path
    path = "C:/opencvImages/sheet01.jpg"
    
    # Read an image in default mode:
    inputImage = cv2.imread(path)
    
    # Remove small noise via median:
    filterSize = 5
    imageMedian = cv2.medianBlur(inputImage, filterSize)
    
    # Get local maximum:
    kernelSize = 15
    maxKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize))
    localMax = cv2.morphologyEx(imageMedian, cv2.MORPH_CLOSE, maxKernel, None, None, 1, cv2.BORDER_REFLECT101)
    
    # Adjust image gain:
    height, width, depth = localMax.shape
    
    # Create output Mat:
    outputImage = np.zeros(shape=[height, width, depth], dtype=np.uint8)
    
    for i in range(0, height):
    
        for j in range(0, width):
            # Get current BGR pixels:
            v1 = inputImage[i, j]
            v2 = localMax[i, j]
    
            # Gain adjust:
            tempArray = []
            for c in range(0, 3):
    
                currentPixel = v2[c]
                if currentPixel != 0:
                    gain = 255 / v2[c]
                    gain = v1[c] * gain
                else:
                    gain = 0
    
                # Gain set and clamp:
                tempArray.append(np.clip(gain, 0, 255))
    
            # Set pixel vec to out image:
            outputImage[i, j] = tempArray
    
    # Convert RGB to grayscale:
    grayscaleImage = cv2.cvtColor(outputImage, cv2.COLOR_BGR2GRAY)
    
    # Threshold:
    threshValue = 110
    _, binaryImage = cv2.threshold(grayscaleImage, threshValue, 255, cv2.THRESH_BINARY)
    
    # Write image:
    imageFilename = "C:/opencvImages/binaryMask2.png"
    cv2.imwrite(imageFilename, binaryImage)
    

    我得到以下测试完整图像的结果:

    还有裁剪后的文字:

    请注意,增益调整操作未矢量化。脚本很慢,主要是因为我从Python 开始,不知道正确的Numpy 语法来加速这个操作。我已经使用C++ 很长时间了,请随时进一步改进代码。

    编辑:

    请注意,您的结果只能与您输入的质量一样好。查看您的输入并问自己“对于自动化流程来说,这是一个好的输入吗?”(自动化流程通常不是很聪明)。您发布的第二张图片质量非常低。不仅模糊,而且分辨率低,并且有压缩伪影。所有这些因素都会阻碍自动化处理。

    话虽如此,您可以在原始版本中加入以下改进: 在灰度输出上尝试normalizebrightness-contrast:

    grayscaleImage = np.uint8(cv2.normalize(grayscaleImage, grayscaleImage, 0, 255, cv2.NORM_MINMAX))
    

    您的灰度图像来自:

    致:

    稍微暗一点,对比度有所提高。让我们尝试通过Otsu thresholding自动计算最优阈值:

    threshValue, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    

    它让你得到这个:

    但是,如果我们将bias 添加到 Otsu 的阈值,我们可以调整结果,如下所示:

    threshValue, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    bias = 0.9
    threshValue = bias * threshValue
    _, binaryImage = cv2.threshold(grayscaleImage, threshValue, 255, cv2.THRESH_BINARY)
    

    这是使用此方法可以获得的最佳图像质量。 如果您觉得这些建议和技巧有用,请至少给我的答案投票。

    【讨论】:

    • 感谢您帮助解决我面临的问题。就像你说的,脚本很慢,但它有效!我尝试了我拥有的测试图像,当图像清晰时它确实有效。对于模糊图像,输出大部分是白色的。如果您想对其进行测试,我在原始帖子中放置了一个“模糊”图像。谢谢。
    • 我想知道如果图像首先转换为灰度并根据您的算法处理而不是基于3个颜色通道处理,您的方法是否仍然有效?这会以某种方式加速脚本吗?我尝试转换您的代码,但目前不是很成功。
    猜你喜欢
    • 2017-10-28
    • 1970-01-01
    • 2021-05-31
    • 2015-10-05
    • 2020-06-24
    • 2023-04-02
    • 2021-10-12
    • 1970-01-01
    • 2018-06-18
    相关资源
    最近更新 更多