首页 > 解决方案 > 使用 OpenCV 的直线角度

问题描述

我有这两张图片

黑色背景上的垂直白线

黑色背景上的水平白线

我使用以下代码来获取线的角度

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)

但是两个图像的打印角度值相同,即 -90

文档中提到cv2.minAreaRect() 返回如下:(左上角(x,y),(宽度,高度),旋转角度)

但对我来说,它只返回 (center-x, center-y, angle)

顺便说一句:我想为线跟随无人机编写代码,这样我需要知道检测到的线的角度,所以我根据它调整我的无人机

标签: pythonopencvimage-processingcomputer-vision

解决方案


minAreaRect 为两者都打印 -90,因为它为这些线定义了不同的矩形(您可以交换宽度和高度并最终得到相同的矩形)。如果您需要可以区分它们的东西,那么您可以取矩形角并找到较长的边。您可以使用该线来计算角度。

以下代码将区分两者(水平为 0 度,垂直为 -89.999999 度)。它应该在 [-90, 90] 度之间(相对于屏幕底部)。

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);

编辑:

糟糕,我把方向搞混了。我编辑了代码,现在应该是 [-90, 90] 度。


推荐阅读