基于OpenCV solvePnP从向量获取正确相机位姿的问题
相机参数复现与OpenCV solvePnP相关问题解答
1. Maya与OpenCV的坐标系向上轴差异
Maya默认采用Y轴向上的右手世界坐标系,而OpenCV的相机坐标系是右手系:X轴向右,Y轴向下,Z轴指向相机前方(远离相机的方向)。OpenCV本身没有固定的"世界坐标系向上轴"定义,但在使用solvePnP时,必须保证输入的3D点坐标系与期望的输出坐标系对齐。如果直接使用Maya导出的3D点,需要先将Y轴坐标取反(因为OpenCV的Y轴向下),或者调整后续旋转/平移参数的转换逻辑,否则会出现轴方向不匹配的问题。
2. 从rvecs/tvecs转换为Maya风格的Rx/Ry/Rz和平移参数
步骤1:旋转向量转旋转矩阵
先用OpenCV的Rodrigues函数将solvePnP输出的旋转向量(rvec)转换为3x3旋转矩阵:
import cv2 import numpy as np rvec = ... # solvePnP输出的旋转向量 R, _ = cv2.Rodrigues(rvec)
步骤2:对齐坐标系
由于Maya和OpenCV的Y轴方向相反,需要先调整旋转矩阵和平移向量:
R_adjusted = R.copy() R_adjusted[1, :] *= -1 # 反转旋转矩阵的Y轴分量 tvec_adjusted = tvec.copy() tvec_adjusted[1] *= -1 # 反转平移向量的Y分量
步骤3:计算相机平移参数(Tx/Ty/Tz)
solvePnP输出的tvec是世界坐标系到相机坐标系的平移向量,而Maya中的Tx/Ty/Tz是相机中心在世界坐标系中的位置,两者关系为:
# 相机中心在世界坐标系中的位置T = -R^T * tvec T = -np.dot(R_adjusted.T, tvec_adjusted).flatten() Tx, Ty, Tz = T[0], T[1], T[2]
步骤4:旋转矩阵转欧拉角(Rx/Ry/Rz)
Maya默认采用Z-Y-X顺序的欧拉角(先绕Z轴旋转Rz,再绕Y轴旋转Ry,最后绕X轴旋转Rx),可以用scipy工具类实现转换:
from scipy.spatial.transform import Rotation as Rot rot = Rot.from_matrix(R_adjusted) # 按zyx顺序获取欧拉角,单位为度 rz, ry, rx = rot.as_euler('zyx', degrees=True) # 对应Maya的Rx/Ry/Rz Rx, Ry, Rz = rx, ry, rz
若没有scipy,也可手动实现旋转矩阵转欧拉角,但需注意处理万向锁问题。
3. solvePnP的实现细节查看
OpenCV的Python版solvePnP是对C++核心实现的封装,所有逻辑都在OpenCV的开源代码中:
- 核心实现位于
modules/calib3d/src/solvepnp.cpp文件,包含了多种求解算法(如EPnP、P3P、迭代优化法等),可直接查看该文件了解具体求解步骤和数学原理。 - 官方文档也有原理说明:它通过最小化3D点到2D图像点的重投影误差求解相机外参,输入至少4组非共面的3D-2D对应点即可得到唯一解;若点共面,也可通过平面PnP算法求解。
内容的提问来源于stack exchange,提问作者nasun
相关产品推荐
相关产品推荐

