2、相机畸变:径向畸变(桶形/枕形)、切向畸变、畸变数学模型
聊完针孔模型,咱们得面对一个现实——真实镜头不是完美的针孔。
你想想看,镜头是玻璃磨出来的,有曲率、有装配误差。光线穿过它,不可能老老实实按直线走。这就引出了畸变。
我刚开始做标定时,总觉得畸变是小事。后来在一个高精度测量项目里,图像边缘的像素偏差直接导致重建误差超了 3 个像素。嗯,从那以后我再也不敢小看畸变了。
2.1 径向畸变:桶形与枕形
径向畸变,说白了就是光线在镜头边缘弯得比中心厉害。它沿着镜头半径方向发生,离中心越远,变形越明显。
我习惯把它分成两类:
- 桶形畸变:图像边缘向外鼓,像木桶。常见于广角镜头、鱼眼镜头。我在做车载环视系统时,四个鱼眼镜头拍出来的地面标线全是弯的,这就是典型的桶形畸变。
- 枕形畸变:图像边缘向内缩,像枕头。常见于长焦镜头、变焦镜头长焦端。做工业检测时,用长焦拍小零件,边缘的直线会变成向内弯的弧线。
为什么会这样?
因为镜头边缘的放大率跟中心不一样。桶形畸变是边缘放大率小于中心,枕形畸变则相反。你可以用一张棋盘格拍张照,看看边缘的格子是不是比中间的小或大,一眼就能判断。
2.2 切向畸变:镜头装配的“锅”
切向畸变,很多人容易忽略。它不是因为镜头曲率,而是因为镜头和成像平面不平行。
你想想看,镜头是手工或机器装上去的,难免有倾斜。光线穿过倾斜的透镜组,就会在切线方向产生偏移。这种畸变在图像上表现为:原本垂直的线变成斜线,或者图像一边被拉伸、另一边被压缩。
我遇到过最夸张的一次,是某款工业相机出厂时镜头装歪了,图像左上角明显比右下角模糊。标定后一看,切向畸变系数 p1、p2 比正常值大了两个数量级。后来返厂重装才解决。
2.3 畸变数学模型
好了,理论说完了,咱们上公式。别怕,我会拆开讲。
畸变模型通常用多项式来描述。假设归一化平面上的理想坐标为 (x, y),畸变后的坐标为 (xd, yd)。
径向畸变模型
径向畸变只跟距离 r 有关,r = √(x² + y²)。
x_distorted = x * (1 + k1*r² + k2*r⁴ + k3*r⁶)
y_distorted = y * (1 + k1*r² + k2*r⁴ + k3*r⁶)
这里 k1、k2、k3 是径向畸变系数。k1 主导畸变方向:
- k1 > 0 → 枕形畸变
- k1 < 0 → 桶形畸变
k2、k3 用来修正边缘更复杂的变形。普通镜头标定 k1、k2 就够了,鱼眼镜头才需要 k3。
切向畸变模型
切向畸变用 p1、p2 两个参数描述:
x_distorted = x + [2*p1*x*y + p2*(r² + 2*x²)]
y_distorted = y + [p1*(r² + 2*y²) + 2*p2*x*y]
这个公式看着复杂,其实就两个作用:
- p1 控制图像在水平方向的倾斜
- p2 控制图像在垂直方向的倾斜
我一般把 p1、p2 的值超过 0.1 就视为镜头装配有问题,需要检查硬件。
完整畸变模型
把径向和切向合起来,就是 OpenCV 里用的标准模型:
x_d = x * (1 + k1*r² + k2*r⁴ + k3*r⁶) + [2*p1*x*y + p2*(r² + 2*x²)]
y_d = y * (1 + k1*r² + k2*r⁴ + k3*r⁶) + [p1*(r² + 2*y²) + 2*p2*x*y]
这个公式就是标定算法要解的“畸变方程”。我们拍棋盘格、提取角点,最终就是为了算出 k1、k2、k3、p1、p2 这五个畸变系数。
2.4 畸变参数速查表
为了方便你对照,我整理了一个表格:
| 参数 | 类型 | 典型范围 | 物理含义 |
|---|---|---|---|
| k1 | 径向 | -0.5 ~ 0.5 | 主导畸变方向与强度 |
| k2 | 径向 | -0.3 ~ 0.3 | 边缘畸变修正 |
| k3 | 径向 | -0.1 ~ 0.1 | 鱼眼/大畸变镜头修正 |
| p1 | 切向 | -0.05 ~ 0.05 | 水平方向倾斜 |
| p2 | 切向 | -0.05 ~ 0.05 | 垂直方向倾斜 |
2.5 畸变知识结构图
下面这张图帮你理清本章的知识脉络:
2.6 小结
这一章咱们把畸变讲透了:
- 径向畸变是镜头曲率导致的,分桶形和枕形,用 k1、k2、k3 描述。
- 切向畸变是装配误差导致的,用 p1、p2 描述。
- 完整模型就是五个参数的多项式,OpenCV 的标定算法就是解这个方程。
记住一句话:畸变参数不是标定完就完事了。我每次标定完都会做一件事——把矫正后的图像和原图叠在一起看边缘直线。如果直线还是弯的,说明标定有问题,得重来。