2. 针孔相机模型:内参矩阵K的推导,焦距、主点偏移的物理意义
说到相机模型,我第一个想到的就是针孔模型。它是最基础、最经典的成像模型。你想想看,一个暗箱,前面戳个小孔,外面的光线穿过小孔,在后面的感光面上形成倒像——就这么简单。但就是从这个简单模型里,我们推导出了整个视觉几何的基石:内参矩阵K。
我在做多相机融合项目时,发现很多同事对K矩阵的理解停留在“公式背下来就行”。结果一遇到畸变大的镜头、或者需要手动标定主点偏移时,就抓瞎了。所以这一节,咱们把K矩阵的来龙去脉彻底捋清楚。
2.1 从物理世界到像素坐标
先理清一条线:三维空间中的一个点,是怎么变成照片上一个像素的?
- 世界坐标系 → 相机坐标系(刚体变换,外参干的活)
- 相机坐标系 → 成像平面坐标系(透视投影,针孔模型干的活)
- 成像平面坐标系 → 像素坐标系(离散化、缩放、平移,内参干的活)
内参矩阵K,管的就是最后两步。说白了,它描述的是“相机内部怎么把光线转换成像素”。
核心观点:K矩阵把相机坐标系下的三维点 (X, Y, Z) 映射到像素坐标 (u, v)。这个映射是透视投影 + 仿射变换的组合。
2.2 针孔模型的几何关系
假设相机坐标系下有一个点 P = (X, Y, Z)。它通过针孔投影到成像平面上。根据相似三角形,成像平面上的坐标 (x, y) 满足:
x = f * X / Z
y = f * Y / Z
这里的 f 是物理焦距,单位是毫米。注意,成像平面在针孔后方,所以像是倒的。但我们在数学上通常把成像平面“翻”到针孔前方,这样公式里就没有负号了。我个人习惯用这种“虚拟成像平面”来推导,省心。
好,现在 (x, y) 还是连续的物理坐标(毫米)。下一步,我们要把它变成离散的像素坐标 (u, v)。
2.3 从毫米到像素:内参矩阵的诞生
这一步涉及两个操作:
- 缩放:每个像素在感光元件上有物理尺寸,比如 dx 毫米/像素、dy 毫米/像素。
- 平移:成像平面的原点(光轴与成像平面的交点)通常不在像素坐标系的原点(通常是图像左上角),所以需要加一个偏移量。
写成公式就是:
u = (x / dx) + cx
v = (y / dy) + cy
把 x = f * X / Z 和 y = f * Y / Z 代进去:
u = (f / dx) * (X / Z) + cx
v = (f / dy) * (Y / Z) + cy
令 fx = f / dx,fy = f / dy,这就是我们常说的等效焦距,单位是像素。然后写成齐次坐标形式:
Z * [u] = [fx 0 cx] * [X]
[v] [ 0 fy cy] [Y]
[1] [ 0 0 1] [Z]
中间那个 3x3 矩阵,就是内参矩阵 K。
我的经验:实际标定时,fx 和 fy 往往不相等。因为感光元件的像素不一定是正方形,或者镜头有轻微的拉伸。别硬把它们设成一样,除非你用的是完美正方形像素的传感器——现实中很少见。
2.4 焦距的物理意义
fx 和 fy 的单位是像素。它们综合了两个物理量:
- 物理焦距 f:镜头的光学属性,单位毫米。焦距越长,视角越窄,远处物体看起来越大。
- 像素密度 1/dx、1/dy:感光元件的分辨率,单位像素/毫米。同样的物理焦距,像素密度越大,fx 越大,图像看起来越“放大”。
举个例子:两个相机,物理焦距都是 4mm。一个传感器像素尺寸 2μm,另一个 4μm。前者的 fx = 4 / 0.002 = 2000 像素,后者 fx = 4 / 0.004 = 1000 像素。同样的场景,前者拍出来的图像在像素上更“宽”。
避坑指南:我曾经在融合两个不同分辨率的相机时,直接把它们的 fx 当成“焦距”来比较,结果空间映射一塌糊涂。后来才意识到,fx 是物理焦距和像素尺寸的乘积,不能直接对比。要对比物理焦距,得用 fx * dx 反算回去。
2.5 主点偏移的物理意义
主点 (cx, cy) 是光轴与成像平面的交点。理想情况下,它应该在图像正中心。但实际中,由于镜头安装误差、传感器封装偏移,主点往往不在中心。
主点偏移的影响:
- 它决定了像素坐标系的“零点”在哪里。
- 在做像素坐标和相机坐标的互相转换时,主点偏移必须精确补偿。
- 对于广角镜头或鱼眼镜头,主点偏移的影响更明显。
我记得有一次标定一个工业相机,标定出来的 cx 偏离中心 15 个像素。一开始我以为是标定出错了,反复标了三次,结果都一样。后来拆开相机一看,传感器确实贴歪了。嗯,这就是主点偏移的物理来源。
2.6 内参矩阵的完整形式
有些教材还会在 K 矩阵里加一个扭曲参数 s:
K = [fx s cx]
[ 0 fy cy]
[ 0 0 1]
s 描述的是像素坐标系的 u 轴和 v 轴不垂直的程度。对于大多数现代相机,s 非常接近 0,可以忽略。但如果你用的是老式 CCD 相机或者扫描式相机,s 可能不可忽略。
总结一下:内参矩阵 K 包含 4 个核心参数(fx, fy, cx, cy),加上可选的 s,总共 5 个内参。它们描述了从相机坐标系到像素坐标系的完整映射。
2.7 知识结构总览
下面这张图把整个推导过程串起来了。我建议你多看几遍,把每个箭头对应的物理意义搞清楚。
2.8 内参矩阵在SLAM中的角色
在SLAM系统里,内参矩阵K几乎无处不在:
| 应用场景 | K矩阵的作用 |
|---|---|
| 特征点三角化 | 将像素坐标反投影到归一化平面,再结合深度恢复3D点 |
| 重投影误差计算 | 将3D点投影回像素坐标,与观测到的像素坐标比较 |
| 本质矩阵/基础矩阵 | 需要K矩阵将像素坐标归一化,才能计算本质矩阵 |
| 多相机融合 | 每个相机有自己的K,融合前必须统一到同一个坐标系 |
| 畸变校正 | 校正后的像素坐标需要K矩阵重新映射到原始图像 |
我的建议:在做异构相机融合时,先把每个相机的K矩阵标定准确。我见过太多项目,花大量时间调融合算法,结果问题出在内参标定上——fx 差了 0.5 个像素,融合出来的点云就错位了。内参是地基,地基不稳,上层建筑再漂亮也没用。
2.9 一个简单的数值例子
假设一个相机:
- 物理焦距 f = 5 mm
- 像素尺寸 dx = dy = 0.004 mm/pixel(4μm)
- 图像分辨率 1920×1080
- 主点偏移 cx = 960, cy = 540(理想中心)
那么:
fx = 5 / 0.004 = 1250 像素
fy = 5 / 0.004 = 1250 像素
K = [1250 0 960]
[ 0 1250 540]
[ 0 0 1]
现在,相机坐标系下有一个点 P = (0.5m, 0.3m, 2.0m)。它在图像上的像素坐标是:
u = 1250 * 0.5 / 2.0 + 960 = 1272.5
v = 1250 * 0.3 / 2.0 + 540 = 727.5
这个点会出现在图像的第1273列、第728行附近。你看,整个过程就是这么直接。
注意:实际项目中,像素坐标是离散的整数。但计算出来的 u, v 通常是浮点数。在做重投影时,我们一般保留浮点精度,只在最终显示或提取像素值时取整。我曾经因为提前取整,导致三角化出来的3D点精度损失了将近1厘米——教训深刻。