第二章:相机内参标定原理
相机内参标定,说白了就是搞清楚相机到底是怎么「看」世界的。我刚开始做标定时,总觉得这事挺玄乎——一个镜头后面藏着那么多参数,怎么算得清楚?后来踩过几次坑才明白,其实核心就四个东西:针孔模型、畸变模型、张正友标定法,还有最后算出来的内参矩阵和畸变系数。咱们一个一个来聊。
2.1 针孔相机模型
先说说最基础的针孔模型。你想想看,一个相机拍照,本质上就是三维世界的光线穿过镜头,投射到成像平面上。针孔模型把这个过程简化了——假设光线是直线传播的,穿过一个小孔,在后面的平面上成像。
数学上怎么描述?很简单,一个三维点 P(X, Y, Z) 映射到图像上的点 p(u, v):
u = f * X / Z + cx
v = f * Y / Z + cy
这里 f 是焦距,cx、cy 是光心在图像上的位置。嗯,这里要注意,这个模型是理想化的。我在项目中遇到过,实际相机根本做不到这么完美——镜头有厚度、有曲率,光线不可能完全直线传播。所以就有了畸变模型。
2.2 畸变模型
畸变分两种:径向畸变和切向畸变。我习惯把它们叫做「镜头本身的毛病」和「装配时的毛病」。
2.2.1 径向畸变
径向畸变就是光线经过镜头时,边缘部分被弯曲了。说白了,越靠近图像边缘,变形越明显。你拍一张棋盘格,边缘的格子看起来是弯的,这就是径向畸变。
数学上,我们用三个参数 k1、k2、k3 来描述:
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 是像素点到光心的距离。k1 管的是主要畸变,k2 管的是边缘更精细的畸变,k3 一般用在鱼眼镜头那种大畸变场景。我记得有一次标定一个广角相机,k3 不加上去,边缘的误差怎么都降不下来。
2.2.2 切向畸变
切向畸变,说白了就是镜头和成像平面没装平行。你想想看,镜头稍微歪了一点,拍出来的图像就会一边大一边小。这个用两个参数 p1、p2 来描述:
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)
避坑指南: 我曾经在标定一个工业相机时,发现畸变系数特别大,怎么调都调不好。后来拆开相机一看,镜头根本没拧紧。所以标定前,先检查机械结构是否牢固,别上来就调参数。
2.3 张正友标定法原理
张正友标定法,可以说是相机标定领域的「标准答案」了。为什么这么说?因为它解决了两个核心问题:
- 怎么从多张棋盘格照片里提取角点
- 怎么用这些角点算出内参和畸变系数
具体流程是这样的:
- 拍 10-20 张不同角度的棋盘格照片
- 每张照片提取角点坐标
- 用这些角点建立方程,先算出一个初始解
- 再用非线性优化把畸变系数也加进去,一起优化
我个人习惯,拍棋盘格时注意三点:
- 棋盘格要占满画面,别只拍中间
- 角度变化要大,俯仰、偏航、旋转都要有
- 光照均匀,别让棋盘格上有反光
小技巧: 我建议每张照片的棋盘格角度至少相差 15 度以上。如果角度变化太小,算出来的参数会不稳定。你想想看,如果所有照片都是正对着拍的,那怎么算得出畸变?
2.4 内参矩阵与畸变系数
标定完,我们得到两个东西:内参矩阵和畸变系数。
内参矩阵 长这样:
K = [fx, 0, cx]
[ 0, fy, cy]
[ 0, 0, 1]
fx、fy 是焦距在 x 和 y 方向上的像素长度。cx、cy 是光心坐标。这个矩阵说白了就是告诉你:一个三维点,经过相机投影后,落在图像上的哪个像素位置。
畸变系数 是一个向量:
D = [k1, k2, p1, p2, k3]
一般标定完,我会先看看 k1 和 k2 的值。如果 k1 的绝对值大于 0.1,说明镜头畸变比较明显。如果 k3 不为零,说明镜头边缘畸变很严重。
重要提醒: 内参矩阵和畸变系数是成对使用的。你单独看内参矩阵,或者单独看畸变系数,都没意义。只有把它们放在一起,才能完整描述一个相机的成像特性。
我记得有一次,一个同事标定完相机,发现去畸变后的图像边缘还是有变形。查了半天,原来是内参矩阵里的 fx 和 fy 算反了。所以标定完一定要验证——拍一张棋盘格,去畸变后看看格子是不是直的。
好了,这一章的内容就这些。下一章咱们聊聊多相机标定,也就是怎么把多个相机的坐标系统一起来。那个更有意思,也更容易踩坑。