2013-04-11 9 views
16

Dalle funzioni per MinAreaRect, restituisce angoli nell'intervallo 0-360 gradi? Non sono sicuro di avere un oggetto orientato a 90 gradi o giù di lì, ma continuo ad ottenere -1 o -15 gradi. Potrebbe essere un errore openCV?Angoli MinAreaRect - Incerti sull'angolo restituito

Qualsiasi consiglio molto apprezzato.

Grazie

risposta

26

ho intenzione di assumere che si sta utilizzando C++, ma la risposta dovrebbe essere lo stesso se si sta utilizzando C o Python.

La funzione minAreaRect sembra dare angoli compresi tra -90 e 0 gradi, escluso lo zero, quindi un intervallo di [-90, 0).

La funzione restituisce -90 gradi se il rettangolo che emette non viene ruotato, ovvero il rettangolo ha due lati esattamente orizzontali e due lati esattamente verticali. Mentre il rettangolo ruota in senso orario, l'angolo aumenta (va verso zero). Quando viene raggiunto lo zero, l'angolo dato dalla funzione torna nuovamente a -90 gradi.

Quindi se si dispone di un rettangolo lungo da minAreaRect e si trova in posizione orizzontale, minAreaRect chiamerà l'angolo -90 gradi. Se si ruota l'immagine fino a quando il rettangolo indicato da minAreaRect è perfettamente verticale, l'angolo dirà nuovamente -90 gradi.

In realtà non lo sapevo (ho procrastinato dal mio progetto OpenCV per scoprire come funziona: /). In ogni caso, ecco un programma di OpenCV che dimostra minAreaRect se non l'ho spiegato in chiaro già abbastanza:

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

Questo consente di vedere facilmente come l'angolo, e la forma, di un rettangolo disegnato manualmente paragonabile alla minAreaRect interpretazione lo stesso rettangolo.

+0

Amico sei un gioiello serio. Grazie :) –

+0

Nessun problema :) La documentazione di OpenCV sembra mancare un sacco di dettagli importanti –

+0

Solo un'altra domanda, come posso ottenere una trasformazione di 0-360 gradi da rotatedrect se fornisce solo angeli tra -90, -1?E sì, opencv è forse meglio sulla documentazione quando si scava nel codice o nei loro campioni –

10

Migliorare sulla risposta di @ Adamo Goodwin voglio aggiungere il mio po 'di codice che cambia il comportamento un po':

volevo avere l'angolo tra il lato più lungo e verticale (per me è la più modo naturale di pensare a rettangoli ruotati):

Behold my Paint skills

Se è necessario lo stesso, basta usare questo codice:

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

Per vederlo in azione appena inserirlo nel Adam Codice Goodwins:

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

se voglio controllare il mio rotatedrect.angle a 360 gradi. Come possiamo farlo. dal momento che il codice corrente funzionerà con 0-180 gradi con verticale. Qualche suggerimento? –

1

Dopo esperimento, trovo che se il lato lungo è nella sinistra del punto inferiore, il valore dell'angolo è tra il lato lungo e l'asse Y + , ma se il lato lungo si trova nella parte destra del punto inferiore, il valore dell'angolo è tra il lato lungo e l'asse X +. Così ho utilizzare il codice come questo (java):

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

L'angolo va da 0 a 180.