2012-05-28 37 views
11

Quiero multiplicar 2 cuaterniones, que se almacenan en una estructura cv :: Mat. Quiero que la función sea lo más eficiente posible. Tengo el siguiente código hasta ahora:Eficiente multiplicación de cuaterniones C++ usando cv :: Mat

/** Quaternion multiplication 
* 
*/ 
void multiplyQuaternion(const Mat& q1,const Mat& q2, Mat& q) 
{ 
    // First quaternion q1 (x1 y1 z1 r1) 
    const float x1=q1.at<float>(0); 
    const float y1=q1.at<float>(1); 
    const float z1=q1.at<float>(2); 
    const float r1=q1.at<float>(3); 

    // Second quaternion q2 (x2 y2 z2 r2) 
    const float x2=q2.at<float>(0); 
    const float y2=q2.at<float>(1); 
    const float z2=q2.at<float>(2); 
    const float r2=q2.at<float>(3); 


    q.at<float>(0)=x1*r2 + r1*x2 + y1*z2 - z1*y2; // x component 
    q.at<float>(1)=r1*y2 - x1*z2 + y1*r2 + z1*x2; // y component 
    q.at<float>(2)=r1*z2 + x1*y2 - y1*x2 + z1*r2; // z component 
    q.at<float>(3)=r1*r2 - x1*x2 - y1*y2 - z1*z2; // r component 
} 

¿Es esta la manera más rápida con OpenCV? ¿Sería más rápido usar aritmética de punto fijo?

+3

16 multiplicaciones y 12 incorporaciones: parece que no hay mucho que mejorar. ¡Haga la función en línea! Espero que estas llamadas "a" no sean llamadas a funciones (es decir, que deberían estar en línea). – JohnB

+0

Es un miembro de openCV de la clase Mat. Creo que es el método más rápido para acceder a Mat Matment, pero no estoy seguro. http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat –

+3

¿Tan eficiente como sea posible? En primer lugar, no use una clase de matriz que haga la asignación dinámica de memoria y el recuento de referencias para algo tan trivial como una matriz de cuatro componentes. Ese es exactamente un caso de uso perfecto para la nueva clase 'Matx', en referencia a una de sus otras preguntas. –

Respuesta

4

En this tutorial se cubren diferentes formas de acceder a diferentes píxeles. Se encontró que la función Mat::at era aproximadamente un 10% más lenta en comparación con el acceso directo a píxeles, probablemente debido a la comprobación adicional en el modo de depuración.

Si está realmente mal para el rendimiento, debe volver a escribir su método con los 3 métodos diferentes mencionados en el texto y luego el perfil para encontrar el que mejor se adapte a su situación.

+0

esto se ve bien, voy a echar un vistazo –

2

Hubo un vector de punto flotante de coma flotante multiplicado por ahí que no puedo encontrar ahora. He podido encontrar esta biblioteca SIMD:

Bullet 3D Game Multiphysics Library

0

cuaterniones se utilizan a menudo para girar vectores 3D lo que podríamos considerar la comprobación de que un cuaternión es un vector pura (es decir, el escalar o parte real es cero). Esto podría reducir su trabajo a 12 multiplicaciones, 8 suma/resta y un cambio de signo.

También puede usar la multiplicación de cuaternión en dos vectores puros para calcular sus productos de punto y cruz simultáneamente, por lo que las pruebas para este caso especial también pueden valer la pena. Si ambos cuaterniones son vectores puros, solo necesitas hacer 9 multiplicaciones, 5 agregar/restar y una vuelta de signo.

+0

De hecho, o escribir y usar una rutina que hace toda la operación: 'vec_rotated = q * (0, vec) * q.conj() 'en una llamada de función, algunas operaciones se guardan en comparación con hacer dos productos completos de cuaternión (el segundo prod siempre tiene una parte real cero). Si necesita rotar muchos vectores por el mismo cuaternión, especialmente si están almacenados en una matriz, es más rápido convertir el cuaternión en una matriz de rotación de 3x3 y usarlo en los vectores. – greggo

Cuestiones relacionadas