简体   繁体   English

我应该如何从 OpenCV 中的这个阈值图像中去除噪声?

[英]How should I remove noise from this thresholded image in OpenCV?

I would like to remove anything that is not part of the letters and numbers in the image.我想删除图像中不属于字母和数字的任何内容。 The input image is as such:输入图像是这样的:

阈值图像

I have tried to apply canny edge detection, but it is susceptible to noise, and the noise contours are quite big.我尝试过应用canny边缘检测,但它容易受到噪声的影响,并且噪声轮廓很大。 Due to this reason, morphological operations have also been unsuccessful.由于这个原因,形态学操作也一直不成功。 I tried cv2.MORPH_CLOSE but the noise areas got bigger.我尝试cv2.MORPH_CLOSE但噪音区域变大了。

My code is here, but it's completely useless as of now in removing noise:我的代码在这里,但到目前为止它在消除噪音方面完全没用:

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()

I've looked at this example and this other example , however they would not work because of the size of the noise and the fact that the contours I would like to keep do not have a definable shape.我已经查看了这个示例另一个示例,但是由于噪声的大小以及我想要保留的轮廓没有可定义的形状,它们无法正常工作。

I've also looked at this method , but again I don't think it will work since there is no overall contour to smooth out.我也看过这种方法,但我再次认为它不会起作用,因为没有整体轮廓可以平滑。

The image you have posted is very challenging.您发布的图像非常具有挑战性。
The solution I am posting is too specific for the image you have posted.我发布的解决方案对于您发布的图像来说太具体了。
I tried to keep it as general as I could, but I don't expect it to work very well on other images.我尽量保持它的一般性,但我不希望它在其他图像上工作得很好。
You may use it for getting ideas for more options for removing noise.您可以使用它来获取更多消除噪音选项的想法。

The solution is mainly based on finding connected components and removing the smaller components - considered to be noise.该解决方案主要基于找到连接的组件并移除较小的组件 - 被认为是噪声。

I used pytesseract OCR for checking if the result is clean enough for OCR.我使用pytesseract OCR 来检查结果对于 OCR 是否足够干净。

Here is the code (please read the comments):这是代码(请阅读评论):

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 (clean image): thresh (干净的图像):
在此处输入图像描述

OCR result: EXPO22016/01-2019 OCR结果: EXPO22016/01-2019

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM