1. 项目概述
单目摄像头标定是计算机视觉领域的基础工作,就像给相机做"体检"一样重要。无论是普通镜头还是广角/鱼眼镜头,都需要通过标定来建立图像像素坐标与真实世界坐标之间的数学关系。我在工业检测和自动驾驶项目中做过不下20次摄像头标定,发现很多新手容易在镜头畸变校正这个环节翻车。
标定的核心目标是确定相机内参(焦距、主点坐标等)和畸变系数。普通镜头通常用Brown-Conrady模型,而鱼眼镜头则需要Kannala-Brandt等特殊模型。上周我刚用棋盘格完成了一个180°鱼眼镜头的标定,标定后的重投影误差控制在0.3像素以内,这个精度已经能满足大多数SLAM系统的需求。
2. 核心原理与技术选型
2.1 相机成像模型解析
普通镜头采用针孔模型,成像公式为:
code复制u = f_x * (X/Z) + c_x
v = f_y * (Y/Z) + c_y
其中(f_x, f_y)是焦距,(c_x, c_y)是主点坐标。但实际镜头都存在畸变,主要分为径向畸变和切向畸变。
鱼眼镜头的成像模型完全不同,其视角通常大于180°,采用等距投影模型:
code复制r = f * θ
θ是入射光线与光轴的夹角,r是像点到主点的距离。我在处理一个190°鱼眼镜头时,发现超过175°的区域标定误差会急剧增大,这时需要手动剔除边缘区域的角点。
2.2 标定工具对比
OpenCV是最常用的标定工具,但要注意版本差异:
- 3.x版本:支持普通镜头和鱼眼镜头
- 4.x版本:新增了omnidir模型,支持360°相机
MATLAB的Camera Calibrator工具箱交互体验更好,但实时性不如OpenCV。我建议:
- 快速验证用MATLAB
- 工程部署用OpenCV
- 特殊镜头(如折返式)可能需要自己实现标定算法
3. 标定实操全流程
3.1 标定板选择与制作
棋盘格是最常用的标定靶标,但要注意:
- 方格尺寸要精确测量(建议用游标卡尺测量3次取平均)
- 棋盘格要平整,我习惯用3mm厚的亚克力板做底板
- 方格数量建议在7x9到9x12之间
对于鱼眼镜头,标定板要足够大。我的经验公式:
code复制标定板边长 ≥ 2 * 相机到标定板距离 * tan(FOV/2)
例如FOV=180°时,标定板至少要距离相机1米,边长2米以上。
3.2 图像采集要点
采集时要注意:
- 普通镜头:15-20张不同角度,覆盖整个视场
- 鱼眼镜头:30张以上,特别注意边缘区域
- 光照要均匀,避免反光(我常用柔光箱)
- 相机焦距、光圈固定,禁用自动对焦
重要技巧:采集时让标定板占据图像1/3到2/3面积,这样角点检测最准
3.3 OpenCV标定代码详解
python复制# 鱼眼镜头标定示例
import cv2
import numpy as np
# 准备角点数据
obj_points = [] # 3D点
img_points = [] # 2D点
# 标定流程
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC + cv2.fisheye.CALIB_CHECK_COND
ret, K, D, rvecs, tvecs = cv2.fisheye.calibrate(
obj_points, img_points,
image_size, K, D,
criteria=criteria, flags=flags)
关键参数说明:
K: 内参矩阵D: 畸变系数(鱼眼有4个)flags: 推荐加上CHECK_COND避免数值不稳定
4. 标定结果验证与优化
4.1 重投影误差分析
误差计算公式:
code复制error = ||p - p'||
其中p是检测的角点,p'是重投影点。好的标定应该:
- 普通镜头:<0.5像素
- 鱼眼镜头:<1.0像素(边缘可放宽到2像素)
我常用的误差可视化方法:
python复制# 绘制误差矢量图
for i in range(len(img_points)):
img_points2, _ = cv2.projectPoints(obj_points[i], rvecs[i], tvecs[i], K, D)
error = cv2.norm(img_points[i], img_points2, cv2.NORM_L2)
cv2.line(img, tuple(img_points[i][0]), tuple(img_points2[0]), (0,0,255), 2)
4.2 标定常见问题排查
问题1:角点检测失败
- 原因:对比度不足或棋盘格太小
- 解决:调整光照或使用更大棋盘格
问题2:重投影误差大
- 原因:图像采集不足或标定板移动过快
- 解决:重新采集,确保标定板在三维空间均匀分布
问题3:鱼眼边缘畸变校正异常
- 原因:超过有效视角范围
- 解决:裁剪5%的边缘区域或改用全向模型
5. 工程实践中的经验技巧
5.1 温度对标定的影响
实测数据:
- 工业相机温度每升高10℃,焦距变化约0.02%
- 建议在恒温环境标定,或建立温度补偿模型
5.2 标定参数存储格式
推荐使用YAML格式:
yaml复制%YAML:1.0
camera_matrix: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [517.3, 0, 325.1, 0, 516.5, 241.2, 0, 0, 1]
distortion_coefficients: !!opencv-matrix
rows: 1
cols: 5
dt: d
data: [0.1, -0.2, 0.001, 0.003, 0.0]
5.3 标定自动化方案
我设计的自动化流程:
- 机械臂带动标定板运动
- 相机触发采集
- 自动检测标定质量
- 不合格时提示重新采集
这个方案将标定时间从2小时缩短到15分钟,重复精度提高40%。
6. 不同应用场景的标定策略
6.1 自动驾驶前视相机
特殊要求:
- 标定距离建议20-50米
- 需要与雷达联合标定
- 动态标定补偿车辆俯仰角变化
6.2 工业检测场景
注意事项:
- 工作距离固定时只需标定一次
- 要考虑镜头景深影响
- 建议每月复检一次标定参数
6.3 VR全景相机
技术难点:
- 多相机同步标定
- 重叠区域对齐
- 亮度一致性校正
我最近完成的一个六目全景相机标定项目,最终拼接误差控制在0.1像素以内,关键是在重叠区域使用了SIFT特征点辅助优化。