我应该如何使用 OpenCV 去除此图像中的噪声?

How should I remove noise in this image using OpenCV?

我正在尝试使用 cv2.HoughLines 来识别此 image 中单词的倾斜角度。
然而,在边缘检测之后,它clearly has too much noise。

我试过使用 cv2.medianBlur 来消除噪音。
但是,有even more noise。

这意味着我无法设置霍夫变换的最小线长度阈值。

我还应该查看哪些其他功能?

图片:

边缘检测后:

编辑:在 Rotem 的帮助下,我的代码现在可以识别倾斜角度在 90 到 -90 度之间的图像,包括 90 度但不包括 -90 度。

import numpy as np
import imutils
import math
import pytesseract

img = cv2.imread('omezole.jpg')

resized = imutils.resize(img, width=300)
gray = cv2.cvtColor(resized,cv2.COLOR_BGR2GRAY)
th3 = cv2.threshold(gray, 80, 255, cv2.THRESH_BINARY_INV)[1]
minLineLength = 50
maxLineGap = 3
lines = cv2.HoughLinesP(th3, rho=1, theta=np.pi/180, threshold=100, minLineLength=minLineLength, maxLineGap=maxLineGap)
colLineCopy = cv2.cvtColor(th3,cv2.COLOR_GRAY2BGR)

#Draw but remove all vertical lines, add corresponding angle to ls
ls = []
for line in lines:

    if line is None:
        angle = 0
    else:
        x1, y1, x2, y2 = line[0].tolist()
        print(line)
        #check for vertical lines since you can't find tan90
        if (x2-x1==0):
            ls.append(-90)
        else:
            ls.append((math.degrees(math.atan((y2-y1)/(x2-x1)))))
            cv2.line(colLineCopy, (x1,y1), (x2,y2), (0,0,250), 2)

#special case of strictly vertical words, if more than 0.2 of the lines are vertical assume, words are vertical
if ls.count(-90)>len(ls)//5:
    angle = 90
else:
    for angle in ls:
        if angle < -80:
            ls.remove(angle)
    angle = sum(ls)/len(ls)

rotated = imutils.rotate_bound(resized, -angle)
cv2.imshow("HoughLinesP", colLineCopy)
cv2.imshow("rotated", rotated)

gray = cv2.cvtColor(rotated, cv2.COLOR_BGR2GRAY)
threshINV  = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV)[1]

cv2.imshow("final", threshINV)
#Run OCR
pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
custom_config = r'--psm 11'
print(pytesseract.image_to_string(threshINV, config = custom_config))
cv2.waitKey(0)
cv2.destroyAllWindows

``

在使用边缘检测之前移除 "noise" 的一种有用方法是应用将图像从灰度图像转换为二值图像的阈值。

(自动)找到正确的阈值并不总是一件容易的事。
我手动将阈值设置为50。

使用 HoughLinesP 代码示例的解决方案:

import numpy as np
import cv2

# Read input image
img = cv2.imread('omezole.jpg')

# Convert from RGB to Grayscale.
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Apply threshold - all values below 50 goes to 0, and values above 50 goes to 1.
ret, thresh_gray = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY)


# https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html
edges = cv2.Canny(thresh_gray, 50, 150, apertureSize = 3)


minLineLength = 100
maxLineGap = 5
lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=100, minLineLength=minLineLength, maxLineGap=maxLineGap)

# Draw lines
for line in lines:
    x1, y1, x2, y2 = line[0].tolist()
    cv2.line(img, (x1,y1), (x2,y2), (0,255,0), 2)

cv2.imwrite('houghlines.png',img)

结果:


HoughLines 解决方案不太可靠。
我建议使用 findContours 的另一种解决方案:

img = cv2.imread('omezole.jpg')

# Inverse polarity:
thresh_gray = 255 - thresh_gray;

# Use "open" morphological operation to remove some rough edges
thresh_gray = cv2.morphologyEx(thresh_gray, cv2.MORPH_OPEN, np.ones((5, 5)))


# Find contours over thresh_gray
cnts = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]

# Iterate contours
for c in cnts:
    # Only if contour area is large enough:
    if cv2.contourArea(c) > 2000:
        rect = cv2.minAreaRect(c)
        box = cv2.boxPoints(rect)
        # convert all coordinates floating point values to int
        box = np.int0(box)
        cv2.drawContours(img, [box], 0, (0, 255, 0), thickness=2)
        angle = rect[2]
        print('angle = ' + str(angle))

cv2.imwrite('findcontours.png', img)

# Show result (for testing).
cv2.imshow('thresh_gray', thresh_gray)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

angle = -21.801406860351562
angle = -21.44773292541504
angle = -21.370620727539062
angle = -21.801406860351562
angle = -22.520565032958984
angle = -22.56700897216797
angle = -23.198591232299805