2010-09-14 2 views
12

Ich arbeite an einer grundlegenden Augmented-Reality-Anwendung für Android. Was ich bisher gemacht habe ist, ein Quadrat mit opencv zu erkennen und dann cvFindExtrinsicCameraParams2() zu verwenden. Ich berechnete einen Rotations- und Translationsvektor. Dazu habe ich 4 Objektpunkte verwendet, die nur die Ecken eines Quadrats um (0,0,0) und die 4 Ecken des Quadrats im Bild sind.Wie benutzt man einen OpenCV-Dreh- und Übersetzungsvektor mit OpenGL ES in Android?

Das ergibt mir eine ziemlich gute Rotation und Translationsmatrix. Ich habe auch die Rotationsmatrix mit cvRodrigues2() berechnet, da dies einfacher ist als der Rotationsvektor. Solange ich diese verwende, um einige Punkte im Bild zu zeichnen, funktioniert alles gut. Mein nächster Schritt ist jedoch, diese Vektoren und die Matrix zurück an Java zu übergeben und sie dann mit OpenGL zu verwenden, um ein Quadrat in einer OpenGLView zu zeichnen. Das Quadrat sollte genau um das Quadrat in dem Bild sein, das hinter der OpenGLView angezeigt wird.

Mein Problem ist, dass ich nicht die richtige Art der Verwendung der Rotationsmatrix und Übersetzungsvektor in OpenGL finden kann. Ich habe mit genau den gleichen Objektpunkten angefangen wie für die openCV-Funktionen. Dann habe ich die Rotationsmatrix und den Translationsvektor so gut wie möglich angewendet. Leider führt keiner dieser Ansätze zu einem Ergebnis, das in etwa dem entspricht, was ich mir erhofft habe. Kann mir jemand sagen, wie man sie richtig benutzt?

Bis jetzt waren die "nächsten" Ergebnisse, die ich erhalten habe, die zufällige Multiplikation der gesamten Matrix mit -1. Meistens sehen die Quadrate jedoch spiegelverkehrt oder um 180 Grad gedreht aus. Also ich denke, es war nur ein Glückstreffer, aber nicht der richtige Ansatz.

+0

Vielleicht müssen Sie [transpose] (http://opencv.willowgarage.com/wiki/Posit) etwas. – genpfault

Antwort

10

Okay, nach einigen weiteren Tests habe ich es endlich geschafft, es zum Laufen zu bringen. Während ich es nicht verstehe ... es funktioniert. Für alle, die das in Zukunft tun müssen, hier ist meine Lösung.

float rv[3]; // the rotation vector 
float rotMat[9]; // rotation matrix 
float tv[3]; // translation vector. 


rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2]; 
//Convert the rotation vector into a matrix here. 

//Complete matrix ready to use for OpenGL 
float RTMat[] = {rotMat[0], rotMat[3], rotMat[6], 0.0f, 
       rotMat[1], rotMat[4], rotMat[7], 0.0f, 
       rotMat[2], rotMat[5], rotMat[8], 0.0f, 
       tv[0], -tv[1], -tv[2], 1.0f}; 

Wie genpfault sagte in seinem Kommentar alles da OpenGL umgesetzt werden muss, da OpenGL eine Spalte-Großauftrag benötigt. (Danke für den Kommentar, ich habe diese Seite schon früher gesehen.) Außerdem müssen der y- und z-Rotationswinkel sowie die y- und z-Translation mit -1 multipliziert werden. Das finde ich ein bisschen komisch. Warum nur diese und nicht die x-Werte?

Dies funktioniert, wie es sollte ich denke. Aber Ecken stimmen nicht genau überein. Ich vermute, das liegt an einigen falschen openGLView-Konfigurationen. Obwohl ich immer noch nicht 100% glücklich mit meiner Lösung bin, denke ich, es ist die Antwort auf meine Frage.

+0

+1. Vielen Dank für diese Antwort! Ich fand es auch hilfreich! Prost! – coder9

+1

Ist das die ModelView-Matrix oder die Projektionsmatrix? –

+4

Sie mussten y und z spiegeln, weil der offene GL die Achse -z unten abbildet und seinen Ursprung links unten definiert, openCV seinen Ursprung oben links und z höchst wahrscheinlich positiv ist. – Hammer

2

Pandoros Methode funktioniert wirklich! Falls sich jemand fragen sollte, wie man den Rotationsvektor in eine Rotationsmatrix umwandelt, hier ist, wie ich es gemacht habe. Übrigens habe ich diese in OpenGL 2 verwendet, nicht in ES.

// use the rotation vector generated from OpenCV's cvFindExtrinsicCameraParams2() 
float rv[] = {rotation->data.fl[0], rotation->data.fl[1], rotation->data.fl[2] }; 

// use the translation vector generated from OpenCV's cvFindExtrinsicCameraParams2() 
float tv[] = {translation->data.fl[0], translation->data.fl[1], translation->data.fl[2]} ; 

float rm[9]; 
// rotation matrix 
CvMat* rotMat = cvCreateMat (3, 3, CV_32FC1); 

// rotation vectors can be converted to a 3-by-3 rotation matrix 
// by calling cvRodrigues2() - Source: O'Reilly Learning OpenCV 
cvRodrigues2(rotation, rotMat, NULL); 

for(int i=0; i<9; i++){ 
    rm[i] = rotMat->data.fl[i]; 
} 

rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2]; 
//Convert the rotation vector into a matrix here. 

//Complete matrix ready to use for OpenGL 
float RTMat[] = {rm[0], rm[3], rm[6], 0.0f, 
      rm[1], rm[4], rm[7], 0.0f, 
      rm[2], rm[5], rm[8], 0.0f, 
      tv[0], -tv[1], -tv[2], 1.0f}; 

Viel Glück!