使用opencv将旋转矩阵转换为欧拉角

使用opencv将旋转矩阵转换为欧拉角,opencv,rotational-matrices,euler-angles,Opencv,Rotational Matrices,Euler Angles,我正在从事一个涉及阿鲁科标记和opencv的项目。 我的项目进展得相当快。我可以读取旋转向量,并使用opencv中的rodrigues()将其转换为rodrigues矩阵 这是我得到的罗德里格斯矩阵的一个例子: [0,1,0 1,0,0 0,0,-1] 我使用以下代码 Mat m33(3, 3, CV_64F); Mat measured_eulers(3, 1, CV_64F); Rodrigues(rotationVectors, m33); measured_eulers = rot2e

我正在从事一个涉及阿鲁科标记和opencv的项目。 我的项目进展得相当快。我可以读取旋转向量,并使用opencv中的rodrigues()将其转换为rodrigues矩阵

这是我得到的罗德里格斯矩阵的一个例子:

[0,1,0

1,0,0

0,0,-1]

我使用以下代码

Mat m33(3, 3, CV_64F);
Mat measured_eulers(3, 1, CV_64F);
Rodrigues(rotationVectors, m33);

measured_eulers = rot2euler(m33);

Degree_euler = measured_eulers * 180 / CV_PI;
我使用预定义的Rot2uler将rodrigues矩阵转换为euler角度。 我把接收到的弧度转换成度

Rot2uler如下所示

Mat rot2euler(const Mat & rotationMatrix)
{
    Mat euler(3, 1, CV_64F);

    double m00 = rotationMatrix.at<double>(0, 0);
    double m02 = rotationMatrix.at<double>(0, 2);
    double m10 = rotationMatrix.at<double>(1, 0);
    double m11 = rotationMatrix.at<double>(1, 1);
    double m12 = rotationMatrix.at<double>(1, 2);
    double m20 = rotationMatrix.at<double>(2, 0);
    double m22 = rotationMatrix.at<double>(2, 2);

    double x, y, z;

    // Assuming the angles are in radians.
    if (m10 > 0.998) { // singularity at north pole
        x = 0;
        y = CV_PI / 2;
        z = atan2(m02, m22);
    }
    else if (m10 < -0.998) { // singularity at south pole
        x = 0;
        y = -CV_PI / 2;
        z = atan2(m02, m22);
    }
    else
    {
        x = atan2(-m12, m11);
        y = asin(m10);
        z = atan2(-m20, m00);
    }

    euler.at<double>(0) = x;
    euler.at<double>(1) = y;
    euler.at<double>(2) = z;

    return euler;
}
Mat转子(常数Mat和旋转矩阵)
{
Mat euler(3,1,CV_64F);
double m00=旋转矩阵(0,0);
double m02=旋转矩阵(0,2);
双m10=旋转矩阵(1,0);
双m11=旋转矩阵,在(1,1)处;
双m12=旋转矩阵。在(1,2)处;
双m20=旋转矩阵,在(2,0)处;
双m22=旋转矩阵,在(2,2)处;
双x,y,z;
//假设角度以弧度为单位。
if(m10>0.998){//北极奇点
x=0;
y=CV_PI/2;
z=atan2(m02,m22);
}
else如果(m10<-0.998){//南极奇点
x=0;
y=-CV_PI/2;
z=atan2(m02,m22);
}
其他的
{
x=atan2(-m12,m11);
y=asin(m10);
z=atan2(-m20,m00);
}
(0)处的欧拉=x;
euler.at(1)=y;
euler.at(2)=z;
返回欧拉;
}
如果我使用罗德里格斯矩阵作为例子,我会得到以下欧拉角

[0;90;-180]

但是我应该得到以下信息

Mat rot2euler(const Mat & rotationMatrix)
{
    Mat euler(3, 1, CV_64F);

    double m00 = rotationMatrix.at<double>(0, 0);
    double m02 = rotationMatrix.at<double>(0, 2);
    double m10 = rotationMatrix.at<double>(1, 0);
    double m11 = rotationMatrix.at<double>(1, 1);
    double m12 = rotationMatrix.at<double>(1, 2);
    double m20 = rotationMatrix.at<double>(2, 0);
    double m22 = rotationMatrix.at<double>(2, 2);

    double x, y, z;

    // Assuming the angles are in radians.
    if (m10 > 0.998) { // singularity at north pole
        x = 0;
        y = CV_PI / 2;
        z = atan2(m02, m22);
    }
    else if (m10 < -0.998) { // singularity at south pole
        x = 0;
        y = -CV_PI / 2;
        z = atan2(m02, m22);
    }
    else
    {
        x = atan2(-m12, m11);
        y = asin(m10);
        z = atan2(-m20, m00);
    }

    euler.at<double>(0) = x;
    euler.at<double>(1) = y;
    euler.at<double>(2) = z;

    return euler;
}
[-180;0;90]

什么时候使用这个工具

您可以看到[0;90;-180]与罗德里格斯矩阵不匹配,但[-180;0;90]与之匹配。(我知道该工具使用ZYX坐标)

所以问题是我得到了正确的值,但顺序不对

另一个问题是,情况并非总是如此。 例如,罗德里格斯矩阵:

[1,0,0

0,-1,0

0,0,-1]

为我提供正确的欧拉角

如果有人知道问题的解决方案,或者可以向我解释Rot2uler函数是如何准确工作的。我们将不胜感激

问候


Brent Convents不是专门针对OpenCV的,但您可以这样写:

cosine_for_pitch = math.sqrt(pose_mat[0][0] ** 2 + pose_mat[1][0] ** 2)
is_singular = cosine_for_pitch < 10**-6
if not is_singular:
    yaw = math.atan2(pose_mat[1][0], pose_mat[0][0])
    pitch = math.atan2(-pose_mat[2][0], cosine_for_pitch)
    roll = math.atan2(pose_mat[2][1], pose_mat[2][2])
else:
    yaw = math.atan2(-pose_mat[1][2], pose_mat[1][1])
    pitch = math.atan2(-pose_mat[2][0], cosine_for_pitch)
    roll = 0
音高的余弦=math.sqrt(姿势垫[0][0]**2+姿势垫[1][0]**2) 音调<10**-6时,是否为单数=余弦 如果不是单数: 偏航=数学atan2(姿势垫[1][0],姿势垫[0][0]) 俯仰=数学atan2(-pose_mat[2][0],余弦_表示俯仰) 滚动=数学atan2(姿势垫[2][1],姿势垫[2][2]) 其他: 偏航=数学atan2(-pose_mat[1][2],pose_mat[1][1]) 俯仰=数学atan2(-pose_mat[2][0],余弦_表示俯仰) 滚动=0 在这里,您可以探索更多内容:


我想我已经很晚了,不过我还是会回答的。 别在这件事上引用我的话 OPENCV 3.3源代码中的文件({OPENCV_INSTALLATION_DIR}/apps/interactive calibration/rotationConverters.cpp)

在我看来,openCV提供了Y-Z-X(类似于上面代码中显示的内容)


为什么我说我不确定,因为我只是查看了cv::Rodrigues的源代码,它似乎没有调用我上面展示的这段代码。罗德里格斯函数包含了数学编码(我认为可以通过取两个旋转矩阵并将它们相乘为-R=Ry*Rz*Rx,然后查看代码中有一个
acos(R(2,0))或asin(R(0,2)
或类似的东西来检查它,因为“R”的一个元素通常是cos()或者正弦,它将为你提供一个关于找到哪个角度的解决方案。

两个不同的欧拉旋转可以代表相同的旋转。尝试使用逆转换获得3x3矩阵。似乎你是在奇点的情况下。据我所知,对于90度或180度这样的角度使用旋转矩阵并不方便(不管它们是正的还是负的)因为你面临奇点的风险。而且看起来公式是错误的。。。