【问题标题】:opencv Vec3d to Eigen::Quaternion, euler flipping on resultsopencv Vec3d 到 Eigen::Quaternion,欧拉翻转结果
【发布时间】:2018-08-26 14:22:24
【问题描述】:

我正在使用 opencv::solvePnP 返回相机姿势。我运行 PnP,它返回 rvec 和 tvec 值。(旋转向量和位置)。

然后我运行此函数将值转换为相机姿势:

void GetCameraPoseEigen(cv::Vec3d tvecV, cv::Vec3d rvecV, Eigen::Vector3d &Translate, Eigen::Quaterniond &quats)
{
    Mat R;
    Mat tvec, rvec;

    tvec = DoubleMatFromVec3b(tvecV);
    rvec = DoubleMatFromVec3b(rvecV);

    cv::Rodrigues(rvec, R); // R is 3x3
    R = R.t();                 // rotation of inverse
    tvec = -R*tvec;           // translation of inverse

    Eigen::Matrix3d mat;
    cv2eigen(R, mat);

    Eigen::Quaterniond EigenQuat(mat);

    quats = EigenQuat;


    double x_t = tvec.at<double>(0, 0);
    double y_t = tvec.at<double>(1, 0);
    double z_t = tvec.at<double>(2, 0);

    Translate.x() = x_t * 10;
    Translate.y() = y_t * 10;
    Translate.z() = z_t * 10;   

}

这可行,但在某些旋转角度,转换后的旋转值会在正值和负值之间随机翻转。然而,源 rvecV 值却没有。我认为这意味着我的转换出错了。如何从 PnP 返回的 cv::Vec3d 中获得稳定的四元数?

编辑:这似乎是四元数翻转,如此处所述:

Quaternion is flipping sign for very similar rotations?

基于此,我尝试添加:

if(quat.w() < 0)
 {
 quat = quat.Inverse();
 } 

但我看到了同样的翻转。

【问题讨论】:

  • 您实际上应该已经阅读了您找到的问题的其他答案:stackoverflow.com/a/42516812
  • 所以基本上,如果 w 是负数,否定 x、y 和 z?对吗?

标签: opencv eigen quaternions opencv-solvepnp


【解决方案1】:

quat-quat 都代表相同的旋转。您可以通过获取单位四元数,将其转换为旋转矩阵,然后执行

quat.coeffs() = -quat.coeffs();

并将其转换为旋转矩阵。 如果由于某种原因您总是想要一个正的 w 值,如果 w 为负值,则否定所有系数。

【讨论】:

  • 谢谢。我将数据分配给 3d 模型,并且翻转显然是巨大的旋转跳跃。
  • 您如何“将数据分配给 3d 模型”?我认为这就是您的实际错误所在。
  • 在虚幻引擎里面,我相信那边没问题。我也试过用opengl。我在两者中都看到了相同的翻转。
  • 好吧,我相信四元数的符号在用于表示 3d 旋转时无关紧要......
  • 我会仔细检查我的应用程序,但这与我之前多次使用的应用轮换方法相同。也许我遇到的问题与翻转不同。我上面的转换看起来正确吗?
【解决方案2】:

标志应该无关紧要......

... 旋转方式,只要 4D 四元数的所有四个字段 都被翻转。这里有更多解释: Quaternion to EulerXYZ, how to differentiate the negative and positive quaternion

这样想: Angle/axis both flipped mean the same thing 并且注意顺时针到逆时针的过渡非常在镜像中。

可能有约定保持quat.w()quat[0] 组件为正,并相应地将其他组件更改为相反。假设w = cos(angle/2) 然后设置w &gt; 0 只是意味着:我希望angle(-pi, pi) 范围内。使-270度旋转变成+90度旋转。

执行quat.Inverse() 可能不是您想要的,因为这会产生相反方向的旋转。那是-quat != quat.Inverse()

另外:检查两个系统是否具有相同的惯用手 (chirality)!测试您的旋转矩阵行列式是 +1 还是 -1。

(对不起,图片链接,我没有足够的声誉来嵌入它们)。

【讨论】:

  • 嗨,我仍然有这个问题。我正在执行以下操作:if (EigenQuat.w() &lt; 0) { EigenQuat.x() = EigenQuat.x() * -1; EigenQuat.y() = EigenQuat.y() * -1; EigenQuat.z() = EigenQuat.z() * -1; EigenQuat.w() = EigenQuat.w() * -1; } 并有所帮助,但我仍然可以在某个角度看到我的 3d 模型中的翻转。这是正确的方法吗?
  • ..我也试过在 w 为负数时只翻转 xyz,效果相同。
  • 你能提供更多关于实际数据/截图/输出值的信息吗?另见:github.com/opencv/opencv/issues/8813
  • 我正在记录数据,看到一些奇怪的东西。使用上面原始问题中的代码,翻转看起来像这样:rvec: [-1.9554, 0.0461893, 0.762008] quat: 0.807827 -0.019082 -0.314805 -0.497945 rvec: [-1.94081, 0.0626131, 0.774592] quat: -0.803091 0.0259088 0.32052 0.501638 您可以清楚地看到四元翻转,而 rvec 值保持不变。当我(如果 w rvec: [2.87162, 0.466238, -1.13857] quat: 0.919152 0.149234 -0.364435 0.00875124 rvec: [-2.84968, -0.447527, 1.14067] quat: -0.918494 -0.144244 0.367654 -0.0198193 RVEC 现在翻转
  • ...在 3d 空间中,在我的模型上,翻转看起来像一个非常快速的旋转 180 度,然后返回。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多