4、畸变模型:径向畸变、切向畸变、畸变公式、OpenCV中的畸变系数顺序
在相机标定中,我们通常假设相机满足理想的小孔成像模型,即三维空间点、光心与像点三点共线。然而,真实镜头由于制造工艺、装配误差和光学设计限制,成像光线会发生弯曲,导致实际像点偏离理想位置,这种偏离统称为镜头畸变。畸变模型是连接理想像素坐标与实际像素坐标的数学桥梁,也是标定算法中需要求解的核心参数之一。理解畸变的物理来源、数学表达以及在OpenCV中的存储顺序,是进行高精度标定、图像校正和三维重建的前提。本章将系统讲解径向畸变与切向畸变的原理、畸变公式的推导逻辑,并重点剖析OpenCV中畸变系数向量的排列规则。
上图展示了畸变模型的整体框架:理想成像模型是基准,真实镜头因光学缺陷产生畸变,畸变分为径向和切向两类,最终通过OpenCV的系数向量进行数学描述。下面我们逐一深入每个环节。
4.1 径向畸变:成因与数学模型
核心原理:径向畸变是镜头光学设计中最主要的畸变来源,表现为像点沿径向方向(从主点向外或向内)发生位移。其物理根源在于镜头的曲面形状——球面透镜无法将所有光线完美汇聚到同一焦点,导致不同入射高度的光线在像面上的放大率不一致。当镜头边缘的放大率小于中心时,图像呈现“桶形畸变”(广角镜头常见);当边缘放大率大于中心时,则呈现“枕形畸变”(长焦镜头常见)。
径向畸变的数学建模基于泰勒级数展开。设归一化图像坐标(已去除内参影响)为 (x, y),其到主点的距离为 r = √(x² + y²),则畸变后的坐标 (xdistorted, ydistorted) 可表示为:
x_distorted = x * (1 + k1*r² + k2*r⁴ + k3*r⁶)
y_distorted = y * (1 + k1*r² + k2*r⁴ + k3*r⁶)
其中 k1、k2、k3 为径向畸变系数。k1 描述主要畸变程度,k2 描述高阶畸变,k3 通常用于鱼眼镜头或高精度标定。对于普通镜头,k3 常设为0。值得注意的是,该公式是在归一化坐标下定义的,即坐标已除以焦距并减去主点偏移,这样畸变模型与相机分辨率无关,便于跨相机比较。
4.2 切向畸变:成因与数学模型
核心原理:切向畸变源于镜头与图像传感器(或镜头组内部镜片)之间的装配不平行,即光轴与传感器平面存在微小倾斜角。这种倾斜导致光线在通过镜头时产生非对称的偏移,像点在切向方向(垂直于径向)发生位移。切向畸变在低端摄像头或受碰撞的镜头中尤为明显。
切向畸变的数学模型由 Brown-Conrady 模型给出,引入两个系数 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 描述水平方向的倾斜。实际标定中,切向畸变系数通常远小于径向畸变系数,但在高精度测量场景(如工业视觉定位)中不可忽略。
| 畸变类型 | 物理来源 | 系数 | 主要影响区域 | 典型量级 |
|---|---|---|---|---|
| 径向畸变 | 镜头球面像差 | k1, k2, k3 | 图像边缘(径向) | 10⁻³ ~ 10⁻¹ |
| 切向畸变 | 镜头/传感器装配倾斜 | p1, p2 | 图像四角(切向) | 10⁻⁴ ~ 10⁻² |
4.3 完整畸变公式与OpenCV系数顺序
核心原理:将径向和切向畸变合并,得到完整的畸变模型。在OpenCV中,畸变系数以向量形式存储,其顺序有严格规定。对于标准标定(使用 cv::calibrateCamera),畸变系数向量 distCoeffs 的长度为4、5或8,具体含义如下:
- 4参数:
[k1, k2, p1, p2]—— 适用于畸变较小的镜头,忽略 k3。 - 5参数:
[k1, k2, p1, p2, k3]—— 最常用,包含三阶径向畸变。 - 8参数:
[k1, k2, p1, p2, k3, k4, k5, k6]—— 用于鱼眼镜头或高精度模型,其中 k4~k6 为更高阶径向系数。
OpenCV的文档明确说明,无论向量长度如何,前四个元素始终是 k1, k2, p1, p2。这一点在编写代码时极易出错——若将 p1, p2 误认为 k3, k4,会导致标定结果完全错误。此外,OpenCV的畸变公式与上述 Brown-Conrady 模型略有差异,其实际实现为:
x_distorted = x * (1 + k1*r² + k2*r⁴ + k3*r⁶) + 2*p1*x*y + p2*(r² + 2*x²)
y_distorted = y * (1 + k1*r² + k2*r⁴ + k3*r⁶) + p1*(r² + 2*y²) + 2*p2*x*y
注意:OpenCV在计算时,若使用5参数模型,k3 参与计算;若使用4参数模型,k3 被忽略。在调用 cv::undistort 或 cv::initUndistortRectifyMap 时,必须确保传入的畸变系数顺序正确。
[k1, k2, p1, p2, k3] 顺序,与 OpenCV 一致,但某些第三方库(如 ROS 的 camera_info)可能使用不同排列。务必查阅目标库的官方文档。
4.4 案例拆解:从标定结果到畸变校正
场景与目标:某工业机器人视觉引导项目,使用 500 万像素工业相机(分辨率 2448×2048)搭配 8mm 定焦镜头,工作距离约 500mm。系统需要实现 ±0.1mm 的定位精度。初始测试发现,在图像边缘区域,机器人抓取位置偏差达到 2~3mm,怀疑是镜头畸变未校正所致。
关键数据与现象:使用 12×9 棋盘格(方格边长 20mm)拍摄 25 张不同位姿图像,通过 OpenCV 标定得到内参矩阵和畸变系数:
内参矩阵 (fx, fy, cx, cy) = (3452.7, 3450.1, 1224.3, 1023.8)
畸变系数 (5参数) = [-0.2841, 0.0823, -0.0012, 0.0008, -0.0156]
分析:k1 = -0.2841 为负值,表明存在明显的桶形畸变;k2 = 0.0823 为正,用于修正边缘过度收缩;p1, p2 接近零,说明装配精度良好;k3 = -0.0156 较小,但保留可提升边缘精度。
操作步骤:
- 使用
cv::initUndistortRectifyMap计算映射表,参数选择CV_32FC1类型。 - 调用
cv::remap对每帧图像进行校正,采用双线性插值。 - 校正后重新测量棋盘格角点,计算重投影误差:从 0.32 像素降至 0.08 像素。
- 在机器人抓取测试中,边缘区域定位偏差从 2.5mm 降至 0.15mm,满足 ±0.1mm 的工艺要求。
风险与代价:校正后的图像边缘区域会有约 8% 的像素被裁剪(因桶形畸变校正后边缘拉伸),需重新调整 ROI 区域。此外,若使用 4 参数模型(忽略 k3),边缘精度会下降约 0.3mm,因此必须保留 k3。
复盘经验:畸变系数顺序错误是标定流程中最隐蔽的错误。建议在标定后立即打印系数向量,并与已知的棋盘格图像进行视觉对比——若校正后直线仍弯曲,优先检查系数顺序。另外,标定图像的位姿多样性(倾斜、旋转、边缘)直接影响 k1~k3 的稳定性,应确保棋盘格覆盖视场各区域。
4.5 常见误区与总结复盘
误区一:忽略切向畸变。许多教程只讲径向畸变,但实际镜头装配误差总会引入切向分量。即使 p1, p2 很小,在高精度测量中也会造成系统性偏差。建议始终使用5参数模型。
误区二:混淆归一化坐标与像素坐标。畸变公式中的 (x, y) 是归一化坐标(已除以焦距),而非像素坐标。若直接对像素坐标应用畸变公式,结果完全错误。OpenCV 内部会自动进行坐标转换,但自定义代码时需格外小心。
误区三:k3 随意置零。对于广角镜头或鱼眼镜头,k3 对边缘畸变的修正至关重要。即使标定结果中 k3 数值较小,也应保留。若使用4参数模型,应确认镜头畸变确实较小(如长焦镜头)。
误区四:畸变系数与内参的耦合。标定过程中,内参 (fx, fy, cx, cy) 与畸变系数是联合优化的。若初始猜测值偏差过大,可能收敛到局部最优解。建议使用 cv::CALIB_USE_INTRINSIC_GUESS 时提供合理初值,或先使用 cv::CALIB_FIX_ASPECT_RATIO 简化问题。