4. 相机模型与成像原理

做标定这么多年,我越来越觉得,搞懂相机模型是标定工程师的「基本功」。你想想看,如果连相机怎么成像的都不清楚,那标定出来的参数你敢用吗?

这一章,咱们就把相机模型彻底掰开揉碎。从最简单的针孔模型讲起,再到畸变模型,最后把内参和外参矩阵说清楚。嗯,这些概念会贯穿整个课程,所以这一章值得你多花点时间。

核心一句话:相机标定,本质上就是求解内参矩阵、外参矩阵和畸变系数的过程。模型越准,标定结果越可靠。

4.1 针孔模型:最朴素的成像原理

针孔模型,说白了就是初中物理课上那个小孔成像实验。光线穿过一个小孔,在后面的平面上形成倒立的像。相机镜头虽然复杂,但核心思想是一样的——把三维世界投影到二维图像上。

我刚开始做视觉项目时,总觉得针孔模型太简单,实际用不上。后来才发现,所有复杂的相机模型都是在这个基础上加修正。你把这个搞懂了,后面学什么都快。

针孔模型的数学表达,其实就是四个坐标系之间的转换:

  • 世界坐标系(World):我们放标定板的地方,单位是毫米或米
  • 相机坐标系(Camera):以相机光心为原点,Z轴指向镜头前方
  • 图像坐标系(Image):在成像平面上,单位是毫米
  • 像素坐标系(Pixel):就是我们最终看到的图像,单位是像素

从世界坐标到像素坐标,一共三步:

  1. 世界坐标 → 相机坐标(外参矩阵搞定)
  2. 相机坐标 → 图像坐标(针孔投影公式)
  3. 图像坐标 → 像素坐标(内参矩阵搞定)

公式长这样:

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

其中 s 是尺度因子,K 是内参矩阵,[R | t] 是外参矩阵。别被公式吓到,后面咱们一个一个拆开看。

4.2 畸变模型:现实世界没有完美的镜头

针孔模型是理想情况。现实中的镜头有透镜,透镜就会带来畸变。我遇到过不少新手,标定完发现误差很大,其实就是没处理好畸变。

畸变主要分两类:

畸变类型 产生原因 视觉效果 数学参数
径向畸变 透镜形状不完美,边缘光线偏折更大 直线变弯,像鱼眼效果 k1, k2, k3
切向畸变 透镜与成像平面不平行 图像倾斜,像被拉伸 p1, p2

4.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 只在畸变特别大的镜头(比如鱼眼)才用。

我的经验:标定径向畸变时,标定板一定要拍到图像的边缘区域。如果只拍中心区域,畸变参数根本算不准。我曾经因为这个吃过亏,后来每次标定都刻意让标定板靠近图像四角。

4.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 就是切向畸变系数。大多数工业镜头的切向畸变很小,但廉价镜头或手机镜头就比较明显。

注意:畸变参数不是越多越好。盲目增加 k3 或高阶项,可能导致过拟合。我一般先用 k1、k2、p1、p2 四个参数,如果重投影误差还大,再考虑加 k3。

4.3 内参矩阵:相机的「身份证」

内参矩阵 K 描述了相机内部的几何特性。它把相机坐标系下的点,映射到像素坐标系。

内参矩阵长这样:

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

四个参数的含义:

参数 含义 单位
fx x方向的焦距(像素单位) 像素
fy y方向的焦距(像素单位) 像素
cx 主点x坐标(光心在图像上的位置) 像素
cy 主点y坐标(光心在图像上的位置) 像素

fx 和 fy 理论上应该相等,但实际制造中会有微小差异。cx 和 cy 一般在图像中心附近,但不一定正好在正中心。

内参矩阵一旦标定好,只要不换镜头、不变焦距,就可以一直用。这也是为什么我们标定一次能用很久。

4.4 外参矩阵:相机在空间中的「位置和姿态」

外参矩阵描述的是相机在世界坐标系中的位置和朝向。它由两部分组成:

  • 旋转矩阵 R:3×3 矩阵,描述相机的朝向
  • 平移向量 t:3×1 向量,描述相机的位置

外参矩阵的完整形式:

[R | t] = [r11, r12, r13, t1]
          [r21, r22, r23, t2]
          [r31, r32, r33, t3]

旋转矩阵 R 有三个自由度,可以用欧拉角(俯仰角、偏航角、翻滚角)或四元数表示。平移向量 t 就是相机光心在世界坐标系中的坐标。

外参矩阵的特点是:每拍一张标定板图片,外参都不一样。因为标定板的位置变了,或者相机动了。这也是为什么标定需要多张图片——每张图片都提供一组外参约束,共同求解内参。

4.5 知识结构总览

下面这张图,把相机模型的核心逻辑串起来了。我建议你多看几遍,把每个模块之间的关系理清楚。

相机模型与成像原理知识结构图 相机模型与成像原理 · 知识结构 世界坐标系 (Xw, Yw, Zw) 外参矩阵 [R | t] 相机坐标系 (Xc, Yc, Zc) 针孔投影 (归一化平面) 畸变模型 (径向+切向) 内参矩阵 K → 像素坐标 (u, v) 外参:每张图片都不同 描述相机与标定板的 相对位置和朝向 内参:标定一次长期使用 fx, fy, cx, cy + 畸变系数 k1, k2, p1, p2

4.6 标定到底在算什么?

把上面所有内容串起来,标定要算的就是这些东西:

参数类别 具体参数 数量 说明
内参 fx, fy, cx, cy 4 相机固有属性,不变
畸变系数 k1, k2, p1, p2(可选 k3) 4~5 镜头畸变修正参数
外参 每张图片的 R 和 t 6 × N N 为标定图片数量

举个例子,你用 20 张图片标定,总共要算的参数是:4(内参)+ 4(畸变)+ 6×20(外参)= 128 个参数。听起来很多,但 OpenCV 的标定算法用最小二乘法一次搞定。

我的建议:标定完成后,一定要看重投影误差。一般小于 0.5 像素就算不错,小于 0.3 像素就很好了。如果误差大于 1 像素,说明标定板检测有问题,或者图片质量不行,需要重新拍。

嗯,这一章的内容就到这儿。相机模型是标定的理论基础,后面讲具体操作时,你会反复用到这些概念。先把它们消化掉,后面的路就好走了。