3. 相机成像模型:针孔模型、畸变模型与内外参矩阵
做手眼标定,说白了就是在回答一个问题:相机看到的像素点,到底对应真实世界哪个位置?
这个问题不搞清楚,后面标定、抓取、测量全是空中楼阁。我见过不少项目,标定精度上不去,最后查来查去,根源就是成像模型理解不到位。
这一章,咱们就把相机成像这件事彻底聊透。从最简单的针孔模型开始,再到畸变补偿,最后把内参、外参矩阵的含义掰开揉碎。
3.1 针孔模型:理想世界的投影
针孔模型是相机成像的“理想状态”。你想象一个暗箱,前面戳个小孔,光线穿过小孔,在后面的感光面上成像。
这个模型有三个关键假设:
- 光线直线传播,没有折射
- 小孔无限小,没有衍射
- 成像面是平面
当然,现实中没有这么完美的相机。但针孔模型给了我们一个数学起点。
它的核心公式很简单:
// 从世界坐标到像素坐标的映射
// 齐次坐标形式
λ * [u, v, 1]^T = K * [R|t] * [X, Y, Z, 1]^T
这里 λ 是尺度因子,K 是内参矩阵,[R|t] 是外参矩阵。后面咱们一个一个拆解。
关键理解:针孔模型是线性模型,它假设图像坐标和世界坐标之间是简单的比例关系。但实际镜头总会引入畸变,所以我们需要在标定时先补偿畸变,再用针孔模型去解算。
3.2 畸变模型:现实世界的修正
现实中的镜头,尤其是广角镜头,拍出来的照片边缘会有明显的弯曲。这就是畸变。
畸变主要分两类:径向畸变和切向畸变。
3.2.1 径向畸变
径向畸变是沿着镜头半径方向的变形。离光心越远,变形越明显。
- 桶形畸变:图像向外凸出,像桶的形状。广角镜头常见。
- 枕形畸变:图像向内凹陷,像枕头。长焦镜头常见。
数学上,我们用泰勒级数来建模:
// 径向畸变修正
x_corrected = x * (1 + k1 * r^2 + k2 * r^4 + k3 * r^6)
y_corrected = y * (1 + k1 * r^2 + k2 * r^4 + k3 * r^6)
其中 r 是像素点到光心的距离,k1、k2、k3 是径向畸变系数。
我的经验:对于普通工业镜头,用 k1、k2 两个参数就够了。k3 通常用于鱼眼镜头或畸变特别大的情况。我在一个项目里用过鱼眼镜头,不加 k3 的话,图像边缘的误差能到十几个像素。
3.2.2 切向畸变
切向畸变是由于镜头和成像面不平行造成的。说白了,就是镜头装歪了。
它的修正公式:
// 切向畸变修正
x_corrected = x + [2 * p1 * x * y + p2 * (r^2 + 2 * x^2)]
y_corrected = y + [p1 * (r^2 + 2 * y^2) + 2 * p2 * x * y]
p1、p2 是切向畸变系数。
注意:切向畸变通常很小,但如果你用的是高精度测量场景(比如0.01mm精度),它就不能忽略。我曾经在一个PCB检测项目里忽略了切向畸变,结果边缘定位误差一直降不下去,加上p1、p2后问题才解决。
3.3 内参矩阵:相机的“内部密码”
内参矩阵 K 描述了相机内部的几何特性。它包含以下参数:
| 参数 | 符号 | 含义 |
|---|---|---|
| 焦距 | fx, fy | 镜头光心到成像面的距离,单位像素 |
| 主点 | cx, cy | 光轴与成像面的交点,通常不在图像正中心 |
| 倾斜因子 | s | 像素坐标系x轴和y轴的不垂直度,通常为0 |
内参矩阵的数学形式:
K = [fx, s, cx]
[ 0, fy, cy]
[ 0, 0, 1]
为什么主点不在中心?因为镜头安装有误差,成像面也不可能居中。我标定过几十台相机,主点偏移几十个像素是常事。所以千万别假设主点在图像正中心。
3.4 外参矩阵:相机在空间中的“位置”
外参矩阵 [R|t] 描述了相机坐标系相对于世界坐标系的旋转和平移。
- R:3x3旋转矩阵,表示相机的朝向
- t:3x1平移向量,表示相机的位置
外参矩阵的作用:把世界坐标系中的点,转换到相机坐标系下。
// 世界坐标到相机坐标
X_cam = R * X_world + t
手眼标定的核心:我们标定的就是相机和机器人末端之间的外参关系。说白了,就是找到相机坐标系和机器人坐标系之间的那个[R|t]。
3.5 完整成像流程:从世界到像素
把上面所有内容串起来,一个3D点变成像素点的完整流程是这样的:
- 世界坐标 → 相机坐标:通过外参矩阵 [R|t]
- 相机坐标 → 归一化平面:除以Z值,得到归一化坐标 (x, y)
- 畸变修正:对归一化坐标应用径向和切向畸变模型
- 归一化平面 → 像素坐标:通过内参矩阵 K 映射到像素
这个流程,HALCON 的标定算子 camera_calibration 已经帮我们封装好了。但理解每一步在做什么,对调试标定结果非常有帮助。
避坑指南:我曾经在标定时发现重投影误差很大,查了半天发现是畸变参数顺序搞反了。HALCON 的畸变参数顺序是 (k1, k2, p1, p2, k3),和 OpenCV 不一样。这个细节不注意,标定结果直接崩。
3.6 知识结构图
下面这张图把相机成像模型的整体脉络画出来了,方便你对照理解:
3.7 小结
这一章的内容,是后面所有标定工作的数学基础。你不需要把公式背下来,但一定要理解:
- 针孔模型是理想情况,实际必须考虑畸变
- 内参矩阵是相机的固有属性,标定一次就能用很久
- 外参矩阵是相机在空间中的位姿,每次移动都要重新标定
嗯,把这些概念吃透,后面讲标定流程的时候,你就能明白每一步在干什么了。