Полезным способом устранения «шума» перед использованием обнаружения края является применение порога, который преобразует изображение из градаций серого в двоичное изображение.
Найти правильный порог (автоматически) не всегда легко.
Я вручную установил пороговое значение равным 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