【问题标题】:How should I remove noise from this thresholded image in OpenCV?我应该如何从 OpenCV 中的这个阈值图像中去除噪声?
【发布时间】:2020-04-14 16:01:19
【问题描述】:

我想删除图片中不属于字母和数字的任何内容。输入图像是这样的:

我尝试过使用canny边缘检测,但它容易受到噪声的影响,并且噪声轮廓很大。由于这个原因,形态学操作也一直不成功。我试过cv2.MORPH_CLOSE,但噪音区域变大了。

我的代码在这里,但到目前为止它在消除噪音方面完全没用:

import imutils

input=cv2.imread("n4.jpg")
resized = imutils.resize(input, width=700)
cv2.imshow("resized",resized)

blur = cv2.GaussianBlur(resized,(7,7),0)
cv2.imshow("blur",blur)

gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
threshINV  = cv2.threshold(gray, 140, 255, cv2.THRESH_BINARY_INV)[1]
cv2.imshow("thresh",threshINV)

e = cv2.Canny(threshINV,20,50)
cv2.imshow("e",e)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4,4))
close = cv2.morphologyEx(threshINV, cv2.MORPH_CLOSE, kernel)
cv2.imshow("close",close)


edged = cv2.Canny(gray, 20, 50)
dilat = cv2.dilate(edged, None, iterations=1)
cv2.imshow("test",dilat)
cv2.waitKey(0)
cv2.destroyAllWindows()

我查看了这个example 和这个other example,但是由于噪声的大小以及我想要保留的轮廓没有可定义的形状,它们无法正常工作。

我也看过这个method,但我再次认为它不会起作用,因为没有整体轮廓可以平滑。

【问题讨论】:

    标签: python opencv image-processing ocr


    【解决方案1】:

    您发布的图片非常具有挑战性。
    我发布的解决方案对于您发布的图片来说太具体了。
    我尽量保持它的一般性,但我不希望它在其他图像上工作得很好。
    您可以使用它来获取更多消除噪音选项的想法。

    解决方案主要基于找到连接的组件并移除较小的组件 - 被认为是噪声。

    我使用pytesseract OCR 来检查结果是否足够干净,可用于 OCR。

    这是代码(请阅读 cmets):

    import numpy as np
    import scipy.signal
    import cv2
    import pytesseract
    
    pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"  # For Windows OS
    
    # Read input image
    input = cv2.imread("n4.jpg")
    
    # Convert to Grayscale.
    gray = cv2.cvtColor(input, cv2.COLOR_BGR2GRAY)
    
    # Convert to binary and invert polarity
    ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    
    # Find connected components (clusters)
    nlabel, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh, connectivity=8)
    
    
    # Remove small clusters: With both width<=10 and height<=10 (clean small size noise).
    for i in range(nlabel):
        if (stats[i, cv2.CC_STAT_WIDTH] <= 10) and (stats[i, cv2.CC_STAT_HEIGHT] <= 10):
            thresh[labels == i] = 0
    
    #Use closing with very large horizontal kernel
    mask = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, np.ones((1, 150)))
    
    # Find connected components (clusters) on mask
    nlabel, labels, stats, centroids = cv2.connectedComponentsWithStats(mask, connectivity=8)
    
    # Find label with maximum area
    # https://stackoverflow.com/questions/47520487/how-to-use-python-opencv-to-find-largest-connected-component-in-a-single-channel
    largest_label = 1 + np.argmax(stats[1:, cv2.CC_STAT_AREA])
    
    # Set to zero all clusters that are not the largest cluster.
    thresh[labels != largest_label] = 0
    
    # Use closing with horizontal kernel of 15 (connecting components of digits)
    mask = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, np.ones((1, 15)))
    
    # Find connected components (clusters) on mask again
    nlabel, labels, stats, centroids = cv2.connectedComponentsWithStats(mask, connectivity=8)
    
    # Remove small clusters: With both width<=30 and height<=30
    for i in range(nlabel):
        if (stats[i, cv2.CC_STAT_WIDTH] <= 30) and (stats[i, cv2.CC_STAT_HEIGHT] <= 30):
            thresh[labels == i] = 0
    
    # Use closing with horizontal kernel of 15, this time on thresh
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, np.ones((1, 15)))
    
    # Use median filter with 3x5 mask (using OpenCV medianBlur with k=5 is removes important details).
    thresh = scipy.signal.medfilt(thresh, (3,5))
    
    # Inverse polarity
    thresh = 255 - thresh
    
    # Apply OCR
    data = pytesseract.image_to_string(thresh, config="-c tessedit"
                                                      "_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-/"
                                                      " --psm 6"
                                                      " ")
    
    print(data)
    
    # Show image for testing
    cv2.imshow('thresh', thresh)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    thresh(干净的图片):

    OCR 结果:EXPO22016/01-2019

    【讨论】:

      猜你喜欢
      • 2017-06-23
      • 1970-01-01
      • 2014-05-22
      • 1970-01-01
      • 2017-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多