基于OpenCV的双目相机校准方案合理性问询及误差排查
核心问题定位
你的方案存在根本性的坐标系转换逻辑错误,尤其是相对位姿的推导部分,这是导致验证阶段重投影误差爆炸、位姿严重偏差的核心原因。此外,手动平均位姿的方式不如OpenCV原生双目校准函数可靠,进一步放大了误差。
逐步骤错误分析
1. 单相机校准(无问题)
单相机calibrateCamera得到的内参重投影误差<0.01像素,说明内参校准效果良好,可排除这部分问题。
2. 相对位姿计算的致命错误
首先明确OpenCVsolvePnP的输出定义:返回的rvec/tvec是世界坐标系(Charuco板)到相机坐标系的转换矩阵,即相机坐标系下的点满足:
P_cam = R @ P_world + t
其中R是rvec转成的旋转矩阵,t是平移向量。
你当前计算相机2到相机1位姿的公式完全搞反了旋转顺序:
- 错误公式:
r_diff = r2^T * r1、t_diff = r2^T * (t1-t2) - 正确推导:假设同一帧中,相机1的转换为
P_cam1 = R1 @ P_w + t1,相机2的转换为P_cam2 = R2 @ P_w + t2。我们需要的是相机2到相机1的转换(即P_cam1 = R @ P_cam2 + T),将P_w = R2.T @ (P_cam2 - t2)代入相机1的公式,可得:R = R1 @ R2.T # 相机2到相机1的旋转矩阵 T = t1 - R @ t2 # 相机2到相机1的平移向量
你当前的旋转矩阵计算顺序完全颠倒,直接导致位姿旋转、缩放彻底错误。
另外,手动将旋转矩阵转四元数平均的方式,远不如OpenCV的stereoCalibrate函数可靠——该函数通过非线性最小二乘法联合优化两个相机的内参和相对位姿,能给出更稳定、准确的结果。
3. 验证阶段的转换公式错误
你当前的验证转换公式r_diff = r_2calibration * r2_v、t_diff = r2_calibration * tvec2 + t_calib不符合坐标系转换逻辑。正确的转换应该是:
若校准得到相机2到相机1的旋转矩阵R、平移向量T,则相机2坐标系下的点转换到相机1坐标系的公式为:
P_cam1 = R @ P_cam2 + T
结合验证场景:用solvePnP得到相机2中Charuco板的位姿(R2_v, t2_v)(即P_cam2 = R2_v @ P_w + t2_v),要将世界点转换到相机1坐标系,应代入上述公式,再用相机1的内参投影到图像平面,与实际检测的角点对比。
修正后的标准流程
- 图像采集与预处理:保留原有的清晰度、角点数量校验逻辑,确保30-40组图像对均能检测到足够的Charuco角点,且所有图像的世界坐标系(Charuco板)定义一致。
- 单相机校准:继续用
calibrateCamera获取两个相机的内参mtx1/mtx2、畸变系数dist1/dist2。 - 双目联合校准:改用OpenCV的
stereoCalibrate计算相对位姿,输入参数包括:- 所有图像对的
object_points(Charuco板世界坐标点) - 相机1/2对应的
image_points - 图像尺寸
- 已校准的单相机内参和畸变系数
该函数会返回相机2到相机1的旋转矩阵R、平移向量T,以及联合重投影误差(正常应在1-3像素范围内)。
- 所有图像对的
- 验证阶段:
- 采集新图像对,分别检测Charuco角点;
- 用相机1的内参将世界点投影到图像,确认单相机重投影误差正常;
- 用校准得到的
R和T,将相机2中的世界点转换到相机1坐标系,再投影到相机1图像,与实际检测角点对比计算误差。
额外注意事项
- 采集图像时,需让Charuco板覆盖相机的整个视野,包含不同距离、角度、位置的场景,避免校准结果过拟合;
- 若需要后续立体匹配,可使用
stereoRectify计算校正映射,消除图像畸变并使极线对齐。
内容的提问来源于stack exchange,提问作者Patrick

