3. 畸变数学模型:径向畸变、切向畸变与标定方法概述
聊鱼眼校正,绕不开一个核心问题——畸变到底长什么样?怎么用数学描述它?
说白了,鱼眼镜头为了把超大视野塞进小小的传感器,必须牺牲“直线性”。光线经过镜头时,离中心越远,弯曲得越厉害。这种弯曲不是随机的,它有规律可循。我们这一节就把这些规律拆开来看。
核心观点:畸变模型是校正算法的“坐标系”。模型选对了,校正就成功了一半。我见过不少项目,算法调了半天没效果,最后发现是模型本身就不匹配镜头特性。
3.1 径向畸变模型
径向畸变是最主要的畸变类型。它沿着镜头半径方向发生,说白了就是“越靠边,变形越严重”。
我习惯把径向畸变分成两类:
- 桶形畸变(Barrel Distortion):图像边缘向外膨胀,像木桶的弧度。鱼眼镜头几乎全是这种。
- 枕形畸变(Pincushion Distortion):图像边缘向内收缩,像枕头。长焦镜头常见,鱼眼很少见。
为什么会这样?因为鱼眼镜头的设计刻意让光线在边缘“压缩”,才能拍到更宽的视野。你想想看,一个180°的视场角,如果按小孔成像去算,传感器根本装不下。
3.1.1 Brown模型
Brown模型是工业界最常用的径向畸变模型之一。它由Duane C. Brown在1960年代提出,至今仍是相机标定的主流选择。
它的数学形式很简单:
// 归一化坐标下的径向畸变
x_distorted = x * (1 + k1 * r² + k2 * r⁴ + k3 * r⁶)
y_distorted = y * (1 + k1 * r² + k2 * r⁴ + k3 * r⁶)
// 其中 r² = x² + y²
// k1, k2, k3 是径向畸变系数
这里有个细节:r 是归一化坐标下的半径,不是像素坐标。我刚开始做标定时,直接拿像素坐标去算,结果畸变参数怎么都收敛不了。后来才发现,必须先把像素坐标转换到归一化平面。
我的经验:对于普通广角镜头,用 k1、k2 两个参数就够了。但鱼眼镜头强烈建议用 k3,甚至有些极端镜头需要 k4、k5。我曾经处理过一个185°的鱼眼镜头,只用 k1、k2 校正后边缘还是有明显弯曲,加上 k3 才搞定。
3.1.2 多项式模型
多项式模型是Brown模型的“亲戚”,但更灵活。它用更高阶的多项式来拟合畸变曲线。
通用形式:
// 多项式径向畸变
r_distorted = r * (1 + k1 * r² + k2 * r⁴ + k3 * r⁶ + ... + kn * r^(2n))
// 或者直接用角度表示(鱼眼专用)
θ_distorted = θ * (1 + k1 * θ² + k2 * θ⁴ + k3 * θ⁶ + ...)
两种形式有什么区别?
| 模型 | 适用场景 | 参数数量 | 特点 |
|---|---|---|---|
| Brown模型 | 普通广角、中焦镜头 | 3个(k1,k2,k3) | 稳定、收敛快 |
| 多项式模型(高阶) | 超广角、鱼眼镜头 | 4~8个 | 拟合能力强,但容易过拟合 |
| 多项式模型(角度域) | 等距投影鱼眼 | 3~5个 | 物理意义更清晰 |
注意:多项式阶数不是越高越好。我曾经试过用8阶多项式去拟合一个普通镜头,结果在校正图像边缘出现了波浪状的伪影。这就是过拟合——模型记住了噪声,而不是真实的畸变规律。一般建议从3阶开始,逐步增加,直到校正效果不再明显改善为止。
3.2 切向畸变模型
切向畸变,也叫离心畸变。它不是因为镜头的光学设计,而是因为镜头和传感器不平行造成的。
你想想看,如果镜头的光轴和传感器平面不是严格垂直,图像就会产生“倾斜”或“拉伸”的效果。这种畸变沿着切线方向发生,所以叫切向畸变。
数学模型:
// 切向畸变
x_distorted = x + [2 * p1 * x * y + p2 * (r² + 2 * x²)]
y_distorted = y + [p1 * (r² + 2 * y²) + 2 * p2 * x * y]
// 其中 p1, p2 是切向畸变系数
这个公式看起来有点复杂,但核心思想很简单:切向畸变是 x 和 y 的耦合项。它不像径向畸变那样只跟半径有关,而是跟具体位置有关。
避坑指南:我曾经处理过一个工业检测项目,相机安装时稍微歪了一点。用纯径向模型校正后,图像中心区域看起来没问题,但边缘的直线还是弯的。后来加上切向畸变模型,一次就搞定了。所以,如果你的相机是人工安装的,千万别忽略切向畸变。
3.3 畸变参数标定方法概述
有了模型,下一步就是求参数。标定方法说白了就是:拿已知的图案去拍,然后反推畸变参数。
我按自己的经验,把主流方法分成三类:
- 基于棋盘格的传统标定(如张正友标定法)
- 基于直线特征的自动标定(如直线校正法)
- 基于深度学习的端到端标定(如直接回归畸变参数)
下面这张图展示了它们的关系:
3.3.1 传统棋盘格标定
这是最经典的方法。你打印一张棋盘格,从不同角度拍十几张照片,然后让算法自动检测角点,再通过最小二乘法求解畸变参数。
具体步骤:
- 采集图像:至少10张,覆盖不同角度和位置
- 角点检测:用OpenCV的
findChessboardCorners - 求解内参和畸变:用
calibrateCamera - 验证:用
undistort检查校正效果
我的习惯:采集图像时,尽量让棋盘格出现在图像的边缘和角落。因为畸变在边缘最明显,如果棋盘格只出现在中心区域,标定出来的参数对边缘畸变几乎没有约束力。我一般会保证每张照片的棋盘格至少覆盖图像面积的30%,并且至少有3张照片的棋盘格靠近图像边缘。
3.3.2 基于直线特征的自动标定
这个方法不需要标定板。它的原理很简单:现实世界中的直线,在畸变图像中应该是曲线。校正的目标就是把这些曲线拉直。
我特别喜欢这个方法的一个场景——户外监控摄像头。你不可能在几十米高的杆子上贴棋盘格,但你可以利用建筑物边缘、道路标线这些天然直线。
算法流程:
- 从图像中提取直线边缘(如Canny + Hough变换)
- 定义能量函数:所有直线在校正后应该变成直线
- 用非线性优化求解畸变参数,使能量函数最小
注意:这个方法对图像质量要求较高。如果场景中直线特征太少,或者直线本身就不直(比如弯曲的马路牙子),优化结果会很不稳定。我曾经在一个仓库场景试过,到处都是货架,直线倒是很多,但货架本身就不完全平行,结果校正出来的图像反而更奇怪了。
3.3.3 基于深度学习的端到端标定
这是近几年兴起的方法。直接用神经网络从图像中回归出畸变参数,或者直接输出校正后的图像。
优点很明显:
- 速度快:训练好后,单张图像推理只需几毫秒
- 不需要标定板:只要有大量畸变-校正图像对就行
- 能处理非标准畸变:比如镜头本身有缺陷的情况
缺点也很明显:
- 需要大量训练数据:而且数据要覆盖各种畸变程度
- 泛化能力有限:换一个镜头型号,可能就要重新训练
- 可解释性差:你很难说清楚网络到底学到了什么
我个人觉得,深度学习标定更适合大规模量产场景——同一款镜头生产几万个,标定参数都差不多,用传统方法一个个标太慢。但如果是做研究或者小批量项目,传统方法更靠谱。
3.4 本章小结
嗯,这一节内容不少,我帮你捋一下核心:
- 径向畸变是鱼眼的主要畸变,用Brown模型或多项式模型描述
- 切向畸变是镜头和传感器不平行造成的,千万别忽略
- 标定方法有三种:传统棋盘格(精度高)、直线特征(无标定板)、深度学习(速度快)