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 知识体系总览
下面这张图把本章的核心逻辑串起来了。你可以看到,从三维世界到像素坐标,每一步都有对应的数学模型和参数。
从这张图可以看得很清楚:三维世界点经过小孔成像、透镜畸变、内参矩阵变换,最后落到像素坐标系上。每一步都有对应的数学模型和参数。做SLAM时,这些参数一个都不能错。
总结一下本章的核心要点:
- 小孔成像模型是基础,但实际相机用透镜,所以有畸变
- 畸变分径向和切向,必须标定校正
- 内参矩阵 K 是三维到二维的桥梁,fx, fy, cx, cy 是关键参数
- 图像坐标系和像素坐标系要分清,写代码时尤其注意
好了,这一章就到这里。记住一句话:理解成像原理,是做好SLAM的第一步。后面讲特征点提取和匹配时,你会发现这些知识全都能用上。
公众号:蓝海资料掘金营,微信deep3321