37

从 MinAreaRect 的函数中,它是否返回 0-360 度范围内的角度?我不确定,因为我有一个方向为 90 度左右的对象,但我一直得到 -1 或 -15 度。这可能是openCV错误吗?

非常感谢任何指导。

谢谢

4

5 回答 5

48

我假设您使用的是 C++,但如果您使用的是 C 或 Python,答案应该是相同的。

该函数minAreaRect似乎给出了从 -90 到 0 度的角度,不包括零,因此区间为 [-90, 0)。

如果它输出的矩形没有旋转,则该函数给出-90 度,即矩形有两条完全水平的边和两条完全垂直的边。随着矩形顺时针旋转,角度增加(趋向于零)。当达到零时,函数给出的角度再次回到 -90 度。

因此,如果您从 有一个长矩形minAreaRect,并且它平躺,minAreaRect则将角度称为 -90 度。如果您旋转图像直到给出的矩形minAreaRect完全直立,那么角度将再次显示 -90 度。

我实际上对此一无所知(我拖延了我的 OpenCV 项目以了解它是如何工作的:/)。无论如何,这是一个 OpenCV 程序,它演示了minAreaRect我是否还没有足够清楚地解释它:

#include <stdio.h>

#include <opencv\cv.h>
#include <opencv\highgui.h>

using namespace cv;

int main() {
    float angle = 0;
    Mat image(200, 400, CV_8UC3, Scalar(0));
    RotatedRect originalRect;
    Point2f vertices[4];
    vector<Point2f> vertVect;
    RotatedRect calculatedRect;

    while (waitKey(5000) != 27) {
        // Create a rectangle, rotating it by 10 degrees more each time.
        originalRect = RotatedRect(Point2f(100,100), Size2f(100,50), angle);

        // Convert the rectangle to a vector of points for minAreaRect to use.
        // Also move the points to the right, so that the two rectangles aren't
        // in the same place.
        originalRect.points(vertices);
        for (int i = 0; i < 4; i++) {
            vertVect.push_back(vertices[i] + Point2f(200, 0));
        }

        // Get minAreaRect to find a rectangle that encloses the points. This
        // should have the exact same orientation as our original rectangle.
        calculatedRect = minAreaRect(vertVect);

        // Draw the original rectangle, and the one given by minAreaRect.
        for (int i = 0; i < 4; i++) {
            line(image, vertices[i], vertices[(i+1)%4], Scalar(0, 255, 0));
            line(image, vertVect[i], vertVect[(i+1)%4], Scalar(255, 0, 0));
        }
        imshow("rectangles", image);

        // Print the angle values.
        printf("---\n");
        printf("Original angle:             %7.2f\n", angle);
        printf("Angle given by minAreaRect: %7.2f\n", calculatedRect.angle);
        printf("---\n");

        // Reset everything for the next frame.
        image = Mat(200, 400, CV_8UC3, Scalar(0));
        vertVect.clear();
        angle+=10;
    }

    return 0;
}

这使您可以轻松查看手动绘制的矩形的角度和形状minAreaRect与相同矩形的解释的比较。

于 2013-04-16T16:55:38.277 回答
26

改进@Adam Goodwin 的答案我想添加我的小代码来稍微改变行为:

我想要长边和垂直之间的角度(对我来说,这是考虑旋转矩形的最自然的方式):

看我的绘画技巧

如果您需要相同的内容,只需使用以下代码:

void printAngle(RotatedRect calculatedRect){
    if(calculatedRect.size.width < calculatedRect.size.height){
        printf("Angle along longer side: %7.2f\n", calculatedRect.angle+180);
    }else{
        printf("Angle along longer side: %7.2f\n", calculatedRect.angle+90);
    }
}

要查看它的实际效果,只需将其插入 Adam Goodwins 代码中:

printf("Angle given by minAreaRect: %7.2f\n", calculatedRect.angle);
printAngle(calculatedRect);
printf("---\n");
于 2014-01-29T10:09:29.263 回答
4

经过大量实验,我发现矩形方向和输出角度之间的关系minAreaRect()。可以概括为下图

在此处输入图像描述

下面的描述假设我们有一个长宽不相等的矩形,即它不是正方形。

如果矩形垂直放置(宽度 < 高度),则检测到的角度为 -90。如果矩形水平放置,则检测到的角度也是 -90 度。

如果矩形的顶部在第一象限,则检测到的角度随着矩形从水平位置旋转到垂直位置而减小,直到检测到的角度变为-90度。在第一象限中,检测到的矩形的宽度大于其高度。

如果检测到的矩形的顶部位于第二象限,则角度会随着矩形从垂直位置旋转到水平位置而减小。但是第二象限和第一象限是有区别的。如果矩形接近垂直位置但尚未处于垂直位置,则其角度接近 0。如果矩形接近水平位置但尚未处于水平位置,则其角度接近 -90 度

这里的这篇文章也很好地解释了这一点。

于 2018-12-19T13:45:33.417 回答
4

经过实验,我发现如果长边在底点的左边,角度值在长边和Y+轴之间,但是如果长边在底点的右边,角度值在长边和Y+轴之间边和 X+ 轴。所以我使用这样的代码(java):

       rRect = Imgproc.minAreaRect(mop2f);
       if(rRect.size.width<rRect.size.height){
            angle = 90 -rRect.angle;
        }else{
            angle = -rRect.angle;
        }

角度从 0 到 180。

于 2016-05-05T09:26:53.270 回答
0

这取决于 opencv 的版本,至少对于 Python 而言。

对于 opencv-python='4.5.4.60'。该角度是正 x 轴与轴逆时针旋转时遇到的第一条线之间的角度。以下是要摘录的代码。

import cv2
import numpy as np

box1 = [[0, 0], [1, 0], [1, 2], [0, 2]]
cv2.minAreaRect(np.asarray(box1))  # angel = 90.0

box2 = [[0, 0], [2, 0], [2, 1], [0, 1]]
cv2.minAreaRect(np.asarray(box2))  # angel = 90.0

box3 = [[0, 0], [2**0.5, 2**0.5], [0.5*2**0.5, 1.5*2**0.5], [-0.5*2**0.5, 0.5*2**0.5]]
cv2.minAreaRect(np.asarray(box3, dtype=np.float32))  # angle = 44.999

box4 = [[0, 0], [-2**0.5, 2**0.5], [-0.5*2**0.5, 1.5*2**0.5], [0.5*2**0.5, 0.5*2**0.5]]
cv2.minAreaRect(np.asarray(box4, dtype=np.float32))  # angle = 45.0

box5 = [[0, 0], [-0.5*2**0.5, 0.5*2**0.5], [-2**0.5, 0], [-0.5*2**0.5, -0.5*2**0.5]]
cv2.minAreaRect(np.asarray(box5, dtype=np.float32))  # angle = 45.0

对于 opencv-python='3.4.13.47'。该角度是正 x 轴和轴顺时针旋转时遇到的第一条线之间的角度。以下是要摘录的代码。

import cv2
import numpy as np

box1 = [[0, 0], [1, 0], [1, 2], [0, 2]]
cv2.minAreaRect(np.asarray(box1))  # angel = -90.0

box2 = [[0, 0], [2, 0], [2, 1], [0, 1]]
cv2.minAreaRect(np.asarray(box2))  # angel = -90.0

box3 = [[0, 0], [2**0.5, 2**0.5], [0.5*2**0.5, 1.5*2**0.5], [-0.5*2**0.5, 0.5*2**0.5]]
cv2.minAreaRect(np.asarray(box3, dtype=np.float32))  # angle = -44.999

box4 = [[0, 0], [-2**0.5, 2**0.5], [-0.5*2**0.5, 1.5*2**0.5], [0.5*2**0.5, 0.5*2**0.5]]
cv2.minAreaRect(np.asarray(box4, dtype=np.float32))  # angle = -45.0

box5 = [[0, 0], [-0.5*2**0.5, 0.5*2**0.5], [-2**0.5, 0], [-0.5*2**0.5, -0.5*2**0.5]]
cv2.minAreaRect(np.asarray(box5, dtype=np.float32))  # angle = -45.0
于 2021-12-20T05:48:04.657 回答