Вопрос по c++ – Эффективное кватернионное умножение C ++ с использованием cv :: Mat

11

Я хочу умножить 2 кватернионов, которые хранятся в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
}

Это самый быстрый способ с OpenCV? Будет ли это быстрее всего с использованием арифметики с фиксированной точкой?

Это член openCV класса Mat. Я думаю, что это самый быстрый способ получить доступ к элементу Mat, но я не уверен.opencv.willowgarage.com/documentation/cpp/… Jav_Rock
ммм, я должен попробовать этот новый класс, спасибо Jav_Rock
16 умножений и 12 сложений - мне кажется, что улучшений не так много. Сделайте функцию встроенной! Я надеюсь, что это "на" вызовы не являются функциональными вызовами (то есть они должны быть встроенными). JohnB
Возможно, стоит установить 4X4 из перемешанных версий q2 и умножить матрицу; своего рода подражать тому, что делает код физики пули. С SSE4 у opencv -should- довольно жесткая матрица умножения. Bobbi Bennett
Максимально эффективно? Не используйте класс матрицы, который выполняет динамическое выделение памяти и подсчет ссылок для чего-то столь же тривиального, как в первую очередь четырехкомпонентный массив. Это идеальный вариант использования для новогоMatx класс, ссылаясь на один из ваших других вопросов. Christian Rau

Ваш Ответ

3   ответа
0

Кватернионы часто используются для поворота трехмерных векторов, поэтому вы можете проверить, является ли один кватернион чистым вектором (т. Е. Скалярная или вещественная часть равна нулю). Это может сократить вашу работу до 12 умножений, 8 сложений / вычитаний и одного переворачивания знака.

Вы также можете использовать умножение кватернионов на двух чистых векторах для одновременного вычисления их точечных и перекрестных произведений, так что тестирование для этого особого случая также может стоить того. Если оба кватерниона являются чистыми векторами, вам нужно всего лишь сделать 9 умножений, 5 сложений / вычитаний и один переворот знака.

Действительно, или напишите и используйте подпрограмму, которая выполняет всю операцию: `vec_rotated = q * (0, vec) * q.conj ()` в одном вызове функции, некоторые операции сохраняются по сравнению с выполнением двух полных продуктов кватерниона (второй Prod всегда имеет нулевую действительную часть). Если вам необходимо повернуть множество векторов на один и тот же кватернион, особенно если они хранятся в матрице, быстрее преобразовать кватернион в матрицу вращения 3х3 и использовать его на векторах.
4

Вэтот В учебнике рассматриваются разные способы доступа к разным пикселям.Mat::at Было установлено, что функция работает примерно на 10% медленнее по сравнению с прямым доступом к пикселям, возможно, из-за дополнительной проверки в режиме отладки.

Если вы действительно настроены на снижение производительности, вам следует переписать свой метод с помощью 3 различных методов, упомянутых в тексте, а затем в профиле, чтобы найти тот, который лучше всего подходит для вашей ситуации.

это выглядит красиво, я посмотрю Jav_Rock
2

Там был бы умноженный кватернион вектора ARM, который я не могу найти сейчас. Я мог бы найти эту SIMD библиотеку:

Bullet 3D Game Мультифизическая библиотека

Похожие вопросы