第二章:相机内参标定原理

相机内参标定,说白了就是搞清楚相机到底是怎么「看」世界的。我刚开始做标定时,总觉得这事挺玄乎——一个镜头后面藏着那么多参数,怎么算得清楚?后来踩过几次坑才明白,其实核心就四个东西:针孔模型、畸变模型、张正友标定法,还有最后算出来的内参矩阵和畸变系数。咱们一个一个来聊。

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 张正友标定法原理

张正友标定法,可以说是相机标定领域的「标准答案」了。为什么这么说?因为它解决了两个核心问题:

  1. 怎么从多张棋盘格照片里提取角点
  2. 怎么用这些角点算出内参和畸变系数

具体流程是这样的:

  • 拍 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 算反了。所以标定完一定要验证——拍一张棋盘格,去畸变后看看格子是不是直的。

好了,这一章的内容就这些。下一章咱们聊聊多相机标定,也就是怎么把多个相机的坐标系统一起来。那个更有意思,也更容易踩坑。