目标
我需要检索相机的位置和姿态角(使用 OpenCV / Python)。
定义
姿态角定义为:
偏航是相机放置在水平面上时的大致方向:朝向北=0,朝向东=90°,南=180°,西=270°,等等。
俯仰是相机的“鼻子”方向:0° = 水平看地平线上的一点,-90° = 垂直向下看,+90° = 垂直向上看,45° = 以 45° 的角度向上看从地平线等
如果相机在您手中时向左或向右倾斜,则滚动(因此当该角度变化时,它总是看着地平线上的一个点):+45° = 当您抓住相机时顺时针旋转倾斜 45°,因此 +90°(和 -90°)将是例如肖像图片所需的角度等。
世界参考系:
我的世界参考系是这样定位的:
Toward east = +X
Toward north = +Y
Up toward the sky = +Z
我的世界对象点在该参考系中给出。
相机参考系:
要达到什么
现在,从cv2.solvepnp()
一堆图像点及其对应的世界坐标中,我计算了rvec
和tvec
。
但是,根据文档:http ://docs.opencv.org/trunk/d9/d0c/group__calib3d.html#ga549c2075fac14829ff4a58bc931c033d ,它们是:
rvec ; 输出旋转矢量(参见
Rodrigues()
),它与 一起tvec
将点从模型坐标系带到相机坐标系。
tvec ; 输出平移向量。
这些向量被赋予到相机参考系。
我需要进行精确的逆运算,从而检索相机相对于世界坐标的位置和姿态。
摄像头位置:
所以我从rvec
with计算了旋转矩阵Rodrigues()
:
rmat = cv2.Rodrigues(rvec)[0]
如果我在这里,在世界坐标系中表示的相机位置由下式给出:
camera_position = -np.matrix(rmat).T * np.matrix(tvec)
(src:来自 cv::solvePnP 的世界坐标中的相机位置)
这看起来相当不错。
相机姿态(偏航、俯仰和滚动):
但是如何从相机的角度(就好像它基本上在你手中一样)检索相应的姿态角(如上所述的偏航、俯仰和滚动)?
我试过在一个函数中实现这个: http ://planning.cs.uiuc.edu/node102.html#eqn:yprmat:
def rotation_matrix_to_attitude_angles(R):
import math
import numpy as np
cos_beta = math.sqrt(R[2,1] * R[2,1] + R[2,2] * R[2,2])
validity = cos_beta < 1e-6
if not validity:
alpha = math.atan2(R[1,0], R[0,0]) # yaw [z]
beta = math.atan2(-R[2,0], cos_beta) # pitch [y]
gamma = math.atan2(R[2,1], R[2,2]) # roll [x]
else:
alpha = math.atan2(R[1,0], R[0,0]) # yaw [z]
beta = math.atan2(-R[2,0], cos_beta) # pitch [y]
gamma = 0 # roll [x]
return np.array([alpha, beta, gamma])
但结果与我想要的不一致。例如,我的滚动角约为 -90°,但相机是水平的,所以它应该在 0 左右。
俯仰角在 0 左右,所以看起来是正确确定的,但我真的不明白为什么它在 0 左右,因为相机参考框架的 Z 轴是水平的,所以它已经从世界的垂直轴倾斜 90°参考范围。我预计这里的值为 -90° 或 +270°。反正。
偏航似乎很好。主要是。
问题
我错过了滚动角的东西吗?