Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
130 views
in Technique[技术] by (71.8m points)

python - Angle of a line using OpenCV

I have these two Images

Vertical white line on a black background

Horizontal white line on a black background

I used the following code to get the angle of the line

import numpy as np
import cv2
x = cv2.imread('ver.png') 
cv_image = cv2.cvtColor(x, cv2.COLOR_RGB2GRAY)
ret, thresh = cv2.threshold(cv_image,70,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
recta = cv2.minAreaRect(contours[0])
center_x, center_y, angle = recta
print (angle)

but the printed angle value is the same for both images which is -90

it is mentioned in the documentation that the cv2.minAreaRect() returns as following: ( top-left corner(x,y), (width, height), angle of rotation )

but for me, it only returns (center-x, center-y, angle)

btw: I wanna write a code for a line follower drone so that I need to know the angle of the detected line so I adjust my drone according to it

question from:https://stackoverflow.com/questions/66051291/angle-of-a-line-using-opencv

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

minAreaRect prints -90 for both because it defines the rectangle differently for those lines (you can swap the width and height and end up with the same rectangle). If you need something that can distinguish between them then you can take the rectangle corners and find the longer side. You can use that line to calculate an angle.

The following code will distinguish between the two (0 degrees for horizontal, -89.999999 degrees for vertical). It should be bound between [-90, 90] degrees (relative to the bottom of the screen).

import numpy as np
import cv2
import math

# 2d distance
def dist2D(one, two):
    dx = one[0] - two[0];
    dy = one[1] - two[1];
    return math.sqrt(dx*dx + dy*dy);

# angle between three points (the last point is the middle)
def angle3P(p1, p2, p3):
    # get distances
    a = dist2D(p3, p1);
    b = dist2D(p3, p2);
    c = dist2D(p1, p2);

    # calculate angle // assume a and b are nonzero
    # (law of cosines)
    numer = c**2 - a**2 - b**2;
    denom = -2 * a * b;
    if denom == 0:
        denom = 0.000001;
    rads = math.acos(numer / denom);
    degs = math.degrees(rads);

    # check if past 90 degrees
    return degs;

# get the rotated box
x = cv2.imread('horizontal.png') 
cv_image = cv2.cvtColor(x, cv2.COLOR_RGB2GRAY)
ret, thresh = cv2.threshold(cv_image,70,255,cv2.THRESH_BINARY)
_, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
recta = cv2.minAreaRect(contours[0])
center_x, center_y, angle = recta

# get the corners
box = cv2.boxPoints(recta)
box = np.int0(box)

# choose the first point
root = box[0];

# find the longer side
end = None;
one = box[-1];
two = box[1];
if dist2D(one, root) > dist2D(two, root):
    end = one;
else:
    end = two;

# take the left-most point
left_point = None;
right_point = None;
if end[0] < root[0]:
    left_point = end;
    right_point = root;
else:
    left_point = root;
    right_point = end;

# calculate the angle [-90, 90]
offshoot = [left_point[0] + 100, left_point[1]];
angle = angle3P(right_point, offshoot, left_point);
if left_point[1] > right_point[0]:
    angle = -angle;
print(angle);

Edit:

Woops, I got my orientation mixed up. I edited the code, now it should be from [-90, 90] degrees.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...