4、相机内参标定:针孔模型、畸变模型(径向、切向)、标定板设计、张正友标定法原理与流程、OpenCV/Matlab标定工具使用

相机内参标定是视觉感知、三维重建与多传感器融合的基础环节。无论是单目视觉里程计、双目立体匹配,还是相机与激光雷达/毫米波雷达的外参联合标定,其精度上限都直接取决于内参标定的准确性。本章从理想针孔模型出发,逐步引入真实镜头的径向与切向畸变,系统讲解标定板的设计要点、张正友平面标定法的数学原理与工程流程,并给出基于OpenCV与Matlab的实操指南。理解内参标定不仅是学会调用API,更关键的是掌握标定误差的来源、棋盘格/圆点格的选择逻辑以及重投影误差的解读方法。

相机内参标定核心链路 世界坐标系 标定板角点 已知物理尺寸 相机坐标系 光心为原点 Z轴指向前方 图像坐标系 物理单位(mm) 主点偏移 像素坐标系 离散整数(u,v) fx, fy, cx, cy R, T 外参 透视投影 f 像素化 dx, dy 畸变模型(非线性修正) 径向畸变(桶形/枕形) k1, k2, k3 r² = x² + y² 切向畸变(透镜装配) p1, p2 x·y 耦合项 校正后像素坐标 x_corr = x(1+k1r²+k2r⁴) + 2p1xy + p2(r²+2x²) 标定板设计要点 • 棋盘格:角点检测稳定 • 圆点格:圆心亚像素精度 • 非对称性(避免旋转歧义) • 平面度 < 0.1mm 张正友标定法流程 ① 拍摄≥10张不同位姿 ② 提取角点坐标 ③ 单应矩阵求解 ④ 线性初值→非线性优化 OpenCV / Matlab cv2.calibrateCamera() 重投影误差 < 0.1px Matlab Camera Calibrator 交互式剔除异常帧 输出:fx, fy, cx, cy, k1, k2, p1, p2, k3

4.1 针孔模型与内参矩阵

理想相机模型采用针孔成像原理,即三维空间点通过光心投影到成像平面。设世界坐标系下一点 Pw = (X, Y, Z)T,经外参(旋转矩阵 R 和平移向量 t)变换到相机坐标系 Pc = R·Pw + t。随后通过透视投影得到归一化平面坐标 (x, y) = (Xc/Zc, Yc/Zc)。最终由内参矩阵 K 映射到像素坐标 (u, v):

[u]   [fx  0  cx] [x]
[v] = [ 0 fy  cy] [y]
[1]   [ 0  0   1] [1]

其中 fx = f/dx,fy = f/dy,f 为焦距(mm),dx、dy 为单个像素的物理尺寸(mm/pixel),cx、cy 为主点(光轴与成像平面交点)的像素坐标。内参矩阵 K 共 4 个自由度(fx, fy, cx, cy),是标定求解的核心目标。需要特别指出,现代相机传感器像素通常为正方形(dx = dy),但工业相机或特殊镜头可能存在非正方形像素,因此 fx 与 fy 需分别求解,不可强制相等。

工程经验:对于分辨率 1920×1080、像素尺寸 3.45μm 的相机,理论 fx ≈ 1920 / (3.45×10-3) × f_mm。若标定结果 fx 与 fy 差异超过 0.5%,应检查标定板是否倾斜过大或图像是否存在拉伸变形。

4.2 畸变模型:径向与切向

实际镜头存在非线性畸变,主要分为径向畸变和切向畸变。径向畸变源于透镜形状,表现为图像边缘的桶形或枕形变形,用多项式模型描述:

x_dist = x(1 + k1·r² + k2·r⁴ + k3·r⁶)
y_dist = y(1 + k1·r² + k2·r⁴ + k3·r⁶)

其中 r² = x² + y²,k1、k2 为低阶畸变系数,k3 通常仅用于鱼眼或广角镜头。切向畸变由透镜与成像平面不平行(装配误差)引起,模型为:

x_corr = x_dist + [2·p1·x·y + p2·(r² + 2x²)]
y_corr = y_dist + [p1·(r² + 2y²) + 2·p2·x·y]

完整畸变参数向量为 [k1, k2, p1, p2, k3]。OpenCV 默认采用 5 参数模型,Matlab 支持 2 参数(仅 k1, k2)或 3 参数(k1, k2, k3)简化模型。标定时应优先使用完整模型,若 k3 标定结果接近 0 且重投影误差无明显改善,可降为 4 参数模型以提升数值稳定性。

畸变类型参数物理成因对图像的影响校正优先级
径向(低阶)k1, k2透镜球面形状边缘直线弯曲必须校正
径向(高阶)k3超广角/鱼眼镜头极端桶形畸变视镜头而定
切向p1, p2透镜与传感器不平行图像梯形/平行四边形变形通常较小,但需校正

4.3 标定板设计:棋盘格与圆点格

标定板是提供已知三维特征点的物理基准。最常用的是棋盘格与圆点阵列。棋盘格通过 Harris 或亚像素角点检测获得交点坐标,角点位置精度高且检测算法成熟。圆点格则利用圆心作为特征点,对模糊和光照变化更鲁棒,且圆心定位可达到亚像素级。设计标定板需遵循以下原则:

  • 非对称性:棋盘格行列数必须一奇一偶(如 9×6),避免旋转 180° 后方向歧义;圆点格需设置一个较大的“方向圆”打破对称性。
  • 尺寸精度:方格边长或圆点间距需用高精度打印(≥1200dpi)并实测验证,误差控制在 ±0.01mm 以内。
  • 平面度:标定板粘贴在光学玻璃或铝合金平板上,平面度优于 0.1mm,避免弯曲导致特征点 Z 坐标偏差。
  • 表面处理:哑光涂层防止反光,黑白对比度需大于 5:1,确保角点检测稳定。
常见误区:使用 A4 纸打印标定板时,纸张受潮或弯曲会引入毫米级误差,直接导致标定焦距偏差 1%~3%。工业级标定应使用陶瓷或玻璃基底标定板,并定期用三坐标测量仪校验。

4.4 张正友标定法:原理与流程

张正友标定法(Zhang's Method)利用平面标定板在不同位姿下的多幅图像,通过单应矩阵约束求解内参。其核心思想是:对于每幅图像,标定板平面到图像平面存在一个单应矩阵 H = K·[r1, r2, t],其中 r1、r2 为旋转矩阵的前两列。利用旋转矩阵的正交性(r1T·r2 = 0,|r1| = |r2|),可建立关于内参的线性约束方程。具体流程如下:

  1. 数据采集:固定相机,移动标定板拍摄 10~20 张图像,覆盖画面中心、边缘、倾斜(≤45°)、远近等位姿。
  2. 角点提取:使用 cv2.findChessboardCorners 或 Matlab 的 detectCheckerboardPoints 提取亚像素角点。
  3. 单应矩阵求解:每幅图像建立 2 个约束方程,至少 3 幅图像可线性求解内参初值。
  4. 极大似然优化:以重投影误差最小化为目标,使用 Levenberg-Marquardt 算法迭代优化内参、畸变系数和外参。
  5. 结果评估:计算所有角点的平均重投影误差(RMS),通常要求 < 0.1 像素。
案例拆解:某自动驾驶项目使用 1920×1080 相机,标定板为 12×9 棋盘格(方格边长 30mm)。采集 15 张图像后,OpenCV 标定结果:fx = 1423.5,fy = 1421.8,cx = 960.2,cy = 540.1,k1 = -0.042,k2 = 0.013,p1 = 0.0002,p2 = -0.0001,RMS = 0.08px。但将标定板移至画面最边缘时,重投影误差增大至 0.35px。分析发现边缘图像存在运动模糊,剔除 2 张低质量帧后 RMS 降至 0.06px。复盘结论:标定数据采集时需确保每帧图像清晰,且标定板占据画面 1/3 以上面积。

4.5 OpenCV 与 Matlab 标定工具实战

OpenCV 提供完整的 C++/Python API,核心函数为 cv2.calibrateCamera()。Python 示例代码如下:

import cv2
import numpy as np

# 准备角点世界坐标(Z=0平面)
pattern_size = (9, 6)  # 内角点数
objp = np.zeros((pattern_size[0]*pattern_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2)
objp *= 30.0  # 方格边长30mm

obj_points = []  # 世界坐标
img_points = []  # 像素坐标

for fname in image_files:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)
    if ret:
        corners_sub = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1),
                                       (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))
        obj_points.append(objp)
        img_points.append(corners_sub)

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(
    obj_points, img_points, gray.shape[::-1], None, None)

print("内参矩阵:\n", mtx)
print("畸变系数:", dist.ravel())
print("重投影误差:", ret)

Matlab 的 Camera Calibrator App 提供图形化界面,支持拖拽导入图像、自动检测棋盘格/圆点格、交互式剔除异常帧,并可直接导出相机参数对象。两者标定结果应高度一致,若差异超过 0.5%,需检查角点提取顺序或标定板尺寸设置是否一致。

对比维度OpenCVMatlab
角点检测findChessboardCorners + cornerSubPixdetectCheckerboardPoints(自动)
畸变模型默认5参数(k1,k2,p1,p2,k3)支持2/3/5参数可选
异常帧处理需手动编写逻辑图形界面直接剔除
批量处理适合自动化脚本适合交互式分析
输出格式NumPy数组cameraParameters对象

4.6 标定质量评估与常见误区

标定完成后,必须进行质量验证。最直接的指标是重投影误差(RMS),即所有角点的检测像素坐标与重投影像素坐标的均方根距离。RMS < 0.1px 为优秀,< 0.2px 为合格,超过 0.3px 应重新标定。此外,可通过以下方法交叉验证:

  • 直线度测试:拍摄一张含直线的场景,校正后直线应恢复为直线。
  • 重复性测试:同一相机多次标定,fx 波动应 < 0.3%。
  • 外参一致性:双目系统中,同一标定板位姿下左右相机外参应稳定。
高频误区:① 标定板图像数量不足(< 8 张)导致内参过拟合;② 标定板仅出现在画面中央,边缘畸变参数无法约束;③ 使用自动对焦镜头标定后变焦,导致焦距失效;④ 忽略标定板厚度,在 Z=0 平面引入系统偏差。正确做法是使用手动对焦并锁定焦距,标定板覆盖画面 80% 区域,且包含明显的倾斜和旋转位姿。

总结而言,相机内参标定是感知系统的“出厂校准”环节,其精度直接影响后续所有视觉算法的性能。掌握针孔模型与畸变模型的数学本质,理解标定板设计的物理约束,熟练运用张正友标定法及 OpenCV/Matlab 工具,并建立严格的质量评估流程,是每一位视觉工程师的基本功。在实际工程中,建议将标定流程脚本化、自动化,并定期复标以应对镜头松动或温度漂移带来的参数变化。