第二章:相机模型与投影几何
大家好,欢迎来到第二章。这一章我们聊聊相机是怎么「看」世界的。说白了,就是研究三维空间里的点,怎么映射到二维图像上。嗯,这是整个视觉SLAM的基石,绕不开的。
2.1 针孔相机模型
先说说最简单的针孔相机模型。你想想看,一个小孔,光线穿过它,在后面的平面上成像。这就是最原始的相机原理。
数学上怎么描述?我们设世界坐标系中有一个点 P = [X, Y, Z]ᵀ,它通过小孔投影到成像平面上的点 p = [x, y]ᵀ。根据相似三角形,有:
x = f * X / Z
y = f * Y / Z
这里的 f 是焦距。但实际相机里,像素坐标和物理坐标还有个偏移。所以完整的针孔模型是:
u = fx * X / Z + cx
v = fy * Y / Z + cy
其中 fx, fy 是焦距在像素坐标系下的表示,cx, cy 是光心偏移。这五个参数(fx, fy, cx, cy, 以及畸变参数)就是相机的内参。
核心要点:内参矩阵 K 把相机坐标系下的3D点映射到像素平面。K = [[fx, 0, cx], [0, fy, cy], [0, 0, 1]]。这个矩阵一旦标定好,基本就不变了。
我个人习惯把内参矩阵想象成「翻译官」——它把物理世界的坐标翻译成像素坐标。没有它,你看到的图像就是一堆没有意义的数字。
2.2 畸变模型
实际相机不是完美的针孔。镜头有曲率,装配有误差,所以图像会变形。这就是畸变。
畸变主要分两种:径向畸变和切向畸变。
2.2.1 径向畸变
径向畸变是光线通过透镜时,边缘弯曲造成的。你拍一张棋盘格,如果边缘的直线变弯了,那就是径向畸变在作怪。
数学上,我们用多项式来修正:
x_corrected = x * (1 + k1 * r² + k2 * r⁴ + k3 * r⁶)
y_corrected = y * (1 + k1 * r² + k2 * r⁴ + k3 * r⁶)
其中 r² = x² + y²,k1, k2, k3 是径向畸变参数。一般用 k1, k2 就够了,鱼眼镜头才需要 k3。
避坑指南:我曾经在一个项目中,用了一个廉价摄像头,畸变特别大。当时只标定了 k1, k2,结果边缘还是歪的。后来加上 k3 才搞定。所以,如果镜头质量一般,建议把 k3 也标上。
2.2.2 切向畸变
切向畸变是镜头和成像平面不平行造成的。说白了,就是镜头装歪了。
修正公式:
x_corrected = x + [2 * p1 * x * y + p2 * (r² + 2 * x²)]
y_corrected = y + [p1 * (r² + 2 * y²) + 2 * p2 * x * y]
p1, p2 是切向畸变参数。嗯,这里要注意,切向畸变一般比较小,但也不能忽略。
2.3 相机标定原理
标定就是求内参和畸变参数的过程。怎么求?用已知的3D点和对应的2D像素点来解方程。
最经典的方法是张正友标定法。你打印一张棋盘格,拍几张不同角度的照片,然后算法自动提取角点,解算出内参和畸变。
流程大致如下:
- 拍摄10-20张棋盘格照片(不同角度、不同距离)
- 提取棋盘格角点坐标
- 用闭式解求初始内参
- 用非线性优化(比如LM算法)求精
注意事项:标定照片一定要覆盖整个视野。我见过有人只拍中心区域,结果边缘畸变完全没标出来。还有,棋盘格要平整,不要用手捏着,最好贴在硬板上。
标定完成后,你会得到这样的结果:
| 参数 | 含义 | 典型值(640x480相机) |
|---|---|---|
| fx | x方向焦距 | ~500 |
| fy | y方向焦距 | ~500 |
| cx | 光心x坐标 | ~320 |
| cy | 光心y坐标 | ~240 |
| k1, k2 | 径向畸变 | ~0.1, ~-0.2 |
| p1, p2 | 切向畸变 | ~0.001 |
2.4 对极几何与基础矩阵
好,现在我们有了一台标定好的相机。接下来要解决一个问题:两帧图像之间,特征点怎么匹配?它们之间有什么几何约束?
这就是对极几何要回答的。
2.4.1 对极约束
假设你在第一帧看到点 p1,在第二帧看到点 p2。如果这两个点是同一个3D点的投影,那么它们满足:
p2ᵀ * F * p1 = 0
这里的 F 就是基础矩阵(Fundamental Matrix)。它编码了两个相机之间的相对位姿和内参信息。
为什么会这样?你想想看,p1 对应的3D点一定在一条射线上,这条射线在第二帧的投影是一条直线(极线)。p2 必须落在这条极线上。基础矩阵就是描述这个约束的。
2.4.2 基础矩阵与本质矩阵
基础矩阵 F 和本质矩阵 E 的关系很简单:
F = K⁻ᵀ * E * K⁻¹
其中 K 是内参矩阵。E 只包含旋转和平移信息,不包含内参。所以,如果你知道内参,可以用 E 来恢复相机运动。
实际应用中,我们通常:
- 用特征匹配(比如ORB特征)找到对应点对
- 用八点法求解基础矩阵 F
- 分解 F 得到旋转 R 和平移 t
个人经验:八点法对噪声很敏感。我建议用RANSAC来剔除误匹配。有一次我在室外场景做VIO,特征匹配里混了30%的误匹配,直接用八点法算出来的位姿完全不对。加上RANSAC后,瞬间稳定了。
2.4.3 单应矩阵
还有一种特殊情况:如果场景是平面,或者相机纯旋转,那么对极几何退化为单应变换。单应矩阵 H 满足:
p2 = H * p1
单应矩阵只需要4对点就能求解,比基础矩阵更稳定。我在做AR应用时,经常用单应矩阵来做平面跟踪,效果很好。
小技巧:判断用基础矩阵还是单应矩阵?看特征点的分布。如果点都在一个平面上(比如墙面),用单应矩阵。如果点分布很广(比如室外建筑),用基础矩阵。当然,也可以两个都算,选重投影误差小的那个。
2.5 本章小结
这一章我们聊了:
- 针孔相机模型:3D到2D的映射
- 畸变模型:径向和切向畸变的修正
- 相机标定:用棋盘格求内参和畸变参数
- 对极几何:基础矩阵、本质矩阵、单应矩阵
嗯,内容不少。但这些都是SLAM的「基本功」。下一章我们会把这些知识用到实际的视觉里程计中。到时候你会发现,今天学的每一个公式,都会在代码里出现。
记住一句话:相机模型是SLAM的「眼睛」,对极几何是SLAM的「骨架」。把这两样搞明白,后面的路就好走了。
好,今天就到这里。有问题欢迎在评论区交流。