1

我正在使用 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 中获得稳定的四元数?

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

四元数正在翻转符号以进行非常相似的旋转?

基于此,我尝试添加:

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

但我看到同样的翻转。

4

2 回答 2

2

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

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

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

于 2018-03-17T18:34:23.447 回答
1

标志应该没关系...

...旋转方面,只要4D 四元数的所有四个字段都被翻转。这里有更多解释: 四元数到 EulerXYZ,如何区分负四元数和正四元数

这样想: 角度/轴都翻转意味着同样的事情 ,注意顺时针到逆时针的过渡,就像在镜像中一样。

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

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

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

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

于 2018-03-20T00:24:39.257 回答