opencv 将旋转矩阵转换为欧拉角并反向转换-特殊情况?

vsdwdz23  于 2022-11-15  发布在  其他
关注(0)|答案(2)|浏览(99)

我将旋转矩阵分解为欧拉角(Tait-Bryan角更具体地说是x-y-z顺序,即先绕x轴旋转),然后再分解为旋转矩阵。我使用了transforms 3d python库(https://github.com/matthew-brett/transforms3d),也遵循了本教程www.gregslabaugh.net/publications/euler.pdf。两者都给予了相同的结果。
问题是重新组合的旋转矩阵与我开始使用的旋转矩阵不匹配。
我使用的矩阵是由openCV的“decomposeHomographyMat”函数创建的,所以我希望它是一个有效的旋转矩阵。

这三个Angular 是[-1.8710997,0.04623301,-0.03679793]。如果我把它们转换回旋转矩阵,我得到

其中R_23不能是舍入误差。
按照上图,绕y轴旋转(β)可通过下式计算:(-R_31)。另一个有效Angular 为pi-asin(-R_31)。绕x轴的Angular (α)可通过atan 2计算(R_32、R_33)。也可以通过求α(R_32/cos(β))或由acos如果我使用后两个等式,我只在使用beta=pi-arcsin时得到相同的alpha结果(-R_31),这意味着β只有一个有效解,atan 2(R_32,R_33)给出了与两者不同的结果。
无论如何,我的矩阵似乎有问题,或者我不明白为什么分解不起作用。

import numpy as np

def rot2eul(R):
    beta = -np.arcsin(R[2,0])
    alpha = np.arctan2(R[2,1]/np.cos(beta),R[2,2]/np.cos(beta))
    gamma = np.arctan2(R[1,0]/np.cos(beta),R[0,0]/np.cos(beta))
    return np.array((alpha, beta, gamma))

def eul2rot(theta) :

    R = np.array([[np.cos(theta[1])*np.cos(theta[2]),       np.sin(theta[0])*np.sin(theta[1])*np.cos(theta[2]) - np.sin(theta[2])*np.cos(theta[0]),      np.sin(theta[1])*np.cos(theta[0])*np.cos(theta[2]) + np.sin(theta[0])*np.sin(theta[2])],
                  [np.sin(theta[2])*np.cos(theta[1]),       np.sin(theta[0])*np.sin(theta[1])*np.sin(theta[2]) + np.cos(theta[0])*np.cos(theta[2]),      np.sin(theta[1])*np.sin(theta[2])*np.cos(theta[0]) - np.sin(theta[0])*np.cos(theta[2])],
                  [-np.sin(theta[1]),                        np.sin(theta[0])*np.cos(theta[1]),                                                           np.cos(theta[0])*np.cos(theta[1])]])

    return R

R = np.array([[ 0.9982552 , -0.03323557, -0.04880523],
       [-0.03675031,  0.29723396, -0.95409716],
       [-0.04621654, -0.95422606, -0.29549393]])

ang = rot2eul(R)
eul2rot(ang)

import transforms3d.euler as eul
ang = eul.mat2euler(R, axes='sxyz')
eul.euler2mat(ang[0], ang[1], ang[2], axes='sxyz')
aemubtdh

aemubtdh1#

结果是旋转矩阵有一个负行列式,这使得它成为一个不正确的旋转矩阵。openCV函数“decomposeHomographyMat”有一个bug:https://github.com/opencv/opencv/issues/4978

8aqjt8rx

8aqjt8rx2#

也许你可以用scipy

from scipy.spatial.transform import Rotation   

### first transform the matrix to euler angles
r =  Rotation.from_matrix(rotation_matrix)
angles = r.as_euler("zyx",degrees=True)

#### Modify the angles
print(angles)
angles[0] += 5

#### Then transform the new angles to rotation matrix again
r = Rotation.from_euler("zyx",angles,degrees=True)
new_rotation_matrix = new_r.as_matrix()

相关问题