web-dev-qa-db-ja.com

MinAreaRectの角度-返される角度が不明

MinAreaRectの関数から、0〜360度の範囲の角度を返しますか?私は90度程度の向きのオブジェクトを持っているので確信がありませんが、-1度または-15度を取得し続けます。これはopenCVエラーでしょうか?

どんなガイダンスも大歓迎です。

ありがとう

29
user349026

私はあなたがC++を使用していると仮定しますが、CまたはPythonを使用している場合の答えは同じでなければなりません。

関数minAreaRectは、0を含まない-90〜0度の範囲の角度を与えるため、[-90、0)の間隔になります。

この関数は、出力する四角形が回転していない場合、つまり、四角形の2つの辺が正確に水平で、2つの辺が正確に垂直の場合、-90度を与えます。長方形が時計回りに回転すると、角度が増加します(ゼロに向かっていきます)。ゼロに達すると、関数によって指定された角度が再び-90度に戻ります。

したがって、minAreaRectからの長い長方形があり、それが平らに横たわっている場合、minAreaRectは角度を-90度と呼びます。 minAreaRectで指定された長方形が完全に直立するまで画像を回転させると、角度は再び-90度になります。

私は実際にはこれを知りませんでした(OpenCVプロジェクトから先延ばしして、どのように機能するかを調べました:/)。とにかく、ここで明確に説明していない場合にminAreaRectを示すOpenCVプログラムを次に示します。

#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解釈とどのように比較されるかを簡単に確認できます。

39
Adam Goodwin

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

実験後、長辺が下のポイントの左にある場合、角度値は長辺とY +軸の間にありますが、長辺が下のポイントの右にある場合、角度値は側面とX +軸。だから私はこのようなコードを使用します(Java):

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

角度は0〜180です。

3
silentteen

多くの実験の後、長方形の向きとminAreaRect()の出力角度との関係を見つけました。次の図に要約できます。

enter image description here

次の説明では、高さと幅の長さが等しくない長方形、つまり正方形ではないことを前提としています。

長方形が垂直にある場合(幅<高さ)、検出される角度は-90です。長方形が水平にある場合、検出される角度も-90度です。

長方形の上部が第1象限にある場合、検出された角度が-90度になるまで、長方形が水平位置から垂直位置に回転すると、検出された角度は減少します。最初の象限では、検出された長方形の幅はその高さよりも長くなっています。

検出された長方形の上部が第2象限にある場合、長方形が垂直位置から水平位置に回転するにつれて角度が減少します。 しかし、第2象限と第1象限の間には違いがあります。長方形が垂直位置に近づくが垂直位置にない場合、その角度は0に近づきます。長方形が水平位置に近づくが水平位置にない場合、その角度は-90度に近づきます

この投稿 here もこれを説明するのに適しています。

2
jdhao