C++ 高效C++;使用cv::Mat的四元数乘法

C++ 高效C++;使用cv::Mat的四元数乘法,c++,opencv,quaternions,C++,Opencv,Quaternions,我想乘以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);

我想乘以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
}
/**四元数乘法
*
*/
虚空倍数四元数(常数矩阵和q1、常数矩阵和q2、矩阵和q)
{
//第一个四元数q1(x1 y1 z1 r1)
常数浮点x1=q1.at(0);
常数浮点y1=q1.at(1);
常数浮点z1=q1.at(2);
常数浮点r1=q1.at(3);
//第二个四元数q2(x2 y2 z2 r2)
常数浮点x2=q2.at(0);
常数浮点y2=q2.at(1);
常数浮点数z2=q2.at(2);
常数浮点r2=q2.at(3);
q、 at(0)=x1*r2+r1*x2+y1*z2-z1*y2;//x分量
q、 at(1)=r1*y2-x1*z2+y1*r2+z1*x2;//y分量
q、 at(2)=r1*z2+x1*y2-y1*x2+z1*r2;//z分量
q、 at(3)=r1*r2-x1*x2-y1*y2-z1*z2;//r分量
}
这是使用OpenCV最快的方法吗?使用定点算法是否最快?

本教程介绍了访问不同像素的不同方法。与直接像素访问相比,
Mat::at
功能被发现大约慢10%,这可能是由于调试模式下的额外检查


如果你真的对性能不满意,你应该用文本中提到的3种不同的方法重写你的方法,然后配置文件以找到一种最适合你的方法。

那里有一个手臂向量浮点四元数乘法,我现在找不到。我可以找到这个SIMD库:


< P>四元数常被用来旋转3D向量,因此你可以考虑检查一个四元数是纯向量(即标量或实部为零)。这可以将你的工作减少到12倍,8加/减和一个符号翻转


您还可以在两个纯向量上使用四元数乘法来同时计算它们的点积和叉积,因此对于这种特殊情况的测试也可能是值得的。如果两个四元数都是纯向量,则只需进行9次乘法、5次加法/减法和一次符号翻转。

16次乘法和12次加法——我似乎没有太大的改进空间。使函数内联!我希望这些“at”调用不是函数调用(即,它们应该是内联的)。它是Mat类的openCV成员。我认为这是接触材料最快的方法,但我不确定。尽可能高效?首先,不要使用一个matrix类来动态分配内存和引用计数像四组件数组这样微不足道的东西。关于你的另一个问题,对于新的
Matx
类来说,这正是一个完美的用例。嗯,我必须尝试一下这个新类,thanksIt-可能-值得从q2的无序版本设置一个4X4,以及矩阵乘法;模拟子弹物理代码的功能。对于SSE4,opencv应该有一个非常紧密的矩阵乘法。这看起来很好,我将确实有一个外观,或者编写并使用一个执行整个运算的例程:`vec_rotated=q*(0,vec)*q.conj()`在一个函数调用中,与执行两个完整的四元数乘积(第二个prod的实部始终为零)相比,一些操作被保存下来。如果需要用同一个四元数旋转许多向量,特别是如果它们存储在矩阵中,则将四元数转换为3x3旋转矩阵并在向量上使用它会更快。