情况:我正在尝试估算头部姿势。我已经校准了相机并获得了相机矩阵。我有一个与图像点相对应的3D模型。我找到姿势并获得旋转和平移矢量:
_, rvec, tvec = cv2.solvePnP(model_points, image_points, camera_matrix, dist_coeffs, flags=...)
然后我从旋转矢量获得旋转矩阵:
rotation_matrix, _ = cv2.Rodrigues(rvec)
现在,我决定看一下欧拉角。我创建投影矩阵如下:
projection_matrix = camera_matrix.dot(np.hstack((rotation_matrix, tvec)))
所以我的投影矩阵现在是3x4。然后我得到了欧拉角:
angles = cv2.decomposeProjectionMatrix(projection_matrix)[-1]
问题::我在这篇文章(Python Opencv SolvePnP yields wrong translation vector)中找到了另一种获取欧拉角的方法,据作者所述,该方法应得到与我的角度相同的结果(确实如此)为他们):
y_rot = math.asin(rotation_matrix[2][0])
x_rot = math.acos(rotation_matrix[2][2]/math.cos(y_rot))
z_rot = math.acos(rotation_matrix[0][0]/math.cos(y_rot))
y_rot_angle = y_rot *(180/3.1415)
x_rot_angle = x_rot *(180/3.1415)
z_rot_angle = z_rot *(180/3.1415)
我从分解投影矩阵中得到的角度是:
[164.17979619 19.45087415 1.95279565]
此其他解决方案提供的内容:
[164.18463841290048, -19.451447820154847, 1.9528532437807946]
标量值相同,但是y角旋转的方向不同。我在想-也许我误会了什么?
答案 0 :(得分:1)
我不确切知道从矩阵中获得euangle的实现是哪种排列,但是它与decomposeProjectionMatrix所使用的不同。 这就是角度不同的原因。
如前所述,欧拉角始终取决于顺序。有12种不同的排列。有关更多信息,请参见Euler Angles。
opencv的decomposeProjectionMatrix使用“ XYZ”顺序表示欧拉角。
pypi上有不同的旋转库。我在本示例中使用transforms3d。 我正在手动设置输入参数,并通过transforms3d软件包的euler2mat函数设置旋转矩阵。 我使用XYZ约定创建一个Rotation矩阵,例如横滚角(X):90°,俯仰(Y):45°,横摆(X):180°
from transforms3d import euler
from math import pi,radians
rotation_matrix = euler.euler2mat(radians(90), radians(45),
radians(180), 'sxyz')
tvec = np.zeros(3).reshape(1,3).T
camera_matrix = np.array([[1500,0,320],[0,1500,256],[0,0,1]])
projection_matrix = camera_matrix.dot(np.hstack((rotation_matrix, tvec)))
rot = cv2.decomposeProjectionMatrix(projection_matrix)
rotation_matrix(输入)和rot [1](输出)是相同的(但仅具有正确的欧拉阶“ sxyz”):
array([[-7.07106781e-01, -7.07106781e-01, 7.91668771e-17],
[ 8.65956056e-17, 2.53632657e-17, 1.00000000e+00],
[-7.07106781e-01, 7.07106781e-01, 4.32978028e-17]])
rot [-1]是:
[[90. ]
[ 45. ]
[ 180. ]]
3d旋转还有更多陷阱。例如。