2010-09-14 7 views
12

Pracuję nad podstawową aplikacją rozszerzonej rzeczywistości na Androida. To, co dotychczas zrobiłem, to wykrycie kwadratu z opencv, a następnie użycie cvFindExtrinsicCameraParams2() Obliczyłem wektor obrotu i translacji. Do tego użyłem 4 punktów obiektu, które są tylko rogami kwadratu (0,0,0) i 4 rogami kwadratu na obrazku.Jak używać wektora obrotu i translacji OpenCV z OpenGL ES w systemie Android?

Daje to całkiem niezłą matrycę obrotu i translacji. Obliczyłem także macierz rotacji za pomocą cvRodrigues2(), ponieważ użycie tego jest łatwiejsze niż wektor obrotu. Dopóki używam ich do rysowania punktów na obrazku, wszystko działa dobrze. Następnym krokiem jest przekazanie tych wektorów i macierzy z powrotem do java, a następnie użycie ich z OpenGL do narysowania kwadratu w OpenGLView. Kwadrat powinien znajdować się dokładnie wokół kwadratu na obrazie, który jest wyświetlany za OpenGLView.

Mój problem polega na tym, że nie mogę znaleźć prawidłowego sposobu użycia macierzy obrotu i wektora translacji w OpenGL. Zacząłem od dokładnie tych samych punktów obiektu, które były używane dla funkcji openCV. Następnie zastosowałem matrycę obrotu i wektor translacji w praktycznie dowolny możliwy sposób, jaki mogłem wymyślić. Niestety, żadne z tych podejść nie przynosi rezultatów, które i tak są bliskie oczekiwaniom. Czy ktoś może mi powiedzieć, jak z nich korzystać poprawnie?

Do tej pory "najbliższym" rezultatem, jaki uzyskałem, było losowe pomnożenie całej macierzy przez -1. Ale przez większość czasu kwadraty nadal wyglądają jak lustro odwrócone lub obrócone o 180 stopni. Sądzę więc, że był to tylko szczęśliwy traf, ale nie właściwe podejście.

+0

Może trzeba [przetłumaczyć] (http://opencv.willowgarage.com/wiki/Posit) coś. – genpfault

Odpowiedz

10

Po kilku kolejnych testach udało mi się wreszcie uruchomić. Chociaż tego nie rozumiem ... to działa. Każdy, kto będzie musiał to zrobić w przyszłości, jest moim rozwiązaniem.

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

Jak powiedział genpfault, wszystko musi zostać transponowane, ponieważ OpenGL potrzebuje OpenGL, aby zamówić kolejność kolumn. (Dzięki za komentarz, już tę stronę widziałem wcześniej.) Ponadto kąt obrotu yi z, a także translacja yi z należy pomnożyć przez -1. To jest dla mnie trochę dziwne. Dlaczego tylko te, a nie wartości x też?

To działa tak, jak powinno. Ale rogi nie pasują dokładnie. Przypuszczam, że jest to spowodowane błędnymi konfiguracjami OpenGLView. Więc mimo, że nadal nie jestem w 100% zadowolony z mojego rozwiązania, to myślę, że jest to odpowiedź na moje pytanie.

+0

+1. Wielkie dzięki za tę odpowiedź! Też znalazłem to pomocne! Twoje zdrowie! – coder9

+1

Czy to jest matryca ModelView lub macierz projekcji? –

+4

trzeba było odwrócić y i z, ponieważ otwarte GL wyświetla dół osi -z i określa jej pochodzenie w lewym dolnym rogu, openCV ma swoje pochodzenie w lewym górnym rogu, a z jest najprawdopodobniej dodatnie. – Hammer

2

Metoda Pandoro naprawdę działa! W przypadku, gdy ktoś zastanawia się "jak przekonwertować wektor obrotu na macierz obrotu", oto jak to zrobiłem. Nawiasem mówiąc, użyłem ich w OpenGL 2, a nie 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}; 

Powodzenia!

Powiązane problemy