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

Posted

技术标签:

【中文标题】使用 cv::Mat 的高效 C++ 四元数乘法【英文标题】:Efficient C++ quaternion multiplication using cv::Mat 【发布时间】:2012-06-02 14:34:36 【问题描述】:

我想将 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 最快的方法吗?使用定点算术会最快吗?

【问题讨论】:

16 次乘法和 12 次加法——对我来说似乎没有太大的改进空间。使函数内联!我希望这些“at”调用不是函数调用(即它们应该是内联的)。 它是 Mat 类的 openCV 成员。我认为这是访问 Mat elment 的最快方法,但我不确定。 opencv.willowgarage.com/documentation/cpp/… 尽可能高效?首先,不要对像四分量数组这样微不足道的东西使用执行动态内存分配和引用计数的矩阵类。对于新的 Matx 类,这正是一个完美的用例,参考您的其他问题之一。 嗯,我得试试那个新课,谢谢 可能值得从 q2 的洗牌版本设置 4X4,然后矩阵相乘;有点模仿子弹物理代码的作用。使用 SSE4,opencv - 应该有一个非常紧凑的矩阵乘法。 【参考方案1】:

在this 教程中介绍了访问不同像素的不同方法。与直接像素访问相比,Mat::at 函数被发现要慢 10%,这可能是由于在调试模式下进行了额外检查。

如果您真的不喜欢性能,您应该使用文中提到的 3 种不同方法重写您的方法,然后分析以找到最适合您情况的一种。

【讨论】:

这个看起来不错,我去看看【参考方案2】:

曾经有一个 ARM 向量浮点四元数乘法,我现在找不到了。我可以找到这个 SIMD 库:

Bullet 3D Game Multiphysics Library

【讨论】:

【参考方案3】:

四元数通常用于旋转 3D 向量,因此您可以考虑检查一个四元数是否为纯向量(即标量或实部为零)。这可以将您的工作减少到 12 次乘法、8 次加法/减法和 1 次符号翻转。

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

【讨论】:

确实,或者编写并使用一个执行整个操作的例程:`vec_rotated = q * (0,vec)*q.conj()` 在一个函数调用中,与做两个完整的四元数产品(第二个产品的实部总是为零)。如果您需要通过相同的四元数旋转大量向量 - 特别是如果它们存储在矩阵中 - 将四元数转换为 3x3 旋转矩阵并在向量上使用它会更快。

以上是关于使用 cv::Mat 的高效 C++ 四元数乘法的主要内容,如果未能解决你的问题,请参考以下文章

结合具有不同枢轴点的四元数

几何系列四元数的基础

四元数 3 轴旋转

Hamilton四元数

C++ 四元数旋转未按预期工作

Unity编程Unity中关于四元数的API详解