Вы можете найти угол, преобразовав свое изображение в двоичное (cv2.threshold(cv2.THRESH_BINARY)
), а затем выполнить поиск контуров.
Когда вы находите свой контур (линию), вы можете разместить линию на вашем контуре cv2.fitLine()
и получить две точки своей линии. Моя математика не очень хорошая, но я думаю, что в линейном уравнении формула имеет вид f(x) = k*x + n
, и вы можете получить k
из этих двух точек (k = (y2-y1)/(x2-x1)
) и, наконец, угол phi = arctan(k)
. (Если я не прав, пожалуйста, исправьте это)
Вы также можете использовать повернутый ограничивающий прямоугольник - cv2.minAreaRect()
- который уже возвращает угол прямоугольника (rect = cv2.minAreaRect()
-> rect[2]
). Надеюсь, поможет. Ура!
Вот пример кода:
import cv2
import numpy as np
import math
img = cv2.imread('angle.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, threshold = cv2.threshold(gray,170,255,cv2.THRESH_BINARY)
im, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
for c in contours:
area = cv2.contourArea(c)
perimeter = cv2.arcLength(c, False)
if area < 10001 and 100 < perimeter < 1000:
# first approach - fitting line and calculate with y=kx+n --> angle=tan^(-1)k
rows,cols = img.shape[:2]
[vx,vy,x,y] = cv2.fitLine(c, cv2.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)
(x1, y1) = (cols-1, righty)
(x2, y2) = (0, lefty)
k = (y2-y1)/(x2-x1)
angle = math.atan(k)*180/math.pi
print(angle)
#second approch - cv2.minAreaRect --> returns center (x,y), (width, height), angle of rotation )
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img,[box],0,(0,0,255),2)
print(rect[2])
cv2.imshow('img2', img)
Исходное изображение:
Выход:
-3,8493663478518627
-3,7022125720977783