MinAreaRect角度 - 不确定返回的角度

时间:2013-04-11 18:26:11

标签: opencv angle

从MinAreaRect的功能来看,它是否会返回0-360度范围内的角度? 我不确定,因为我有一个朝向90度左右的物体,但我一直得到-1或-15度。这可能是openCV错误吗?

非常感谢任何指导。

谢谢

4 个答案:

答案 0 :(得分:35)

我将假设您正在使用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解释的比较。

答案 1 :(得分:20)

改进@Adam Goodwin的答案我想添加一些改变行为的小代码:

我希望在长边和垂直之间有一个角度(对我而言,这是考虑旋转矩形的最自然的方式):

Behold my Paint skills

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

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

答案 2 :(得分:3)

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

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

角度从0到180。

答案 3 :(得分:2)

经过大量实验,我发现矩形方向与minAreaRect()的输出角度之间的关系。可以总结在下图中

enter image description here

以下描述假定我们有一个矩形,其高度和宽度的长度不相等,即它不是正方形。

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

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

如果检测到的矩形的顶部在第二象限中,则随着矩形从垂直位置旋转到水平位置,角度将减小。 但是第二象限和第一象限之间存在差异。如果矩形接近垂直位置但尚未处于垂直位置,则其角度接近0。如果矩形接近水平位置但尚未处于水平位置,则其角度接近-90度

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