第二章:相机模型与投影几何

大家好,欢迎来到第二章。这一章我们聊聊相机是怎么「看」世界的。说白了,就是研究三维空间里的点,怎么映射到二维图像上。嗯,这是整个视觉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像素点来解方程。

最经典的方法是张正友标定法。你打印一张棋盘格,拍几张不同角度的照片,然后算法自动提取角点,解算出内参和畸变。

流程大致如下:

  1. 拍摄10-20张棋盘格照片(不同角度、不同距离)
  2. 提取棋盘格角点坐标
  3. 用闭式解求初始内参
  4. 用非线性优化(比如LM算法)求精

注意事项:标定照片一定要覆盖整个视野。我见过有人只拍中心区域,结果边缘畸变完全没标出来。还有,棋盘格要平整,不要用手捏着,最好贴在硬板上。

标定完成后,你会得到这样的结果:

参数含义典型值(640x480相机)
fxx方向焦距~500
fyy方向焦距~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 来恢复相机运动。

实际应用中,我们通常:

  1. 用特征匹配(比如ORB特征)找到对应点对
  2. 用八点法求解基础矩阵 F
  3. 分解 F 得到旋转 R 和平移 t

个人经验:八点法对噪声很敏感。我建议用RANSAC来剔除误匹配。有一次我在室外场景做VIO,特征匹配里混了30%的误匹配,直接用八点法算出来的位姿完全不对。加上RANSAC后,瞬间稳定了。

2.4.3 单应矩阵

还有一种特殊情况:如果场景是平面,或者相机纯旋转,那么对极几何退化为单应变换。单应矩阵 H 满足:

p2 = H * p1

单应矩阵只需要4对点就能求解,比基础矩阵更稳定。我在做AR应用时,经常用单应矩阵来做平面跟踪,效果很好。

小技巧:判断用基础矩阵还是单应矩阵?看特征点的分布。如果点都在一个平面上(比如墙面),用单应矩阵。如果点分布很广(比如室外建筑),用基础矩阵。当然,也可以两个都算,选重投影误差小的那个。

2.5 本章小结

这一章我们聊了:

  • 针孔相机模型:3D到2D的映射
  • 畸变模型:径向和切向畸变的修正
  • 相机标定:用棋盘格求内参和畸变参数
  • 对极几何:基础矩阵、本质矩阵、单应矩阵

嗯,内容不少。但这些都是SLAM的「基本功」。下一章我们会把这些知识用到实际的视觉里程计中。到时候你会发现,今天学的每一个公式,都会在代码里出现。

记住一句话:相机模型是SLAM的「眼睛」,对极几何是SLAM的「骨架」。把这两样搞明白,后面的路就好走了。

好,今天就到这里。有问题欢迎在评论区交流。