2010-09-14 29 views
12

Estoy trabajando en una aplicación básica de realidad aumentada en Android. Lo que hice hasta ahora es detectar un cuadrado con opencv y luego usar cvFindExtrinsicCameraParams2() Calculé un vector de rotación y traducción. Para esto usé 4 puntos de objeto, que son solo las esquinas de un cuadrado alrededor (0,0,0) y las 4 esquinas del cuadrado en la imagen.¿Cómo usar un vector de traducción y rotación de OpenCV con OpenGL ES en Android?

Esto me da una matriz de rotación y traducción bastante buena. También calculé la matriz de rotación con cvRodrigues2() ya que usar esto es más fácil que el vector de rotación. Siempre que los use para dibujar algunos puntos en la imagen todo funciona bien. Sin embargo, mi siguiente paso es pasar estos vectores y la matriz a Java y luego usarlos con OpenGL para dibujar un cuadrado en un OpenGLView. El cuadrado debe estar exactamente alrededor del cuadrado en la imagen que se muestra detrás de OpenGLView.

Mi problema es que no puedo encontrar la forma correcta de usar la matriz de rotación y el vector de traducción en OpenGL. Empecé con exactamente los mismos puntos de objeto que usé para las funciones de openCV. Luego apliqué la matriz de rotación y el vector de traducción prácticamente de cualquier manera que pudiera pensar. Lamentablemente, ninguno de estos enfoques produce un resultado que, de todos modos, esté cerca de lo que esperaba. ¿Alguien puede decirme cómo usarlos correctamente?

Hasta ahora, los resultados "más cercanos" que he obtenido han sido al multiplicar aleatoriamente toda la matriz con -1. Pero la mayoría de las veces los cuadros aún se ven invertidos o girados en el espejo por 180 grados. Así que supongo que fue solo un golpe de suerte, pero no el enfoque correcto.

+0

Quizás necesite [transponer] (http://opencv.willowgarage.com/wiki/Posit) algo. – genpfault

Respuesta

10

Bien después de algunas pruebas más finalmente logré ponerlo a funcionar. Si bien no lo entiendo ... sí funciona. Para cualquiera que necesite hacer esto en el futuro aquí está mi solución.

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

Como genpfault dijo en su comentario todo lo que ha de ser incorporada desde OpenGL OpenGL ya necesita una orden de la columna-principal. (Gracias por el comentario, ya vi esa página anteriormente). Además, el ángulo de rotación y y z, así como la traducción yyz, deben multiplicarse por -1. Esto es lo que encuentro un poco raro. ¿Por qué solo esos y no los valores x también?

Esto funciona como debería, supongo. Pero las esquinas no coinciden exactamente. Supongo que esto es causado por algunas configuraciones incorrectas de OpenGLView. Entonces, aunque todavía no estoy 100% satisfecho con mi solución, supongo que es la respuesta a mi pregunta.

+0

+1. Muchas gracias por esta respuesta! ¡También lo encontré útil! ¡Aclamaciones! – coder9

+1

¿Es esta la matriz ModelView o la matriz de proyección? –

+4

necesitaba voltear yyz porque abre las vistas GL hacia abajo del eje -z y define su origen en la esquina inferior izquierda, openCV tiene su origen en la parte superior izquierda yz es muy probable que sea positivo. – Hammer

2

¡El método de Pandoro realmente funciona! En caso de que alguien se pregunte "cómo convertir el vector de rotación en una matriz de rotación", así es como lo hice. Por cierto, los he usado en OpenGL 2, no en 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}; 

¡Buena suerte!

Cuestiones relacionadas