我使用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();
}
但我看到同样的翻转。
答案 0 :(得分:1)
quat
和-quat
代表相同的轮播。您可以通过获取单位四元数,将其转换为旋转矩阵,然后执行
quat.coeffs() = -quat.coeffs();
并将其转换为旋转矩阵。
如果由于某种原因您始终需要正w
值,则在w
为负数时否定所有系数。
答案 1 :(得分:0)
标志无关紧要......
...旋转方式,只要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 > 0
只是意味着:我希望angle
在(-pi, pi)
范围内。这样-270度旋转变为+90度旋转。
执行quat.Inverse()
可能不是您想要的,因为这会在相反的方向上创建旋转。那是-quat != quat.Inverse()
。
另外:检查两个系统是否具有相同的灵活性(chirality)!测试旋转矩阵行列式是否为+1或-1。
(对于图片链接,我没有足够的声誉嵌入它们。)