Как мне удалить шум на этом изображении с помощью OpenCV? - PullRequest
1 голос
/ 10 марта 2020

Я пытаюсь использовать cv2.HoughLines, чтобы определить угол наклона слов в этом изображении .
Однако после обнаружения края в явно слишком много шума .

Я пытался использовать cv2.medianBlur для удаления шума.
Тем не менее, еще больше шума .

Это означает, что я не могу установить пороговое значение минимальной длины строки для грубого преобразования.

На какие другие функции я должен смотреть?

Изображение:
enter image description here

После обнаружения края:
enter image description here

Редактировать: После помощи 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

``

1 Ответ

0 голосов
/ 10 марта 2020

Полезным способом устранения «шума» перед использованием обнаружения края является применение порога, который преобразует изображение из градаций серого в двоичное изображение.

Найти правильный порог (автоматически) не всегда легко.
Я вручную установил пороговое значение равным 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)

Результат:

enter image description here


Решение 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()

Результат:
enter image description here

angle = -21.801406860351562
angle = -21.44773292541504
angle = -21.370620727539062
angle = -21.801406860351562
angle = -22.520565032958984
angle = -22.56700897216797
angle = -23.198591232299805
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...