2012-05-28 4 views
11

Chcę pomnożyć 2 kwaterunki, które są przechowywane w strukturze cv :: Mat. Chcę, aby funkcja była jak najbardziej efektywna. Mam następujący kod do tej pory:Efektywne mnożenie kwaternionów C++ za pomocą 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 
} 

Czy to najszybszy sposób z OpenCV? Czy byłoby to najszybsze z arytmetyką o stałym punkcie?

+3

16 multiplikacji i 12 dodatków - wydaje mi się, że nie mam wiele do zrobienia. Włącz funkcję inline! Mam nadzieję, że te wywołania "at" nie są wywołaniami funkcji (tj. Powinny być wbudowane). – JohnB

+0

Jest to element openCV klasy Mat. Myślę, że jest to najszybsza metoda, aby uzyskać dostęp do Mat elment, ale nie jestem pewien. http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat –

+3

Jak najbardziej efektywny? Nie używaj klasy macierzy, która dynamicznie przydziela alokację pamięci i liczenie odwołań do czegoś tak banalnego jak tablica czteroskładnikowa. Jest to idealny przypadek użycia dla nowej klasy 'Matx', w odniesieniu do jednego z twoich innych pytań. –

Odpowiedz

4

W samouczku this uwzględniono różne sposoby dostępu do różnych pikseli. Stwierdzono, że funkcja Mat::at jest o około 10% wolniejsza w porównaniu do bezpośredniego dostępu do pikseli, prawdopodobnie z powodu dodatkowej kontroli trybu debugowania.

Jeśli jesteś naprawdę gotowy do wykonania, powinieneś przepisać swoją metodę za pomocą 3 różnych metod wymienionych w tekście, a następnie wybrać profil, który najlepiej pasuje do Twojej sytuacji.

+0

to wygląda ładnie, będę musiał wyglądać –

0

Quaternions są często używane do obracania wektorów 3D więc może warto rozważyć sprawdzenie, że jeden quaternion jest czystym wektor (tj skalarne lub część rzeczywista jest równa zero). Może to zmniejszyć twoją pracę do 12 mnożeń, 8 dodawania/odejmowania i jednego przewracania znaku.

Można również użyć mnożenia kwaternionowego na dwóch czystych wektorach, aby obliczyć ich produkty punktowe i krzyżowe jednocześnie, więc testowanie w tym szczególnym przypadku również może być tego warte. Jeśli oba zdania są czystymi wektorami, potrzebujesz tylko 9 mnożeń, 5 dodawania/odejmowania i jednego przewracania znaku.

+0

Rzeczywiście, lub napisać i używać rutyny, która wykonuje całą operację: 'vec_rotated = q * (0, vec) * q.conj() 'w jednym wywołaniu funkcji, niektóre operacje są zapisywane w porównaniu do wykonywania dwóch pełnych produktów kwaterunkowych (drugi prod zawsze ma zerową rzeczywistą część). Jeśli chcesz obrócić wiele wektorów o to samo kwaternionu - zwłaszcza jeśli są one przechowywane w macierzy - szybciej przekształcasz kwaternion na macierz obrotu 3x3 i używasz tego na wektorach. – greggo