第三章 相机外参标定:旋转矩阵与平移向量
各位同学,今天我们来聊聊相机外参标定。说白了,外参就是描述相机在真实世界里「站在哪、朝哪看」的那组参数。我刚开始接触这个时,总觉得内参才是核心,外参不就是个坐标变换嘛?后来在实车调试中吃了大亏——外参差个几毫米,融合结果直接崩掉。
3.1 旋转矩阵与平移向量
外参由两部分组成:旋转矩阵 R 和 平移向量 t。它们共同描述了从世界坐标系到相机坐标系的刚体变换。
旋转矩阵 R 是个 3×3 的正交矩阵,满足 RTR = I,行列式为 +1。它表示三个轴的旋转。你想想看,一个物体在三维空间里转来转去,用欧拉角表示会有万向锁问题,用四元数又不够直观。我个人习惯用旋转矩阵,虽然参数多了点,但数学性质好,后续优化方便。
平移向量 t 是个 3×1 的向量,表示相机光心在世界坐标系中的位置。注意,这个位置是相对于世界原点的偏移量。
核心公式:
P_c = R * P_w + t
其中 P_w 是世界坐标点,P_c 是相机坐标点。
我在项目中遇到过一个问题:用 ROS 的 tf 树直接拿外参,结果发现旋转矩阵不满足正交性。查了半天,原来是有人手动修改了参数文件,破坏了矩阵结构。嗯,这里要注意——旋转矩阵必须严格正交,否则后续的三角测量全是错的。
3.2 外参标定流程
外参标定,说白了就是求解 R 和 t。流程大致如下:
- 准备标定板:棋盘格或圆点阵,尺寸要精确测量
- 采集图像:至少 10-20 张不同位姿的图像
- 提取角点:用 OpenCV 的 findChessboardCorners
- 求解外参:基于 PnP 算法(Perspective-n-Point)
- 优化:用非线性最小二乘(如 Levenberg-Marquardt)微调
这里我分享一个经验:采集图像时,标定板要覆盖整个视野,尤其是边缘区域。我曾经偷懒只拍了中间区域,结果标出来的外参在边缘误差巨大,融合后的点云直接扭曲了。
避坑指南:我曾经用单张图像做 PnP 求解,结果外参精度完全不够。后来改用多张图像联合优化,误差从 5 厘米降到了 2 毫米。记住:多视图约束是王道。
代码实现上,OpenCV 提供了现成的接口:
// C++ 示例:使用 solvePnP 求解外参
cv::Mat rvec, tvec;
cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);
cv::Mat R;
cv::Rodrigues(rvec, R); // 旋转向量转旋转矩阵
注意,solvePnP 返回的是旋转向量,需要用 Rodrigues 公式转成旋转矩阵。我刚开始总忘记这步,直接拿旋转向量去乘坐标,结果可想而知。
3.3 手眼标定与车辆安装标定
这两个概念容易混淆,我简单区分一下:
- 手眼标定:标定相机与机械臂末端之间的变换关系。典型场景是机器人抓取。
- 车辆安装标定:标定相机与车辆底盘之间的变换关系。典型场景是自动驾驶。
手眼标定有两种经典形式:
| 类型 | 公式 | 说明 |
|---|---|---|
| 眼在手上(Eye-in-Hand) | AX = XB | 相机固定在机械臂末端 |
| 眼在手外(Eye-to-Hand) | AX = XB | 相机固定在外部,观察机械臂 |
你想想看,为什么两种形式都是 AX = XB?因为本质上都是在求解一个齐次变换矩阵 X,使得两个坐标系之间的约束成立。我当年推导这个公式时,画了整整一页的坐标系变换图才搞明白。
车辆安装标定相对简单一些。通常我们已知车辆后轴中心作为车体坐标系原点,然后通过以下步骤求解:
- 将车辆停在标定场地,测量相机在车体坐标系下的粗略位置
- 用标定板或已知特征点,建立世界坐标系与相机坐标系的对应关系
- 通过最小二乘优化,精确求解 R 和 t
重要提醒:车辆安装标定必须在平坦地面上进行。我曾经在略有坡度的停车场做标定,结果外参的俯仰角偏差了 0.5 度。别小看这 0.5 度,在 50 米外,投影误差能达到 0.4 米,直接导致车道线检测错位。
实际工程中,我推荐使用 Tsai 算法 做手眼标定,它基于四元数分解,数值稳定性好。对于车辆安装标定,我习惯用 非线性优化 方法,把重投影误差作为代价函数,用 Ceres Solver 或 g2o 求解。
下面是我画的一张流程图,帮你理清整个外参标定的知识体系:
最后说一句,外参标定不是一次性工作。车辆在使用过程中,由于振动、碰撞或温度变化,外参会发生微小漂移。我建议每 3 个月或每 5000 公里做一次外参校验。如果发现融合结果出现系统性偏差,优先检查外参。
好了,这一章的内容就到这里。记住:外参是感知融合的基石,地基不稳,上层建筑全是空中楼阁。