第2章:相机模型与投影几何
相机模型,说白了就是回答一个问题:三维世界里的一个点,到底是怎么跑到二维图像上的? 这个问题看似简单,但里面藏着不少门道。我做了这么多年SLAM,发现很多新手栽跟头,就是栽在对这个基础模型的理解不够深。
2.1 针孔模型:最朴素的相机
先聊聊最经典的针孔模型。你想想看,最早的相机其实就是个暗箱,前面戳个小孔,光线透过小孔在后面的感光板上成像。这就是针孔模型的物理原型。
数学上怎么描述?很简单,四个坐标系之间的变换:
- 世界坐标系:我们生活的三维空间,单位是米
- 相机坐标系:以相机光心为原点,Z轴朝前
- 图像坐标系:在成像平面上,单位还是米
- 像素坐标系:最终你看到的图像,单位是像素
从世界点到像素点,经历了三步:
- 世界坐标 → 相机坐标(外参干的活)
- 相机坐标 → 图像坐标(投影)
- 图像坐标 → 像素坐标(内参干的活)
核心公式:
s * p = K * [R|t] * P
其中 p 是像素坐标,P 是世界坐标,K 是内参矩阵,[R|t] 是外参矩阵,s 是尺度因子。
嗯,这里要注意:那个 s 尺度因子,很多人会忽略它。为什么会有 s?因为从3D到2D,深度信息丢失了,我们只知道方向,不知道距离。这就是单目SLAM的尺度不确定性根源。
2.2 内参矩阵:相机的"身份证"
内参矩阵 K,我习惯把它看作相机的"身份证"。每个相机都有自己的内参,出厂就定了,但会随着温度、震动等因素轻微变化。
K 长这样:
K = [fx, 0, cx;
0, fy, cy;
0, 0, 1]
这里:
- fx, fy:焦距的像素表示。说白了就是焦距(毫米)除以像素大小(毫米/像素)
- cx, cy:主点偏移。理论上应该在图像正中心,但实际总有偏差
我的经验: 我在项目中遇到过一台相机,标定出来的 cx 偏离中心整整20个像素。一开始以为是标定出错了,反复标了三次,结果都一样。后来查资料才知道,这是镜头组装时的公差导致的。所以别迷信"主点应该在中心"这个说法。
2.3 畸变模型:镜头不是完美的
针孔模型是理想情况。现实中的镜头,尤其是广角镜头,会引入畸变。最常见的两种:
- 径向畸变:光线经过透镜时,边缘弯曲比中心厉害。表现为"桶形"或"枕形"
- 切向畸变:镜头和成像平面不平行。表现为图像倾斜
数学上怎么矫正?用多项式近似:
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
其中 k1, k2, k3 是径向畸变参数,p1, p2 是切向畸变参数。r 是点到主点的距离。
避坑指南: 我曾经在标定一个鱼眼镜头时,只用了 k1, k2 两个参数,结果矫正后的图像边缘还是弯的。后来加了 k3 和 k4,效果才好了。记住:视场角越大,需要的畸变参数越多。普通镜头用3个径向参数就够了,鱼眼镜头可能需要5个甚至更多。
2.4 外参矩阵:相机在哪儿?朝哪儿看?
外参矩阵 [R|t] 描述的是相机在世界坐标系中的位置和朝向。R 是旋转矩阵,t 是平移向量。
我见过很多同学搞混一件事:外参到底是从世界到相机,还是从相机到世界?
答案是:从世界到相机。也就是说,一个世界坐标系下的点 P_w,乘以 [R|t] 后,就变成了相机坐标系下的点 P_c。
P_c = R * P_w + t
R 有3个自由度,t 有3个自由度,所以外参一共6个自由度。这也是为什么我们常说"6自由度位姿"。
一个容易混淆的点: 外参矩阵的逆 [R^T | -R^T * t] 才是从相机到世界的变换。如果你想把相机位姿可视化出来,记得用逆矩阵。
2.5 投影几何:从3D到2D的完整流程
把上面所有东西串起来,完整的投影流程是这样的:
- 世界点 P_w = [X, Y, Z, 1]^T
- 乘以外参:P_c = [R|t] * P_w
- 归一化:x = X_c / Z_c, y = Y_c / Z_c
- 加畸变:x', y' = distort(x, y)
- 乘以内参:u = fx * x' + cx, v = fy * y' + cy
你看,每一步都有明确的物理意义。我在调试SLAM系统时,经常把中间结果打印出来检查,看看是哪一步出了问题。
调试技巧: 如果你发现重投影误差很大,别急着调算法。先检查一下:
- 内参标定文件是不是加载对了?
- 畸变矫正有没有做?
- 外参的旋转顺序是不是你期望的?
我曾经花了一整天找bug,最后发现是标定文件里 fx 和 fy 写反了。这种低级错误,排查起来最费时间。
2.6 知识体系总览
下面这张图,是我自己总结的相机模型知识体系。每次带新人,我都会先让他们看这张图,把整体脉络理清楚。
这张图把整个流程串起来了。你从世界坐标出发,经过外参变换到相机坐标,然后归一化到归一化平面,再经过畸变矫正,最后通过内参映射到像素坐标。每一步都有对应的数学模型和参数。
嗯,说到这儿,我想起一个事。有一次我在做VIO初始化,发现视觉和IMU的对不齐。查了半天,原来是外参的旋转顺序搞错了。视觉用的是ZYX欧拉角,IMU用的是四元数,两者没对齐。从那以后,我每次做标定都会先确认一下旋转的表示方式。
总结一下本章核心:
- 针孔模型是基础,但现实需要加畸变矫正
- 内参矩阵K是相机固有属性,需要标定得到
- 外参矩阵[R|t]描述相机位姿,是SLAM要估计的核心量
- 投影过程:世界→相机→归一化→畸变→像素
这些概念,是后面所有SLAM算法的基础。你如果能把它们吃透,后面学特征匹配、三角化、PnP、BA都会轻松很多。