1. 畸变校正基础:什么是镜头畸变?径向畸变与切向畸变的数学模型

大家好,欢迎来到《畸变校正与图像质量调优系统指南》的第一章。

说到镜头畸变,我印象特别深。刚入行那会儿,我拿着刚买的广角镜头去拍建筑,回来一看照片——好好的摩天大楼变成了比萨斜塔。当时我还以为是相机坏了,后来才知道,这就是典型的镜头畸变。

说白了,镜头畸变就是相机“撒谎”了。它拍出来的东西,跟现实世界对不上。你想想看,一个完美的镜头应该把直线拍成直线,把正方形拍成正方形。但现实中的镜头,尤其是广角和变焦镜头,总会带点“私心”。

核心定义:镜头畸变是光学系统固有的成像误差,源于透镜的物理形状和组装偏差。它导致图像中的几何关系与真实场景不一致。

1.1 畸变从哪来?

我习惯把畸变的原因分成两类:

  • 物理原因:透镜是球面的,光线经过不同区域时折射角度不一样。边缘的光线比中心的光线弯得更厉害。
  • 机械原因:镜头组在装配时,镜片之间不可能做到平行。哪怕偏了0.1毫米,图像边缘就会变形。

嗯,这里要注意:畸变不是“坏镜头”的专利。哪怕几万块的电影镜头,也有畸变,只是程度不同。我在项目中遇到过客户抱怨“我们用的可是蔡司镜头,怎么还有畸变?”——我只好解释,畸变是物理定律,不是工艺问题。

1.2 径向畸变:镜头“肚子”的问题

径向畸变是最常见的一种。它沿着镜头半径方向发生,说白了就是图像被“撑大”或“挤小”了。

为什么会这样?因为光线经过球面透镜时,边缘的折射率跟中心不一样。离光轴越远,偏差越大。

径向畸变分两种:

类型 现象 常见场景
桶形畸变 图像向外膨胀,直线向外弯曲 广角镜头、手机前置摄像头
枕形畸变 图像向内收缩,直线向内弯曲 长焦镜头、变焦镜头远端

我记得有一次做车载环视系统,四个鱼眼镜头全是桶形畸变。如果不校正,拼接出来的俯视图就像哈哈镜一样。那会儿我天天盯着畸变参数调,眼睛都快花了。

径向畸变的数学模型

数学上,我们用多项式来描述径向畸变。假设理想图像坐标为 (x, y),畸变后的坐标为 (xd, yd),径向距离 r = √(x² + y²)。那么:

x_d = x * (1 + k1*r² + k2*r⁴ + k3*r⁶)
y_d = y * (1 + k1*r² + k2*r⁴ + k3*r⁶)

这里 k1、k2、k3 就是径向畸变系数。你想想看,r 越大(越靠近图像边缘),r²、r⁴、r⁶ 增长得越快,畸变就越明显。

我的经验:大多数情况下,只用 k1 和 k2 就够了。k3 一般用于鱼眼镜头或超大广角。我曾经为了省事,给普通镜头也用了三阶模型,结果过拟合了,校正后的图像反而出现了波浪形扭曲。所以,别贪多。

1.3 切向畸变:镜头“歪了”的问题

切向畸变,说白了就是镜头没装正。镜片组的光轴没跟成像平面垂直,或者镜片之间有了偏移。

这种现象在手机摄像头里特别常见。你想想,手机那么薄,镜头模组是硬塞进去的,装配公差很难控制。我拆过几台手机摄像头,里面的镜片就靠胶水固定,稍微偏一点,切向畸变就出来了。

切向畸变的表现是:图像中的直线变成斜线,或者图像整体有“倾斜感”。比如拍一个矩形,它可能变成平行四边形。

切向畸变的数学模型

切向畸变用两个参数 p1、p2 来描述:

x_d = x + [2*p1*x*y + p2*(r² + 2*x²)]
y_d = y + [p1*(r² + 2*y²) + 2*p2*x*y]

注意看,这里跟径向畸变不一样。径向畸变只跟 r 有关,而切向畸变跟 x 和 y 的具体位置都有关。所以它造成的变形是不对称的。

避坑指南:我曾经在标定一个工业相机时,发现径向畸变参数怎么调都不对。折腾了两天,最后发现是镜头没拧紧,产生了微小的切向偏移。拧紧后重新标定,一切正常。所以,做畸变校正前,先检查机械结构。

1.4 两种畸变的对比

对比维度 径向畸变 切向畸变
根本原因 透镜球面折射 镜片装配偏差
变形方向 沿半径方向 沿切线方向
对称性 中心对称 不对称
参数数量 3个 (k1, k2, k3) 2个 (p1, p2)
常见程度 几乎每个镜头都有 装配质量差的镜头常见
校正难度 较容易 需要精确标定

1.5 完整畸变模型

实际应用中,我们把径向和切向畸变合在一起。完整的畸变模型就是:

// 先算径向畸变
x_radial = x * (1 + k1*r² + k2*r⁴ + k3*r⁶)
y_radial = y * (1 + k1*r² + k2*r⁴ + k3*r⁶)

// 再加上切向畸变
x_distorted = x_radial + [2*p1*x*y + p2*(r² + 2*x²)]
y_distorted = y_radial + [p1*(r² + 2*y²) + 2*p2*x*y]

这个模型就是 OpenCV 里 cv::fisheye 和 cv::calibrateCamera 用的标准模型。你如果做过相机标定,应该对这套公式不陌生。

关键点:畸变校正是“反推”过程。我们已知畸变后的图像,想恢复理想图像。所以实际算法是:遍历目标图像的每个像素,用上述模型反算出它在原图的位置,然后插值采样。

1.6 知识结构图

下面这张图帮你理清本章的知识脉络:

镜头畸变知识体系 镜头畸变 物理原因:透镜球面 机械原因:装配偏差 径向畸变 切向畸变 完整畸变模型 桶形畸变 枕形畸变 p1, p2 参数 径向 + 切向联合 核心公式 径向:x_d = x·(1 + k₁r² + k₂r⁴ + k₃r⁶) 切向:x_d = x + [2p₁xy + p₂(r² + 2x²)]

1.7 小结

这一章我们聊了镜头畸变的本质和数学模型。总结几个要点:

  • 径向畸变是透镜物理特性导致的,用 k1、k2、k3 描述
  • 切向畸变是装配偏差导致的,用 p1、p2 描述
  • 完整模型是两者叠加,OpenCV 标定输出的就是这5个参数
  • 畸变校正是“反推”过程,不是“正推”

我个人习惯,拿到一个新镜头,第一件事就是做标定,看看它的畸变参数有多大。如果 k1 超过 0.1,那这个镜头的畸变就比较明显了,校正时要特别小心边缘区域。