4、相机模型与投影几何:针孔相机模型、畸变模型、双目视觉模型、单应矩阵与本质矩阵
各位做VIO的同行,咱们今天聊聊相机模型和投影几何。说实话,这部分内容看着像数学课本,但你要是搞不懂它,后面做标定、做初始化、做三角化,全都会踩坑。我当年刚入行时,就被畸变模型坑过一次——跑出来的轨迹像喝醉了酒,后来才发现是畸变参数给反了。
好,咱们一个一个来。
4.1 针孔相机模型:最朴素的成像原理
针孔相机模型,说白了就是小孔成像。你想想看,一个暗箱,前面戳个小孔,光线穿过小孔在后面的感光元件上成像。这就是最原始的相机模型。
数学上怎么描述?我们通常用四个坐标系:世界坐标系、相机坐标系、图像坐标系、像素坐标系。从3D世界点到2D像素点,经历三步变换:
- 世界坐标系 → 相机坐标系:刚体变换(旋转+平移)
- 相机坐标系 → 图像坐标系:透视投影(除以Z)
- 图像坐标系 → 像素坐标系:缩放+平移(内参)
写成矩阵形式就是:
s * [u, v, 1]^T = K * [R|t] * [X, Y, Z, 1]^T
其中K是内参矩阵:
K = [fx, 0, cx;
0, fy, cy;
0, 0, 1]
fx、fy是焦距(以像素为单位),cx、cy是主点坐标。嗯,这里要注意,fx和fy不一定相等,因为传感器像素可能不是正方形。
4.2 畸变模型:镜头不是完美的
现实中的镜头不是理想针孔。为了收集更多光线,镜头是凸透镜,这就带来了畸变。主要分两类:
- 径向畸变:光线在透镜边缘弯曲更厉害,产生「桶形」或「枕形」畸变
- 切向畸变:镜头和传感器不平行,产生「倾斜」效果
数学上,我们用多项式来建模:
x_distorted = x * (1 + k1*r^2 + k2*r^4 + k3*r^6) + 2*p1*x*y + p2*(r^2 + 2*x^2)
y_distorted = y * (1 + k1*r^2 + k2*r^4 + k3*r^6) + p1*(r^2 + 2*y^2) + 2*p2*x*y
其中r^2 = x^2 + y^2,k1、k2、k3是径向畸变系数,p1、p2是切向畸变系数。
实际工程中,我们通常用OpenCV的cv::fisheye或cv::calibrateCamera来做标定。标定板建议用棋盘格或AprilGrid,我个人更推荐AprilGrid——角点检测更鲁棒,尤其在有运动模糊的场景下。
4.3 双目视觉模型:用两个眼睛看世界
单目相机丢掉了深度信息。双目相机通过两个视角的视差,恢复出深度。说白了,就是模仿人的两只眼睛。
双目模型的核心是对极几何。左右两个相机观察同一个3D点,在左右图像上形成两个投影点。这两个点满足:
x2^T * F * x1 = 0
其中F是基础矩阵。如果两个相机已经标定好(内参已知),我们可以用本质矩阵E:
x2^T * E * x1 = 0
深度计算公式(理想平行双目):
Z = f * b / d
其中f是焦距,b是基线长度,d是视差(左右图像对应点的横坐标差)。
我在项目中遇到过一个问题:双目相机的基线太短(比如手机上的双目),导致远距离的深度估计噪声极大。后来我们换了个基线更长的相机模组,效果立竿见影。
4.4 单应矩阵与本质矩阵:两视图几何的核心
这两个矩阵是VIO初始化阶段的关键工具。它们描述了不同视角下同一场景的几何关系。
4.4.1 本质矩阵 E
本质矩阵描述了两个已标定相机之间的对极几何。它包含了旋转R和平移t的信息:
E = [t]× * R
其中[t]×是t的反对称矩阵。E有5个自由度(3个旋转 + 3个平移,但尺度不可知)。
求解E通常用五点法或八点法。我习惯用五点法,因为它对噪声更鲁棒,需要的匹配点更少。
从E中恢复R和t,需要对E做SVD分解:
E = U * Σ * V^T
R = U * R_z(±π/2) * V^T
t = U * (0, 0, 1)^T
这里有四种可能的解,只有一种能使得3D点在两个相机前方。嗯,这个「选对解」的步骤,我当年写代码时忘了做,结果初始化出来的位姿全是反的。
4.4.2 单应矩阵 H
单应矩阵描述了两个平面之间的投影变换。当场景近似在一个平面上时(比如地面、墙面),用单应矩阵更合适。
x2 = H * x1
H有8个自由度(尺度不可知)。求解H至少需要4对匹配点。
单应矩阵在VIO中有什么用?
- 纯旋转检测:如果相机只有旋转没有平移,本质矩阵退化,但单应矩阵仍然有效
- 平面场景初始化:比如无人机起飞时对着地面,用单应矩阵做初始化更稳定
- 视觉里程计中的运动估计:当特征点共面时,用H比用E更准
4.5 本章知识体系
下面这张图总结了相机模型与投影几何的核心逻辑:
4.6 工程实践中的注意事项
| 知识点 | 常见坑 | 我的建议 |
|---|---|---|
| 针孔模型 | 内参标定不准,尤其是主点偏移 | 用多张不同角度的标定图像,覆盖整个视场 |
| 畸变模型 | 广角镜头只用k1,k2不够 | 至少用k1,k2,k3,必要时用fisheye模型 |
| 双目模型 | 基线太短,深度噪声大 | 根据应用场景选择基线,室内10cm以上,室外20cm以上 |
| 本质矩阵 | 纯旋转时退化 | 检测视差是否足够,不够时用单应矩阵 |
| 单应矩阵 | 非平面场景下精度差 | 先做平面检测,再决定用E还是H |
好了,相机模型和投影几何就聊到这儿。这些内容看起来基础,但每一个细节都直接影响VIO系统的精度和稳定性。我建议你动手写代码实现一遍标定和去畸变,踩过坑才能真正理解。
公众号:蓝海资料掘金营,微信deep3321