2. 相机成像原理:小孔成像模型、透镜与畸变、相机内参矩阵、图像坐标系与像素坐标系

做SLAM这么多年,我经常被问到同一个问题:“相机到底是怎么把三维世界变成二维图像的?”

这个问题看似简单,但如果你不理解成像原理,后面做标定、做去畸变、做特征点匹配,都会踩坑。今天我就把这块掰开揉碎了讲清楚。

2.1 小孔成像模型:最朴素的相机

先别急着想复杂的镜头。最原始的相机,其实就是个带小孔的暗箱。

光线从物体上反射出来,穿过小孔,在后面的感光平面上形成一个倒立的像。这就是小孔成像模型。

核心公式:

假设物体高度为 H,距离小孔为 Z,像的高度为 h,小孔到成像平面的距离为 f(焦距),那么:

h / f = H / Z

说白了就是:物体离得越远,像越小;焦距越长,像越大。

我在项目中遇到过一个问题:有人用手机摄像头做SLAM,发现远处的地标点总是对不准。后来一查,是因为手机镜头焦距太短,远处物体的像只有几个像素,根本没法稳定跟踪。所以选相机时,焦距和视场角一定要匹配你的应用场景。

个人习惯:做室内SLAM,我一般选焦距 4-8mm 的镜头;做室外大场景,焦距 12mm 以上更靠谱。

2.2 透镜与畸变:现实总是不完美的

小孔成像虽然简单,但有个致命问题:小孔太小,进光量不够,图像太暗。所以真实相机都用透镜来聚光。

但透镜一加上去,问题就来了——畸变

你想想看,透镜的形状是弧面的,光线经过时会发生折射。边缘的光线折射角度和中心不一样,结果就是图像变形。

2.2.1 径向畸变

这是最常见的畸变。说白了就是直线变弯了。

  • 桶形畸变:图像边缘向外凸,像桶一样。广角镜头常见。
  • 枕形畸变:图像边缘向内凹,像枕头。长焦镜头常见。

我记得有一次做双目视觉,左右相机拍出来的图像对不上,怎么调基线都没用。后来发现是其中一个镜头的径向畸变特别大,标定后一校正,问题就解决了。嗯,这里要注意:畸变校正不是可选项,是必选项。

2.2.2 切向畸变

这个更隐蔽。它是因为透镜和成像平面不平行造成的。说白了就是镜头装歪了。

切向畸变会让图像看起来像被“拧”了一下。虽然量不大,但在高精度SLAM里,这点误差足以让位姿估计跑偏。

我曾经踩过的坑:有一次用鱼眼镜头做SLAM,觉得畸变校正参数用默认值就行。结果跑出来的轨迹全是弯的。后来老老实实做了棋盘格标定,才发现切向畸变系数比想象中大得多。所以,每换一次镜头,必须重新标定。

2.3 相机内参矩阵:从三维到二维的“翻译官”

好了,现在我们知道相机是怎么成像的了。但计算机要处理的是像素,不是物理坐标。所以需要一个东西把三维空间点映射到像素坐标——这就是相机内参矩阵 K

内参矩阵长这样:

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

其中:

  • fx, fy:分别是 x 和 y 方向的焦距(单位是像素)。注意,这里不是物理焦距,而是物理焦距 × 像素密度
  • cx, cy:主点坐标,也就是光轴与成像平面的交点。理想情况下在图像中心,但实际会有偏移。

为什么会这样?因为相机传感器上的像素不是完美的正方形,而且安装时也有偏差。所以 fx 和 fy 往往不相等。

一个重要的公式:

三维点 P = (X, Y, Z) 投影到像素坐标 (u, v) 的过程:

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

你看,这里有个 Z 在分母上。这就是为什么深度信息在单目相机里是丢失的——你只知道方向,不知道距离。

我个人习惯在代码里把内参矩阵写成 3×3 的浮点数组,方便做矩阵运算。比如在 OpenCV 里:

cv::Mat K = (cv::Mat_<double>(3,3) <<
     fx, 0, cx,
     0, fy, cy,
     0, 0, 1);

2.4 图像坐标系与像素坐标系:别搞混了

这两个概念经常被混淆,我刚开始做SLAM时也犯过这个错。

  • 图像坐标系:以图像中心为原点,单位是毫米或米。x 轴向右,y 轴向上。
  • 像素坐标系:以图像左上角为原点,单位是像素。u 轴向右,v 轴向下。

它们之间的转换关系很简单:

u = x / dx + u0
v = y / dy + v0

其中 dx, dy 是每个像素的物理尺寸,u0, v0 是主点的像素坐标。

避坑指南:在写代码时,一定要搞清楚你用的是哪个坐标系。比如 OpenCV 的 cv::Point2f 默认是像素坐标,而 Eigen 的 Vector3d 往往是归一化图像坐标。混用的话,结果会完全不对。我曾经调试一个特征点匹配的问题,花了整整两天,最后发现是坐标系搞反了。

2.5 知识体系总览

下面这张图把本章的核心逻辑串起来了。你可以看到,从三维世界到像素坐标,每一步都有对应的数学模型和参数。

相机成像原理知识体系 三维世界点 (X, Y, Z) 小孔成像 小孔成像模型 h/f = H/Z 透镜畸变 透镜与畸变 径向 + 切向 相机内参矩阵 K fx, fy, cx, cy 三维 → 归一化图像坐标 图像坐标系 中心原点,单位:mm 像素坐标系 左上角原点,单位:pixel u = x/dx + u0 最终像素坐标 (u, v)

从这张图可以看得很清楚:三维世界点经过小孔成像、透镜畸变、内参矩阵变换,最后落到像素坐标系上。每一步都有对应的数学模型和参数。做SLAM时,这些参数一个都不能错。

总结一下本章的核心要点:

  • 小孔成像模型是基础,但实际相机用透镜,所以有畸变
  • 畸变分径向和切向,必须标定校正
  • 内参矩阵 K 是三维到二维的桥梁,fx, fy, cx, cy 是关键参数
  • 图像坐标系和像素坐标系要分清,写代码时尤其注意

好了,这一章就到这里。记住一句话:理解成像原理,是做好SLAM的第一步。后面讲特征点提取和匹配时,你会发现这些知识全都能用上。


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