4、相机内参标定:针孔模型、畸变模型(径向、切向)、标定板设计、张正友标定法原理与流程、OpenCV/Matlab标定工具使用
相机内参标定是视觉感知、三维重建与多传感器融合的基础环节。无论是单目视觉里程计、双目立体匹配,还是相机与激光雷达/毫米波雷达的外参联合标定,其精度上限都直接取决于内参标定的准确性。本章从理想针孔模型出发,逐步引入真实镜头的径向与切向畸变,系统讲解标定板的设计要点、张正友平面标定法的数学原理与工程流程,并给出基于OpenCV与Matlab的实操指南。理解内参标定不仅是学会调用API,更关键的是掌握标定误差的来源、棋盘格/圆点格的选择逻辑以及重投影误差的解读方法。
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 需分别求解,不可强制相等。
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,确保角点检测稳定。
4.4 张正友标定法:原理与流程
张正友标定法(Zhang's Method)利用平面标定板在不同位姿下的多幅图像,通过单应矩阵约束求解内参。其核心思想是:对于每幅图像,标定板平面到图像平面存在一个单应矩阵 H = K·[r1, r2, t],其中 r1、r2 为旋转矩阵的前两列。利用旋转矩阵的正交性(r1T·r2 = 0,|r1| = |r2|),可建立关于内参的线性约束方程。具体流程如下:
- 数据采集:固定相机,移动标定板拍摄 10~20 张图像,覆盖画面中心、边缘、倾斜(≤45°)、远近等位姿。
- 角点提取:使用 cv2.findChessboardCorners 或 Matlab 的 detectCheckerboardPoints 提取亚像素角点。
- 单应矩阵求解:每幅图像建立 2 个约束方程,至少 3 幅图像可线性求解内参初值。
- 极大似然优化:以重投影误差最小化为目标,使用 Levenberg-Marquardt 算法迭代优化内参、畸变系数和外参。
- 结果评估:计算所有角点的平均重投影误差(RMS),通常要求 < 0.1 像素。
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%,需检查角点提取顺序或标定板尺寸设置是否一致。
| 对比维度 | OpenCV | Matlab |
|---|---|---|
| 角点检测 | findChessboardCorners + cornerSubPix | detectCheckerboardPoints(自动) |
| 畸变模型 | 默认5参数(k1,k2,p1,p2,k3) | 支持2/3/5参数可选 |
| 异常帧处理 | 需手动编写逻辑 | 图形界面直接剔除 |
| 批量处理 | 适合自动化脚本 | 适合交互式分析 |
| 输出格式 | NumPy数组 | cameraParameters对象 |
4.6 标定质量评估与常见误区
标定完成后,必须进行质量验证。最直接的指标是重投影误差(RMS),即所有角点的检测像素坐标与重投影像素坐标的均方根距离。RMS < 0.1px 为优秀,< 0.2px 为合格,超过 0.3px 应重新标定。此外,可通过以下方法交叉验证:
- 直线度测试:拍摄一张含直线的场景,校正后直线应恢复为直线。
- 重复性测试:同一相机多次标定,fx 波动应 < 0.3%。
- 外参一致性:双目系统中,同一标定板位姿下左右相机外参应稳定。
总结而言,相机内参标定是感知系统的“出厂校准”环节,其精度直接影响后续所有视觉算法的性能。掌握针孔模型与畸变模型的数学本质,理解标定板设计的物理约束,熟练运用张正友标定法及 OpenCV/Matlab 工具,并建立严格的质量评估流程,是每一位视觉工程师的基本功。在实际工程中,建议将标定流程脚本化、自动化,并定期复标以应对镜头松动或温度漂移带来的参数变化。