4、相机内参标定:针孔模型、畸变模型(径向/切向)、标定板设计、张正友标定法、OpenCV/Matlab标定工具实战
相机内参标定是视觉传感器与激光雷达、IMU等异构传感器进行外参联合标定的前置基础。如果内参不准,外参标定中的特征重投影误差会被系统性放大,导致融合系统在远距离目标上的定位精度急剧下降。本章从针孔成像的几何本质出发,深入剖析畸变来源与建模方式,并围绕张正友标定法给出从标定板设计到OpenCV/Matlab工具实战的完整闭环。
4.1 针孔模型与内参矩阵的几何本质
针孔模型是相机成像的理想化近似:三维空间中的点通过光心投影到像平面上。设世界坐标系下一点 \(P_w = (X_w, Y_w, Z_w)^T\),经外参(旋转矩阵 \(R\) 和平移向量 \(t\))变换到相机坐标系 \(P_c = R P_w + t\),再通过针孔投影得到归一化坐标 \(x' = X_c / Z_c\),\(y' = Y_c / Z_c\)。最终映射到像素坐标 \((u, v)\) 的完整公式为:
s * [u, v, 1]^T = K * [R | t] * [X_w, Y_w, Z_w, 1]^T
其中 K = [fx, 0, cx; 0, fy, cy; 0, 0, 1]
内参矩阵 \(K\) 中的 \(fx, fy\) 分别为 \(x\)、\(y\) 方向的等效焦距(单位像素),\(cx, cy\) 为主点坐标。需要特别强调的是,\(fx\) 与镜头物理焦距 \(f\)(毫米)的关系为 \(fx = f / dx\),其中 \(dx\) 为单个像素的物理宽度。在实际标定中,我们直接求解 \(fx, fy\),无需单独测量像素尺寸。
4.2 畸变模型:径向与切向的数学表达
实际镜头存在两类主要畸变:径向畸变源于透镜曲面形状误差,光线离光心越远弯曲越严重,表现为桶形(k1<0)或枕形(k1>0)失真;切向畸变源于透镜与成像平面不平行,产生梯形失真。OpenCV 采用 Brown-Conrady 模型,畸变系数向量 \(D = [k_1, k_2, p_1, p_2, k_3]\):
径向畸变:
x_distorted = x * (1 + k1*r^2 + k2*r^4 + k3*r^6)
y_distorted = y * (1 + k1*r^2 + k2*r^4 + k3*r^6)
切向畸变:
x_distorted = x + [2*p1*x*y + p2*(r^2 + 2*x^2)]
y_distorted = y + [p1*(r^2 + 2*y^2) + 2*p2*x*y]
其中 r^2 = x^2 + y^2,x、y 为归一化平面坐标
对于常规工业镜头,通常只需 \(k_1, k_2, p_1, p_2\) 四个系数;对于广角或鱼眼镜头,需引入 \(k_3\) 甚至更高阶项。标定工具会输出每个系数的标准差,若某个系数标准差过大(如超过系数本身),说明该系数不可靠,应将其置零重新标定。
| 畸变类型 | 主导系数 | 典型表现 | 校正优先级 |
|---|---|---|---|
| 径向(桶形) | k1 < 0 | 直线向外弯曲 | 高 |
| 径向(枕形) | k1 > 0 | 直线向内弯曲 | 高 |
| 切向 | p1, p2 | 梯形/平行四边形失真 | 中 |
| 高阶径向 | k3 | 画面边缘严重扭曲 | 低(仅广角) |
4.3 标定板设计与采集规范
标定板质量直接决定标定精度上限。推荐使用氧化铝基板+光刻工艺的陶瓷棋盘格,而非普通打印纸——后者在温湿度变化下热膨胀系数大,且表面不平整。设计要点如下:
- 棋盘格尺寸:推荐 10×7 或 12×9 内角点(即 11×8 或 13×10 格),方格边长 20-30mm。过少角点导致单应矩阵求解不稳定,过多则增加角点检测计算量。
- 平面度要求:标定板平面度误差应小于 0.1mm,否则在近距离标定时会引入系统性误差。
- 表面处理:哑光涂层避免反光,黑白格对比度需大于 5:1,确保角点检测算法稳定提取。
- 采集规范:至少 15-20 张图像,覆盖画面中心、四角、上下左右边缘;标定板倾斜角度控制在 15°-45° 之间,避免正对相机(退化位姿)。
4.4 张正友标定法核心流程
张正友标定法(Zhang's Method)利用平面标定板在不同位姿下的多张图像,通过单应矩阵约束求解内参。其核心步骤可归纳为:
- 角点检测:使用 OpenCV 的
findChessboardCorners或findCirclesGrid提取角点,并用cornerSubPix进行亚像素细化(窗口 5×5,迭代 30 次)。 - 单应矩阵求解:每张图像建立 3×3 单应矩阵 \(H\),将标定板平面映射到图像平面。利用 \(H\) 的正交约束构建线性方程组,求解内参初值。
- 畸变系数估计:在最小二乘框架下,将畸变模型线性化,交替优化内参和畸变系数。
- 非线性优化:使用 Levenberg-Marquardt 算法最小化重投影误差,得到最终内参和畸变系数。
# OpenCV Python 标定核心代码
import cv2
import numpy as np
# 棋盘格内角点数
pattern_size = (10, 7) # 10列7行
square_size = 0.025 # 方格边长25mm
# 准备对象点
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 *= square_size
obj_points = [] # 3D点
img_points = [] # 2D点
for img_path in image_paths:
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)
if ret:
corners_sub = cv2.cornerSubPix(gray, corners, (5,5), (-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)
# 评估重投影误差
total_error = 0
for i in range(len(obj_points)):
imgpoints2, _ = cv2.projectPoints(obj_points[i], rvecs[i], tvecs[i], mtx, dist)
error = cv2.norm(img_points[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2)
total_error += error
print(f"平均重投影误差: {total_error/len(obj_points):.4f} px")
4.5 实战案例:工业相机标定与精度验证
场景背景:某机器人抓取系统使用 Basler acA2440-75um 相机(2448×2048 分辨率,像元 3.45μm)搭配 16mm 镜头,工作距离 600mm,要求抓取定位精度 ±0.5mm。标定前发现机械臂视觉引导在视野边缘误差达 8mm。
初始现象:使用默认内参(厂家标称值)进行手眼标定后,在视野中心区域定位误差约 1.2mm,边缘区域误差急剧增大至 8mm,且呈明显桶形失真特征。
关键输入数据:采用 12×9 棋盘格(方格边长 25mm,平面度 0.05mm),采集 22 张图像,覆盖不同角度和位置。初始重投影误差 0.35px,其中 k1 = -0.082,p1 = 0.0012。
分析判断:重投影误差 0.35px 虽在可接受范围(<0.5px),但结合边缘误差 8mm 的表现,判断是畸变模型未充分拟合边缘区域。进一步检查发现,k3 系数标准差过大(0.015 vs 系数值 0.008),说明 k3 不可靠。
操作步骤:
- 将畸变模型从 5 参数(含 k3)降为 4 参数(去掉 k3),重新标定。
- 增加 5 张标定板靠近画面边缘的图像,提高边缘区域权重。
- 使用
cv2.getOptimalNewCameraMatrix计算优化后的内参,并采用cv2.undistort校正图像。 - 校正后重新进行手眼标定,验证定位精度。
结果对比:重投影误差从 0.35px 降至 0.12px;视野边缘定位误差从 8mm 降至 0.8mm;中心区域误差从 1.2mm 降至 0.3mm。系统整体抓取成功率从 82% 提升至 97%。
风险与代价:增加边缘图像后,标定时间从 5 分钟延长至 8 分钟;但精度提升显著。复盘发现,初始标定失败的主因是图像采集时标定板始终位于画面中心区域,导致畸变模型对边缘拟合不足。
calibrateCamera 返回的 per-view 误差)逐张检查,剔除重投影误差大于 0.5px 的异常图像。
4.6 常见误区与工程建议
| 误区 | 后果 | 正确做法 |
|---|---|---|
| 使用打印纸标定板 | 平面度差,精度损失 30%+ | 使用玻璃/陶瓷基板光刻标定板 |
| 图像数量不足 10 张 | 内参过拟合,泛化差 | 至少 15 张,覆盖全视野 |
| 忽略 k3 系数可靠性 | 边缘畸变校正过度 | 检查系数标准差,不可靠则置零 |
| 标定后不验证 | 误差累积到外参标定 | 用独立测试图验证重投影误差 |
| 固定焦距/光圈后重新标定 | 内参失效 | 变焦或调光圈后必须重新标定 |
最后强调,内参标定不是一次性工作。在车载、机器人等振动环境中,镜头固定螺丝松动或温度变化都会导致内参漂移。建议每 3-6 个月或每次拆装镜头后重新标定,并在外参标定前用 cv2.projectPoints 快速验证内参一致性。