3. 数学基础回顾(二):相机模型与投影几何

好,咱们接着聊。上一节我们把坐标系和刚体运动理清了,这节要解决一个核心问题:三维世界里的点,是怎么跑到二维图像上的?

说白了,这就是相机模型要干的事。你想想看,我们做VIO,天天跟图像打交道,如果连相机怎么成像的都不清楚,那后面的东西根本没法搞。我个人习惯,每次拿到一个新传感器,第一件事就是搞清楚它的投影模型和畸变参数,这能省掉后面一大堆调试的麻烦。

3.1 针孔相机模型

先讲最经典的针孔模型。虽然现在相机五花八门,但基本原理还是这个。

想象一个暗箱,前面戳个小孔,光线穿过小孔,在后面的感光平面上成一个倒像。这就是针孔相机。嗯,这里要注意,我们做算法时通常把成像平面翻到前面来,这样就不用处理倒立的问题了,数学上更直观。

核心公式:

假设空间点 P = [X, Y, Z]^T,投影到像素坐标 [u, v]^T:

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

其中 fx, fy 是焦距(单位是像素),cx, cy 是光心偏移。

我在项目中遇到过一个问题:有人把 fx 和 fy 设成一样的,结果标定出来的地图总是歪的。为什么?因为大多数相机的像素不是正方形,fx 和 fy 必须分开标定。

写成矩阵形式更简洁:

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

这个3x3矩阵,就是传说中的内参矩阵K。它只跟相机本身有关,跟外部场景无关。你换一个镜头,内参就得重新标。

3.2 畸变模型

现实中的镜头不是完美的针孔。为了收集更多光线,我们用了透镜,但透镜会引入畸变。最常见的两种:径向畸变切向畸变

3.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 是畸变参数。

我的经验:对于普通相机,只用 k1, k2 就够了。k3 通常用于鱼眼镜头。我曾经在一个项目中用了 k3 去标定普通镜头,结果过拟合了,去畸变后的图像反而更奇怪。

3.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 就是切向畸变参数。一般用两个就够了。

避坑指南:我曾经在标定一个工业相机时,发现去畸变后的图像边缘有奇怪的扭曲。查了半天,原来是标定板没放平,导致切向畸变参数被错误地估计了。记住:标定板一定要平整,最好贴在玻璃板上

3.3 双目视觉基础

单目相机有个致命问题:深度信息丢失了。你想想看,一个点在图像上的位置,既可以是近处的小物体,也可以是远处的大物体。单目没法区分。

双目视觉就是来解决这个问题的。用两个相机,像人的两只眼睛,通过视差来算深度。

3.3.1 视差与深度

假设左右相机水平放置,光心距离为 b(基线长度),焦距都是 f。空间点 P 在左图成像为 u_L,右图成像为 u_R。那么视差 d = u_L - u_R。

深度 Z 的计算公式:

Z = f * b / d

就这么简单。但实际用起来坑很多。

关键点:

  • 视差 d 越大,物体越近
  • 视差 d 越小,物体越远
  • 当 d = 0 时,物体在无穷远

3.3.2 极线约束

你可能会问:左右图像上那么多点,我怎么知道哪个点跟哪个点对应?

这就是极线约束发挥作用的地方。对于左图上的一个点,它在右图上的匹配点一定在一条直线上——这条线叫极线。

数学上,极线约束用基础矩阵 F 表示:

x_R^T * F * x_L = 0

其中 x_L 和 x_R 是左右图像上的归一化坐标。

有了极线约束,我们只需要在一维的极线上搜索匹配点,而不是在整个二维图像上搜索。这效率提升可不是一点半点。

我的建议:做双目匹配时,先做极线校正,把图像变成行对齐的。这样极线就变成了水平线,搜索起来特别方便。OpenCV 的 stereoRectify 函数就是干这个的。

3.4 本章知识体系

为了让你更直观地理解这些概念之间的关系,我画了张图:

相机模型与投影几何知识体系 相机模型 针孔相机模型 畸变模型 双目视觉基础 内参矩阵 K = [fx, fy, cx, cy] 投影方程:u = fx*X/Z + cx 径向畸变:k1, k2, k3 切向畸变:p1, p2 视差 d = u_L - u_R 深度 Z = f * b / d 极线约束:x_R^T * F * x_L = 0 核心目标:建立 3D 世界点 ↔ 2D 像素坐标的映射关系

3.5 小结

这一节我们聊了三个核心内容:

  • 针孔模型:用内参矩阵把3D点投影到2D图像上
  • 畸变模型:用多项式修正镜头带来的径向和切向畸变
  • 双目视觉:用视差算深度,用极线约束加速匹配

这些是VIO的数学地基。你想想看,如果没有这些模型,我们连图像上的点对应到空间哪个位置都不知道,后面的位姿估计、地图构建根本无从谈起。

嗯,我个人建议你找个相机,实际跑一遍标定流程。纸上得来终觉浅,亲手做一次,比看十遍公式都管用。


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