简体   繁体   English

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

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

I'm trying to use cv2.HoughLines to identify the skew angle of the words in this image .我正在尝试使用cv2.HoughLines来识别此图像中单词的倾斜角度。
However, after edge detection, it clearly has too much noise .然而,在边缘检测之后,它显然有太多的噪声

I've tried using cv2.medianBlur to remove the noise.我试过使用cv2.medianBlur去除噪音。
However, there is even more noise .然而,还有更多的噪音

This means that I'm unable to set the minimum line length threshold for hough transform.这意味着我无法为霍夫变换设置最小线长阈值。

What other functions should I be looking at?我还应该关注哪些其他功能?

Image:图片:
在此处输入图片说明

After edge detection:边缘检测后:
在此处输入图片说明

Edit: After Rotem's help, my code now identifies images with skew angles between 90 to -90 degrees including 90 but excluding -90.编辑:在 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

``

A useful way for removing the "noise", before using edge detection is applying a threshold that converts the image from Grayscale to binary image.在使用边缘检测之前去除“噪声”的一种有用方法是应用阈值,将图像从灰度图像转换为二值图像。

Finding the correct threshold (automatically) is not always an easy task.找到正确的阈值(自动)并不总是一件容易的事。
I manually set the threshold value to 50.我手动将阈值设置为 50。

Solution using HoughLinesP code sample:使用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)

Result:结果:

在此处输入图片说明


The HoughLines solution is not so robust. HoughLines解决方案不是那么健壮。
I suggest another solution using findContours :我建议使用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()

Result:结果:
在此处输入图片说明

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

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

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