第4章:相机成像模型

相机是怎么把三维世界变成二维图像的?

这个问题,我刚入行时也琢磨了很久。后来做标定项目多了,才真正理解——相机成像模型就是连接三维点和二维像素的那座桥。今天咱们就把这座桥拆开,一块砖一块砖地看。

4.1 针孔相机模型

先说说最简单的模型——针孔相机模型。说白了,就是一个小孔成像。

想象一个密闭的盒子,前面戳个小孔,光线穿过小孔,在后面的感光面上成像。这就是最原始的相机。

数学上怎么描述?

核心公式:

X_cam = [X, Y, Z]^T   // 三维点在相机坐标系下的坐标
x = f * X / Z          // 归一化到成像平面
y = f * Y / Z

这里有个关键点:Z 不能为 0。你想想看,如果物体正好在相机光心位置,那成像就跑到无穷远去了。实际中当然不会发生,但数学上要留意。

我个人习惯把针孔模型拆成两步理解:

  1. 投影变换:把三维点映射到归一化平面(Z=1 的平面)
  2. 缩放平移:把归一化坐标映射到像素坐标

这样做的好处是——畸变校正、立体匹配这些操作,都在归一化平面上做,干净利落。

我的经验:做标定时,我习惯先把所有特征点反投影到归一化平面,再去做优化。这样内参和外参的耦合度最低,收敛也更快。

4.2 畸变模型

现实中的镜头不是完美的针孔。镜头有曲率,有装配误差,这就带来了畸变。

畸变主要分两类:径向畸变和切向畸变。我一个个说。

4.2.1 径向畸变

径向畸变,就是图像从中心向外,像素位置发生了偏移。说白了,直线变弯了。

有两种情况:

  • 桶形畸变:图像向外膨胀,像桶一样。常见于广角镜头。
  • 枕形畸变:图像向内收缩,像枕头一样。常见于长焦镜头。

数学上怎么建模?用泰勒展开:

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 是径向畸变系数。

注意:k3 一般只在鱼眼镜头或畸变特别大的镜头中使用。普通镜头用 k1、k2 就够了。我曾经在一个项目中盲目加了 k3,结果过拟合,标定结果反而更差。

4.2.2 切向畸变

切向畸变,是因为镜头和成像平面不平行造成的。说白了,就是装配时镜头歪了。

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 是切向畸变系数。这个模型是 Brown 在 1971 年提出的,到现在还在用。

我记得有一次做车载相机标定,发现图像边缘的直线总是弯的。一开始以为是径向畸变没校正好,调了半天 k1、k2 都没用。后来一查,原来是镜头装配时有个微小的倾斜。加上 p1、p2 后,问题立刻解决了。

避坑指南:我曾经在标定一个工业相机时,发现重投影误差总是降不下去。排查了很久,最后发现是畸变模型选错了——那个镜头是鱼眼镜头,用普通针孔模型加畸变根本不够。后来换成鱼眼模型,误差直接降了一个数量级。

4.3 内参矩阵

内参矩阵,就是把归一化坐标映射到像素坐标的那个矩阵。它长这样:

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

各参数含义:

  • fx, fy:焦距在 x、y 方向上的像素长度。单位是像素。
  • cx, cy:主点坐标,也就是光轴与成像平面的交点。单位是像素。

为什么 fx 和 fy 可能不一样?因为像素不一定是正方形的。有些相机的像素是矩形,所以 x 和 y 方向的焦距会不同。

完整的成像过程可以写成:

[u]   [fx,  0, cx]   [X/Z]
[v] = [ 0, fy, cy] * [Y/Z]
[1]   [ 0,  0,  1]   [ 1 ]

你想想看,这个矩阵其实做了两件事:

  1. 把归一化坐标 (X/Z, Y/Z) 缩放(乘以 fx、fy)
  2. 平移(加上 cx、cy)

说白了,就是把物理世界中的角度,映射到图像上的像素位置。

重要:内参矩阵是相机本身的属性,不随相机运动而改变。所以标定一次,只要焦距不变、镜头不换,就可以一直用。

4.4 完整成像流程

把上面所有内容串起来,一个三维点是怎么变成像素的?

  1. 世界坐标系 → 相机坐标系:通过外参(旋转 R、平移 t)
  2. 相机坐标系 → 归一化平面:除以 Z,得到 (x, y)
  3. 归一化坐标 → 畸变坐标:应用径向畸变和切向畸变
  4. 畸变坐标 → 像素坐标:通过内参矩阵 K

这个流程,我建议你背下来。做标定、做三维重建、做 SLAM,天天都要用。

我的习惯:写代码时,我会把畸变校正和内参映射分开写。这样调试时,可以单独看畸变校正的效果,也可以单独看内参映射的效果。耦合度低,排查问题快。

4.5 知识体系图

下面这张图,把本章的核心逻辑串起来了。建议你多看几遍,理解每个模块之间的关系。

相机成像模型知识体系 三维点 (X, Y, Z) 外参 (R, t) 世界→相机坐标系 归一化平面 (x = X/Z, y = Y/Z) 畸变模型 径向畸变: k1, k2, k3 切向畸变: p1, p2 内参矩阵 K fx, fy, cx, cy 归一化→像素坐标 像素坐标 (u, v) 关键点 • Z ≠ 0 • 畸变在归一化平面处理 • 内参是相机固有属性 • 外参会随运动变化 • 标定一次,长期使用 💡 我的建议 写代码时,畸变校正和内参映射 分开写,方便调试

4.6 小结

这一章我们聊了:

  • 针孔相机模型:三维点到归一化平面的投影
  • 畸变模型:径向畸变(k1, k2, k3)和切向畸变(p1, p2)
  • 内参矩阵:归一化坐标到像素坐标的映射

这些是相机标定的基础。你想想看,标定说白了就是求解这些参数——内参、畸变系数、外参。理解了成像模型,标定就成功了一半。

下一章,我们会把这些知识用到实际标定中。到时候,我会带你手写一个标定程序,从图像采集到参数求解,一步步走通。

可可精品资料库