4. 单相机外参标定:旋转矩阵与平移向量、相机位姿表示
外参标定,说白了就是搞清楚相机在世界坐标系里到底「站」在哪、朝哪个方向看。我刚开始做多相机系统时,总觉得内参更重要,外参随便算算就行。结果有一次把两个相机的旋转方向搞反了,重建出来的点云直接拧成了麻花……嗯,从那以后我再也不敢小看外参了。
这一章我们聚焦单相机的外参。你理解了它,四相机联合标定就完成了一半。
4.1 外参到底在描述什么?
外参包含两个部分:旋转矩阵 R 和 平移向量 t。它们共同完成一个任务——把世界坐标系下的点 Pw 转换到相机坐标系下:
P_c = R * P_w + t
你可以这样理解:
- R:描述相机坐标系相对于世界坐标系的姿态(朝向)
- t:描述相机坐标系原点在世界坐标系中的位置
我个人习惯把外参看作「一个刚体变换」。相机固定在一个支架上,它相对于世界坐标系的旋转和平移,就是一组外参。
关键点:外参是 3×4 矩阵 [R|t] 的前 3 列是旋转,第 4 列是平移。它把世界点映射到相机坐标系,而不是反过来。
4.2 旋转矩阵:不只是 3×3 的数字
旋转矩阵 R 是一个 3×3 的正交矩阵,满足 RTR = I,且 det(R) = 1。它每一列都是单位向量,且两两正交。
我在项目中遇到过一个问题:用优化算法直接估计 R 的 9 个元素,结果矩阵不满足正交约束,重建出来的场景全是扭曲的。所以实际工程中,我们很少直接优化 R 的 9 个参数。
| 表示方式 | 自由度 | 优点 | 缺点 |
|---|---|---|---|
| 旋转矩阵 R | 9(实际 3) | 直观、易组合 | 需满足正交约束 |
| 欧拉角 | 3 | 参数少、直观 | 万向锁、不连续 |
| 四元数 | 4 | 无奇点、易插值 | 需归一化 |
| 轴角 | 3 | 紧凑、几何意义明确 | 有奇点 |
4.3 欧拉角:直观但暗藏陷阱
欧拉角用三个角度表示旋转:绕 X 轴(roll)、绕 Y 轴(pitch)、绕 Z 轴(yaw)。听起来很简单对吧?
但这里有个坑——万向锁。当 pitch 接近 ±90° 时,roll 和 yaw 会失去一个自由度,导致旋转退化。我曾经在无人机云台标定中遇到过这个问题,pitch 角一过 85°,姿态解算就开始乱跳。
避坑指南:如果你用欧拉角做优化变量,一定要限制 pitch 范围在 ±80° 以内,或者干脆换用四元数。我曾经因为没注意这个,浪费了整整两天调试时间。
另外,欧拉角的旋转顺序也很关键。常见的顺序有 ZYX、XYZ、ZYZ 等。不同顺序得到的角度值完全不同。你想想看,如果标定程序用 ZYX,而你的算法用 XYZ,那结果肯定对不上。
4.4 四元数:SLAM 工程师的最爱
四元数 q = (w, x, y, z) 是一种超复数,满足 w² + x² + y² + z² = 1。它用 4 个参数表示 3 个自由度的旋转,没有奇点,而且插值平滑。
我个人在 SLAM 项目中几乎只用四元数。原因很简单:
- 优化时不需要额外约束(只要归一化)
- 组合旋转用乘法,比矩阵快
- 插值(Slerp)非常平滑
四元数到旋转矩阵的转换公式:
R = [
[1-2(y²+z²), 2(xy-wz), 2(xz+wy)],
[2(xy+wz), 1-2(x²+z²), 2(yz-wx)],
[2(xz-wy), 2(yz+wx), 1-2(x²+y²)]
]
小技巧:实际编码时,直接用 Eigen 或 OpenCV 的 Rodrigues 函数转换,别手写矩阵。我见过太多人把符号写反了。
4.5 平移向量:别忽略尺度
平移向量 t = (tx, ty, tz)T 表示相机光心在世界坐标系中的位置。单位通常和标定板尺寸一致(比如毫米)。
这里有个容易忽略的点:平移向量的尺度。如果你用棋盘格标定,格子大小是 30mm,那 t 的单位就是 mm。如果你用二维码标定,尺寸是 5cm,那 t 的单位就是 cm。混用单位会导致重建结果完全不对。
我记得有一次帮同事排查问题,他标定出来的外参总是偏大 10 倍。查了半天,原来是标定板尺寸写成了 3cm,实际是 30mm。嗯,这种低级错误其实很常见。
4.6 本章知识结构
下面这张图帮你理清外参标定的核心逻辑:
4.7 实战:从棋盘格计算外参
实际标定时,我们通常用 PnP(Perspective-n-Point)算法从 2D-3D 对应点求解外参。OpenCV 提供了 solvePnP 函数:
// 输入:3D 世界点、2D 图像点、内参矩阵、畸变系数
// 输出:旋转向量 rvec、平移向量 tvec
cv::Mat rvec, tvec;
cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);
// 将旋转向量转为旋转矩阵
cv::Mat R;
cv::Rodrigues(rvec, R);
注意:solvePnP 默认使用迭代法,对初始值敏感。如果标定板在图像边缘,建议先用 solvePnPRansac 做鲁棒估计。
我个人习惯在标定前先检查一下 2D 点提取的精度。如果角点检测有 1 个像素的误差,外参的旋转误差可能达到 0.1°。对于四相机系统,0.1° 的误差在 2 米外就会产生 3.5mm 的偏差——这已经很大了。
4.8 避坑总结
- 旋转矩阵:别直接优化 9 个参数,用四元数或轴角
- 欧拉角:注意万向锁,限制 pitch 范围
- 四元数:记得归一化,否则矩阵不正交
- 平移向量:统一单位,别混用 mm 和 cm
- PnP 求解:用 RANSAC 版本抗噪
外参标定是四相机联合标定的基石。你把这个单相机的外参搞清楚了,后面把四个相机的外参统一到一个世界坐标系下,就只是矩阵乘法的事了。