一、相机模型与成像原理

大家好,我是你们这门课的主讲。今天咱们聊聊相机模型,这是整个多视图几何的基石。说白了,就是搞明白「世界上的一个点,是怎么跑到照片上的那个像素位置去的」。

我刚开始做3D重建那会儿,觉得相机模型太简单了,不就是小孔成像嘛。结果第一次标定相机,出来的内参矩阵奇奇怪怪,重建的模型歪七扭八。嗯,后来老老实实把每个坐标系捋了一遍,才算是真正入了门。

1.1 针孔相机模型

先看最经典的模型——针孔相机。你想想看,一个暗箱,前面戳个小孔,光线穿过小孔,在后面的胶片上成像。这就是最朴素的成像原理。

数学上怎么描述?假设世界中有个点 P,坐标为 (X, Y, Z)。它通过小孔(光心)后,在成像平面上形成点 p,坐标为 (x, y)。根据相似三角形:

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

这里的 f 是焦距,也就是小孔到成像平面的距离。注意,这个模型有个特点:成像是倒立的。不过在实际的相机中,传感器会帮你把图像正过来,所以我们通常假设成像平面在光心前方,这样计算更方便。

核心要点:针孔模型是线性模型,它假设光线直线传播,没有畸变。但现实中的镜头总会引入一些非线性失真,后面我们会讲畸变模型。

1.2 相机内参矩阵

刚才的公式 (x, y) 还是物理坐标(单位是毫米),但我们要的是像素坐标(单位是像素)。这就需要一个转换——从物理世界到像素世界的桥梁,就是内参矩阵 K

内参矩阵长这样:

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

其中:

  • fx, fy:分别是 x 和 y 方向的焦距(以像素为单位)。为什么有两个?因为传感器像素可能不是正方形,或者有缩放。
  • cx, cy:主点坐标,也就是光轴与成像平面的交点。理想情况下在图像中心,但实际会有偏移。

我个人习惯把内参矩阵理解为「相机自己的身份证」。每个相机都有自己独一无二的内参,它决定了空间中的点怎么映射到像素坐标。我在项目中遇到过一台工业相机,标定后发现 cx 偏离中心十几个像素,一开始以为是标定出错了,后来查手册才知道是传感器封装时就有偏移。

小技巧:如果你用 OpenCV 标定,内参矩阵通常用 cameraMatrix 这个变量名。记得检查 fx 和 fy 是否接近,如果差太多,可能是标定板没放平。

1.3 相机外参矩阵

内参管的是「相机内部怎么成像」,外参管的是「相机在世界上什么位置、朝哪个方向看」。外参矩阵由两部分组成:旋转矩阵 R平移向量 t

外参矩阵通常写成 4×4 的齐次形式:

[ R | t ]
[ 0 | 1 ]

它的作用是把世界坐标系中的点,变换到相机坐标系中。举个例子:你站在天安门广场拍照,你的相机位置就是 t,你转头的角度就是 R。不同位置、不同角度拍同一个建筑,外参就不一样。

我曾经犯过一个低级错误:把旋转矩阵和平移向量的顺序搞反了。结果重建出来的点云,所有物体都跑到相机后面去了。排查了半天才发现是外参矩阵的乘法顺序错了。嗯,这里要注意:先旋转,再平移,顺序不能乱。

1.4 世界坐标系到像素坐标的完整映射

把上面所有步骤串起来,一个世界点 P_w 到像素点 p 的完整流程是:

  1. 世界 → 相机:P_c = R * P_w + t
  2. 相机 → 归一化平面:x_n = X_c / Z_c, y_n = Y_c / Z_c
  3. 归一化平面 → 像素:u = fx * x_n + cx, v = fy * y_n + cy

写成矩阵形式就是:

p = K * [R | t] * P_w

这个公式,我建议你刻在脑子里。整个多视图几何,从三角测量到光束法平差,全是在这个公式的基础上做文章。

一句话总结:内参 K 告诉你「相机长什么样」,外参 [R|t] 告诉你「相机在哪、朝哪看」。两者结合,才能把世界坐标变成像素坐标。

1.5 镜头畸变模型

现实中的镜头不是完美的针孔。为了收集更多光线、减少像差,镜头会引入畸变。最常见的两种是:

  • 径向畸变:光线经过透镜边缘时弯曲得更厉害,导致图像边缘的直线变弯。分为桶形畸变(负)和枕形畸变(正)。
  • 切向畸变:镜头和传感器不平行,导致图像倾斜。

畸变模型通常用多项式来描述:

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

其中 k1, k2, k3 是径向畸变系数,p1, p2 是切向畸变系数。r 是点到主点的距离。

我记得第一次做鱼眼相机标定,畸变系数 k1 大得离谱,校正后的图像边缘像被揉过的纸。后来发现鱼眼相机需要特殊的畸变模型(比如等距投影模型),不能用普通的多项式模型硬套。

避坑指南:我曾经在标定一个广角镜头时,只用了 k1 和 k2,结果图像边缘的畸变校正不干净。后来加上 k3 才搞定。建议:如果镜头视角超过 90°,至少用 3 个径向畸变参数。

1.6 相机标定基础

标定,说白了就是求内参和畸变系数。最经典的方法是张正友标定法,用棋盘格标定板,拍十几张不同角度的照片,然后解方程。

标定的基本步骤:

  1. 打印一张棋盘格标定板,贴在平面上
  2. 用相机从不同角度拍摄 10-20 张照片
  3. 检测每张照片中的角点坐标
  4. 利用角点的世界坐标(已知)和像素坐标(检测得到),求解内参和畸变

这里有个关键点:标定板必须平整。我见过有人把标定板贴在弯曲的纸箱上,标定出来的内参全是错的。还有,照片要覆盖整个视场,尤其是边缘区域,否则畸变参数估计不准。

我的经验:标定时,让标定板在画面中占 1/3 到 1/2 的面积,不要太远也不要太近。角度变化要丰富,俯仰、偏航、旋转都要有。这样标定出来的参数才鲁棒。

标定完成后,你会得到内参矩阵 K 和畸变系数 (k1, k2, k3, p1, p2)。有了这些,你就可以对任意一张图像做畸变校正,然后进行后续的 3D 重建工作了。

相机模型与成像流程 世界坐标系 P_w = (X, Y, Z) 外参 [R|t] 相机坐标系 P_c = (X_c, Y_c, Z_c) 透视投影 归一化平面 (x_n, y_n) = (X_c/Z_c, Y_c/Z_c) 内参 K 像素坐标 (u, v) 畸变校正 (k1,k2,k3,p1,p2) 完整映射公式 p = K · [R | t] · P_w 内参 K 决定「怎么成像」,外参 [R|t] 决定「在哪拍」 相机标定流程(张正友法) ① 拍摄棋盘格标定板(10-20张不同角度) ② 检测角点 → ③ 求解内参 K 和畸变系数 ④ 优化参数(最小化重投影误差) 输出:K, k1, k2, k3, p1, p2

好了,这一章的内容就到这里。相机模型是基础中的基础,后面的三角测量、PnP、光束法平差,全都建立在这个框架之上。建议你动手写一段代码,用 OpenCV 标定一下自己的手机相机,感受一下从世界坐标到像素坐标的完整流程。


公众号:蓝海资料掘金营,微信deep3321