2013-04-11 8 views

Antwort

26

Ich werde Sie mit C++ zu übernehmen, aber die Antwort soll das gleiche sein, wenn Sie C oder Python verwenden.

Die Funktion minAreaRect scheint Winkel von -90 bis 0 Grad zu geben, ohne Null, also ein Intervall von [-90, 0].

Die Funktion gibt -90 Grad, wenn das Rechteck, das es ausgibt, nicht gedreht wird, d.h. das Rechteck hat zwei Seiten genau horizontal und zwei Seiten genau vertikal. Wenn sich das Rechteck im Uhrzeigersinn dreht, nimmt der Winkel zu (geht gegen Null). Wenn Null erreicht wird, tickt der von der Funktion vorgegebene Winkel wieder auf -90 Grad.

Also wenn Sie ein langes Rechteck von minAreaRect haben, und es liegt flach, minAreaRect wird den Winkel -90 Grad aufrufen. Wenn Sie das Bild drehen, bis das von minAreaRect angegebene Rechteck perfekt aufrecht steht, wird der Winkel wieder -90 Grad angezeigt.

Ich wusste eigentlich nichts davon (Ich zögerte aus meinem OpenCV-Projekt, um herauszufinden, wie es funktioniert: /). Wie auch immer, hier ist ein OpenCV-Programm, das minAreaRect zeigt, wenn ich es klar genug schon nicht erklärt haben:

#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; 
} 

Auf diese Weise können Sie leicht erkennen, wie der Winkel und die Form, eines manuell gezeichneten Rechteck auf die minAreaRect Interpretation vergleicht der das gleiche Rechteck.

+0

Geck Sie ein ernsthaftes Juwel sind. Danke :) –

+0

Kein Problem :) OpenCV's Dokumentation scheint viele wichtige Details zu vermissen –

+0

Nur noch eine Frage, wie kann ich eine 0-360 Grad Transformation von routedrect bekommen, wenn es nur Engel zwischen -90, -1 gibt?Und ja, opencv ist möglicherweise besser auf Dokumentation, wenn Sie in Code oder ihre Beispiele graben –

10

Verbesserung auf die Antwort von @ Adam Goodwin will ich meinen kleinen Code hinzufügen, dass das Verhalten ein wenig verändert:

ich den Winkel zwischen der längeren Seite und vertikal haben wollte (mir ist es die natürliche Art und Weise zu drehen Rechtecke zu denken):

Behold my Paint skills

Wenn Sie das gleiche benötigen, nur diesen Code verwenden:

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

es in Aktion zu sehen, legen Sie sie in Adam Goodwins Code:

printf("Angle given by minAreaRect: %7.2f\n", calculatedRect.angle); 
printAngle(calculatedRect); 
printf("---\n"); 
+0

wenn ich meine routedrect.angle in 360 Grad überprüfen möchte. Wie können wir das machen. da Ihr aktueller Code mit 0-180 Grad mit Vertikal arbeitet. Irgendein Hinweis? –

1

Nach Experiment, finde ich, dass, wenn die lange Seite in der linken Seite des unteren Punktes ist, der Winkelwert zwischen der Längsseite und Y + Achse , aber wenn sich die lange Seite rechts vom unteren Punkt befindet, liegt der Winkel zwischen der langen Seite und der X + -Achse. So verwende ich den Code wie diese (Java):

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

Der Winkel ist von 0 bis 180.

Verwandte Themen