2012-05-28 2 views
11

cv :: Mat 구조체에 저장된 2 쿼터니언을 곱하고 싶습니다. 나는 가능한 한 효율적으로 기능을 원한다. 지금까지 다음 코드를 가지고 있습니다 :cv :: Mat를 이용한 효율적인 C++ 쿼터니언 곱

/** 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 
} 

이것이 OpenCV에서 가장 빠른 방법입니까? 고정 소수점 산술을 사용하면 가장 빠를까요?

+3

16 개의 곱셈과 12 개의 덧셈 - 나에게 개선의 여지가별로없는 것 같습니다. 함수를 인라인으로 만드십시오! 이 'at'호출이 함수 호출이 아닌 (즉 인라인이어야 함) 것이 좋겠습니다. – JohnB

+0

이것은 Mat 클래스의 openCV 멤버입니다. 나는 그것이 매트 엘먼트에 접근하는 가장 빠른 방법이라고 생각하지만 확실하지 않습니다. http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat –

+3

가능한 한 효율적입니까? 동적 메모리 할당과 참조 계산을하는 행렬 클래스를 사소한 배열로 사용하지 마십시오. 그것은 당신의 다른 질문 중 하나와 관련하여 새로운'Matx' 클래스의 완벽한 사용 사례입니다. –

답변

4

this에서 다른 픽셀에 액세스하는 다양한 방법이 설명됩니다. Mat::at 기능은 직접 픽셀 액세스에 비해 약 10 % 느린 것으로 나타났습니다. 아마도 디버그 모드에서 추가 검사가 이루어 졌기 때문일 수 있습니다.

성능면에서는 성능이 좋지 않은 경우 텍스트에서 언급 한 3 가지 방법을 사용하여 메소드를 다시 작성한 다음 자신의 상황에서 가장 적합한 것을 찾는 프로파일을 작성해야합니다.

+0

이 모양이 멋지게 보입니다. –

2

거기에 ARM 벡터 부동 소수점 쿼터니언이 배수했는데 지금은 찾을 수 없습니다. 나는이 SIMD 라이브러리를 찾을 수 : 한 사원 수는 순수한 벡터가 있음을 확인 고려할 수 있도록

Bullet 3D Game Multiphysics Library

0

사원 수는 종종 3D 벡터를 회전하는 데 사용됩니다 (즉, 스칼라 또는 실수 부분이 제로). 이로써 12 곱셈, 8 덧셈/뺄셈 및 1 부호 플립으로 작업을 줄일 수 있습니다.

두 순수 벡터에 대해 쿼터니언 곱하기를 사용하여 도트 및 교차 곱을 동시에 계산할 수 있으므로이 특별한 경우에 대한 테스트도 가치가있을 수 있습니다. 두 쿼터니언 모두 순수 벡터 인 경우 9 곱셈, 5 덧셈/뺄셈 및 1 부호 플립 만 필요합니다.

+0

실제로, 전체 op를 수행하는 루틴을 작성하고 사용하십시오 :'vec_rotated = q * (0, vec) * q.conj()'를 호출하면 두 개의 완전 쿼터니언 제품을 수행하는 것과 비교하여 일부 작업이 저장됩니다 (두 번째 제품에는 항상 실수가 0입니다). 같은 쿼터니언에 의해 많은 벡터를 회전시킬 필요가있는 경우 - 특히 행렬에 저장되는 경우 - 쿼터니온을 3x3 회전 행렬로 변환하고 벡터에서이를 사용하는 것이 빠릅니다. – greggo