第二章 成像模型:针孔相机模型详解、世界坐标系到像素坐标系的四大变换
聊到单目视觉标定,绕不开的第一个核心概念就是——针孔相机模型。
很多人觉得这东西太理论,上来就想直接调OpenCV的calibrateCamera()。我刚开始做视觉的时候也这么干过,结果标出来的参数怎么都不对,后来才发现是连最基本的成像模型都没吃透。说白了,你连相机怎么把三维世界变成二维图像的都不清楚,标定出来的内参外参你敢用吗?
2.1 针孔相机模型——最朴素的成像原理
针孔相机模型,名字很形象。想象一个密闭的盒子,前面戳一个小孔,光线穿过小孔在后面的感光面上成像。这就是最原始的相机。
数学上,我们用光心(小孔的位置)、成像平面(感光面)、焦距(光心到成像平面的距离)来描述这个过程。
核心假设:针孔模型假设所有光线都直线传播,且只通过光心这一个点。实际镜头有畸变,那是后面章节要处理的事。
这里有个关键点:针孔成像是倒立的。为了数学上方便,我们通常把成像平面“虚拟”地翻到光心前面,这样图像就是正立的,计算也简单很多。这个虚拟平面叫归一化平面。
我的习惯:在推导公式时,我永远用虚拟成像平面。它让坐标系变换变得非常直观,不容易搞混正负号。
2.2 四大坐标系——从世界到像素的“接力赛”
一个三维点怎么变成图像上的像素?中间要经过四次坐标变换。我把它叫做“接力赛”:
- 世界坐标系 → 相机坐标系(刚体变换)
- 相机坐标系 → 图像物理坐标系(透视投影)
- 图像物理坐标系 → 图像像素坐标系(离散化)
等等,题目说四大变换,这里只有三个?别急,第四个其实是畸变校正,它穿插在第二步和第三步之间。我们先把前三步讲透。
2.2.1 世界坐标系 → 相机坐标系(外参登场)
世界坐标系是客观的,相机坐标系是以相机光心为原点的。两者之间差了一个旋转和一个平移。
数学表达:
P_c = R * P_w + t
其中:
P_w:世界坐标系下的点 (X, Y, Z)R:3x3 旋转矩阵t:3x1 平移向量P_c:相机坐标系下的点 (X_c, Y_c, Z_c)
我曾经踩过的坑:旋转矩阵有9个参数,但自由度只有3。直接用9个参数去优化,结果矩阵不再正交,标定出来的外参完全不能用。后来我改用旋转向量(Rodrigues)表示,才解决了这个问题。
2.2.2 相机坐标系 → 图像物理坐标系(透视投影)
这一步是真正的“成像”。根据相似三角形原理:
x = f * X_c / Z_c
y = f * Y_c / Z_c
这里 (x, y) 是图像物理坐标,单位是毫米。f 是焦距。
你想想看,这里出现了除法,所以这个变换是非线性的。这也是为什么相机标定不能简单地用线性代数一步求解的原因。
2.2.3 图像物理坐标系 → 图像像素坐标系(离散化)
物理坐标是连续的,像素坐标是离散的。我们需要把毫米转换成像素:
u = x / dx + u0
v = y / dy + v0
其中:
dx, dy:每个像素的物理尺寸(毫米/像素)(u0, v0):主点坐标(光心在像素坐标系下的位置)
把上面三步合并,写成齐次坐标形式,就是大名鼎鼎的相机内参矩阵 K:
K = [fx 0 u0
0 fy v0
0 0 1]
其中 fx = f/dx,fy = f/dy。
注意:fx 和 fy 通常不相等,因为像素不是完美的正方形。这也是标定要解的参数之一。
2.3 完整的投影方程
把外参和内参合在一起,一个三维点 P_w 到像素坐标 p 的完整变换是:
p = K * [R | t] * P_w
用齐次坐标展开:
s * [u, v, 1]^T = K * [R | t] * [X, Y, Z, 1]^T
这里的 s 是尺度因子,等于 Z_c。为什么会有它?因为从3D到2D丢失了深度信息,同一个像素点对应的是空间中的一条射线。
2.4 知识结构总览
下面这张图,是我做标定项目时一定会贴在工位上的。它把整个成像模型串起来了:
2.5 畸变——理想模型的“现实修正”
针孔模型是理想情况。实际镜头有加工误差,光线不是完美直线。这就引出了畸变。
畸变主要分两类:
| 畸变类型 | 产生原因 | 数学模型 | 典型表现 |
|---|---|---|---|
| 径向畸变 | 镜头曲率不完美 | δr = k1*r^3 + k2*r^5 + k3*r^7 | 桶形(广角)、枕形(长焦) |
| 切向畸变 | 镜头与感光面不平行 | δx = 2*p1*x*y + p2*(r^2+2*x^2) | 图像倾斜、梯形失真 |
我的经验:对于手机镜头或广角摄像头,径向畸变的前两项(k1, k2)就够用了。但对于鱼眼镜头,必须用到 k3 甚至更高阶项。切向畸变一般很小,p1, p2 通常接近零。
2.6 标定到底在标什么?
现在可以回答这个问题了。相机标定,就是求解:
- 内参:fx, fy, u0, v0, k1, k2, p1, p2(可能还有 k3)
- 外参:每张标定图片对应的 R 和 t
你想想看,一个内参加若干外参,少说几十个未知数。怎么解?靠的是多张不同角度的标定板图片,建立超定方程组,然后用最小二乘法优化。
我曾经犯过的错:一开始只拍了3张标定板图片,觉得够了。结果标出来的内参,换一组图片就变。后来才知道,标定板图片至少要10-20张,而且必须覆盖视野的各个区域——中心、边缘、倾斜、旋转,缺一不可。