目标
我需要使用OpenCV / Python检索相机的位置和姿态角。
定义
姿态角由以下定义:
偏航角是相机在水平平面上的一般方向:朝北=0,朝东=90°,朝南=180°,朝西=270°等。
俯仰角是相机的“鼻子”方向:0°=水平看着地平线上的一个点,-90°=垂直向下看,+90°=垂直向上看,45°=以45°的角度向上看等。
翻滚角是当相机在你手中倾斜时左右倾斜的角度(因此当该角度变化时,它始终看着地平线上的一个点):+45°=顺时针旋转45°当你抓住相机时倾斜,因此例如+90°(和-90°)将是拍摄肖像照片所需的角度等。
世界参考系:
我的世界参考系是这样定向的:
以下是中文的翻译:
向东 = +X
向北 = +Y
朝天上方 = +Z
我的世界对象点是在此参考系中给出的。
相机参考系:
需要达成的目标
现在,我通过cv2.solvepnp()
算出了一堆图像点和它们对应的世界坐标,计算出了rvec
和tvec
。但是,根据文档:http://docs.opencv.org/trunk/d9/d0c/group__calib3d.html#ga549c2075fac14829ff4a58bc931c033d,它们是: ; 输出旋转向量(参见
Rodrigues()
),与 tvec
一起将模型坐标系中的点带到相机坐标系中。; 输出平移向量。
这些向量是提供给相机参考框架的。
我需要执行确切的反向操作,从而检索相机位置和姿态相对于世界坐标。
相机位置:
因此,我已经使用 Rodrigues()
从 rvec
计算出旋转矩阵:
rmat = cv2.Rodrigues(rvec)[0]
如果我没错的话,相机在世界坐标系中的位置可以表示为:
camera_position = -np.matrix(rmat).T * np.matrix(tvec)
(来源: 从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°。无论如何。
偏航看起来不错。主要是。
问题
我在滚转角方面漏掉了什么吗?
alpha = math.atan2(R[2,0], R[2,1])
,beta = math.acos(R[2,2])
和gamma= -math.atan2(R[0,2], R[1,2])
。 - cyborg