相机几何基础:针孔相机模型、内参矩阵与外参矩阵、畸变模型

做三维重建这些年,我越来越觉得——相机几何是整个 pipeline 的基石。你想想看,如果连相机怎么成像都不清楚,后面那些三角化、BA 优化、点云融合,说白了都是在沙子上盖楼。

这一节,我们就来把相机几何的几个核心概念彻底讲透。我会结合自己踩过的坑,帮你把针孔模型、内外参矩阵、畸变模型这些看似枯燥的东西,变成你手头真正能用的工具。

1. 针孔相机模型:最朴素的成像原理

先问一个问题:一张照片是怎么来的?

最简单的解释就是针孔相机模型。想象一个密闭的盒子,前面开一个小孔,光线穿过小孔,在后面的感光平面上倒立成像。嗯,这就是最原始的相机。

数学上怎么描述这个过程?我们通常用相似三角形来建模。假设三维空间里有一个点 P = [X, Y, Z]^T,它通过小孔投影到成像平面上的点 p = [x, y]^T。那么有:

x = f * X / Z
y = f * Y / Z

这里的 f 就是焦距。注意,这个模型假设小孔无限小,没有透镜,没有畸变。实际相机当然不是这样,但它是我们理解一切相机几何的起点。

核心要点:针孔模型本质上是将三维空间到二维图像的映射,简化为一个中心投影。所有更复杂的相机模型,都是在这个基础上加修正项。

我个人习惯把针孔模型看作一个「黑盒」——输入是三维点,输出是像素坐标。至于中间怎么变换,就是接下来要讲的内参和外参。

2. 内参矩阵:从相机坐标系到像素坐标系

刚才的公式 x = f * X / Z 其实还差一步。成像平面上的物理坐标 (x, y) 怎么变成我们看到的像素坐标 (u, v)?

这里就需要内参矩阵 K 了。它负责把相机坐标系下的点,映射到像素坐标系。K 的典型形式是:

K = [fx,  0, cx;
     0,  fy, cy;
     0,   0,  1]

其中 fx, fy 是焦距在 x 和 y 方向上的像素度量,cx, cy 是光心在像素坐标系中的偏移。

为什么 fx 和 fy 可能不一样?因为像素不一定是正方形。我在项目中遇到过一台工业相机,它的像素是 5.5μm × 5.5μm,按理说 fx = fy,但实际标定出来总有微小差异。这很正常,因为镜头本身有制造公差。

我的经验:标定内参时,一定要用至少 20 张不同角度的棋盘格图像。我曾经只用 10 张就急着往下跑,结果重建出来的模型全是扭曲的。后来老老实实拍了 30 张,效果立竿见影。

内参矩阵的完整投影公式是:

u = fx * (X / Z) + cx
v = fy * (Y / Z) + cy

写成齐次坐标形式就是:

s * [u, v, 1]^T = K * [X, Y, Z, 1]^T

这里的 s 是尺度因子,其实就是 Z 值。嗯,这个齐次形式在后续的三角化和 BA 优化中会反复出现,建议你把它刻在脑子里。

3. 外参矩阵:从世界坐标系到相机坐标系

内参解决的是「相机内部怎么投影」,但相机在空间中的位置和朝向呢?这就需要外参矩阵了。

外参矩阵由旋转矩阵 R 和平移向量 t 组成:

[R | t]

它把世界坐标系下的点 P_w,变换到相机坐标系下的点 P_c:

P_c = R * P_w + t

你想想看,这个变换其实就是一个刚体变换——不改变物体的形状,只改变它的位置和朝向。

我记得有一次做室外场景重建,GPS 给的初始外参误差很大,导致相邻帧的匹配点对投影误差超过 50 个像素。后来我改用特征匹配 + PnP 来初始化外参,才把误差降下来。这里有个教训:外参的初始值非常重要,尤其是旋转矩阵,稍微偏一点,后面的优化就很难收敛。

避坑指南:我曾经在写代码时把 R 和 t 的顺序搞反了,结果重建出来的模型全部倒立。检查了半天才发现是矩阵乘法顺序的问题。记住:先旋转,后平移。

完整的投影公式,把内参和外参合起来就是:

s * [u, v, 1]^T = K * [R | t] * [X_w, Y_w, Z_w, 1]^T

这个公式,就是三维重建中最核心的投影方程。后面所有的几何计算,都绕不开它。

4. 畸变模型:现实世界的不完美

针孔模型是理想情况。实际相机有透镜,透镜就会引入畸变。最常见的两种是径向畸变和切向畸变。

径向畸变:光线经过透镜边缘时弯曲得更厉害,导致图像边缘的直线变弯。分为桶形畸变和枕形畸变。数学模型是:

x_distorted = x * (1 + k1 * r^2 + k2 * r^4 + k3 * r^6)
y_distorted = y * (1 + k1 * r^2 + k2 * r^4 + k3 * r^6)

其中 r^2 = x^2 + y^2,k1, k2, k3 是径向畸变系数。

切向畸变:透镜和成像平面不平行导致的。模型是:

x_distorted = x + [2 * p1 * x * y + p2 * (r^2 + 2 * x^2)]
y_distorted = y + [p1 * (r^2 + 2 * y^2) + 2 * p2 * x * y]

p1, p2 是切向畸变系数。

关键点:畸变校正的顺序很重要。先校正畸变,再投影到像素坐标系。顺序反了,结果全错。

我建议你在实际项目中,用 OpenCV 的 cv::calibrateCamera() 来标定畸变参数。它返回的就是 k1, k2, p1, p2, k3 这五个参数。注意,k3 通常只在鱼眼镜头中才需要,普通镜头用 k1, k2 就够了。

为什么要校正畸变?因为三维重建中,我们假设光线是直线传播的。如果图像有畸变,三角化出来的三维点位置就会偏。说白了,畸变校正就是让现实相机「变回」针孔模型。

5. 知识体系总览

下面这张图,是我自己总结的相机几何知识结构。你可以把它当作一个「地图」,随时回来对照。

相机几何知识体系 相机几何基础 针孔相机模型 内参矩阵 K 外参矩阵 [R|t] 相似三角形投影 中心投影假设 fx, fy, cx, cy 像素坐标系映射 旋转矩阵 R 平移向量 t 畸变模型(径向 + 切向) 径向畸变 k1, k2, k3 切向畸变 p1, p2 畸变校正流程

6. 总结与实用建议

好了,这一节的内容就到这里。我们来快速回顾一下:

  • 针孔模型:最基础的成像模型,用相似三角形描述三维到二维的投影。
  • 内参矩阵:把相机坐标系下的点映射到像素坐标,包含焦距和光心偏移。
  • 外参矩阵:把世界坐标系下的点变换到相机坐标系,包含旋转和平移。
  • 畸变模型:修正透镜带来的径向和切向畸变,让现实相机逼近针孔模型。

我的建议:如果你刚开始做三维重建,先把相机标定这一步做扎实。标定结果的好坏,直接决定了后续重建的精度。我一般会用 OpenCV 的标定工具,配合棋盘格,反复标定三次取平均。别嫌麻烦,这一步值得花时间。

最后说一句:相机几何看起来是基础,但很多高级算法的问题,追根溯源都是这里没搞透。你想想看,如果连投影方程都写不对,后面的多视图几何、BA 优化怎么可能跑得通?


专注资料整理