4. 相机标定基础:内参、外参、畸变模型,标定板的选择与标定流程
在3D视觉抓取系统中,相机标定是决定抓取精度上限的第一道关卡。如果标定结果存在偏差,后续的点云配准、位姿估计和机器人运动学解算都会产生系统性误差。本章将围绕Halcon环境下的相机标定,深入剖析内参、外参、畸变模型的核心数学意义,并给出标定板选型与完整标定流程的工程化建议。
4.1 相机成像模型与参数体系
相机标定的本质是求解从三维世界坐标到二维像素坐标的映射关系。这个映射可以拆解为四个坐标系的连续变换:世界坐标系(World)、相机坐标系(Camera)、图像物理坐标系(Image)和像素坐标系(Pixel)。
完整的投影方程如下:
Zc * [u, v, 1]^T = K * [R | t] * [Xw, Yw, Zw, 1]^T
其中,K 为内参矩阵,[R | t] 为外参矩阵(旋转和平移),Zc 为相机坐标系下的深度值。
4.1.1 内参矩阵(Intrinsic Matrix)
内参矩阵描述了相机光学中心到像素平面的投影关系,其形式为:
K = [ fx 0 cx ]
[ 0 fy cy ]
[ 0 0 1 ]
- fx, fy:分别为x轴和y轴方向的归一化焦距,单位是像素。它们与物理焦距 f 和像元尺寸 dx, dy 的关系为 fx = f/dx,fy = f/dy。
- cx, cy:主点坐标,即光轴与成像平面的交点,理想情况下位于图像中心,但实际制造中会有偏移。
在Halcon中,内参通过 cam_par 元组表示,例如 ['area_scan_division', 0.008, -500, 8.5e-6, 8.5e-6, 640, 512, 1280, 1024],其中包含畸变系数、焦距、像元尺寸和图像宽高等信息。
4.1.2 外参矩阵(Extrinsic Matrix)
外参矩阵将世界坐标系中的点变换到相机坐标系。它由旋转矩阵 R(3x3)和平移向量 t(3x1)组成。在抓取场景中,外参通常指相机相对于机器人基座或标定板的位置姿态。Halcon中通过 pose 类型表示,包含平移向量和旋转角(如欧拉角或四元数)。
camera_calibration 算子返回的 CameraParam 和 Pose 分别对应内参和外参。外参的旋转顺序默认是 'gba'(即绕X、Y、Z轴依次旋转),理解这一点对于后续手眼标定中的坐标变换至关重要。
4.1.3 畸变模型(Distortion Model)
实际镜头存在光学畸变,主要包括径向畸变和切向畸变。Halcon支持两种畸变模型:Division模型和Polynomial模型。
- Division模型:使用一个参数 K 描述径向畸变,计算量小,适合广角镜头和实时性要求高的场景。其畸变校正公式为:
u_corr = u / (1 + K * r^2),其中 r 为像素点到主点的距离。 - Polynomial模型:使用三个径向参数(K1, K2, K3)和两个切向参数(P1, P2),精度更高,适用于高精度测量或畸变较大的镜头。
切向畸变通常由镜头与成像平面不平行引起,在精密抓取中不可忽略。Halcon中通过 change_radial_distortion_cam_par 算子可以在不同畸变模型间转换。
4.2 标定板的选择策略
标定板是标定精度的物理基准。选择不当会导致标定失败或精度不足。以下是工程选型的关键维度:
| 标定板类型 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| 陶瓷/玻璃棋盘格 | 高精度实验室、静态抓取 | 热膨胀系数低,平整度极高 | 易碎,价格高 |
| 亚克力/塑料棋盘格 | 现场调试、频繁更换 | 轻便、成本低 | 温度变形大,精度有限 |
| 圆形阵列板(实心圆) | 大视角、低纹理场景 | 圆心提取精度高,抗噪能力强 | 需要保证圆间距精确 |
| ChArUco板 | 部分遮挡、多视角标定 | 支持单张标定,鲁棒性好 | 编码解码增加计算量 |
标定板的尺寸选择应遵循以下原则:标定板在图像中的面积占比应达到 20% - 40%。如果占比过小,角点提取的亚像素精度会下降;占比过大,则无法覆盖图像边缘的畸变区域。
4.3 Halcon标定流程详解
Halcon提供了一套完整的标定算子链,推荐使用 calibrate_cameras 算子进行多图像联合优化。以下是标准流程:
4.3.1 图像采集与预处理
采集10-20张不同姿态的标定板图像。要求:
- 标定板需覆盖图像的九个区域(四角、四边中点、中心)。
- 标定板与相机光轴夹角在 ±30° 以内,避免过大倾斜导致角点提取失败。
- 光照均匀,避免反光和阴影。
使用 find_calib_object 算子自动检测标定板,该算子返回标定板上的特征点坐标(如棋盘格角点或圆心)。
* 创建标定模型
create_calib_data ('calibration_object', 'camera', 1, 1, CalibHandle)
* 设置相机初始内参(可使用相机出厂参数或估算值)
set_calib_data_cam_param (CalibHandle, 0, 'area_scan_division', [0.008, -500, 8.5e-6, 8.5e-6, 640, 512, 1280, 1024])
* 设置标定板描述文件(描述标定板类型、尺寸、间距)
set_calib_data_calib_object (CalibHandle, 0, 'calplate_100mm.descr')
* 读取图像并查找标定板
read_image (Image, 'calib_image_01.png')
find_calib_object (Image, CalibHandle, 0, 0, 0, [], [])
* 收集所有图像后执行标定
calibrate_cameras (CalibHandle, Errors)
* 获取标定结果
get_calib_data (CalibHandle, 'camera', 0, 'params', CameraParam)
get_calib_data (CalibHandle, 'calib_obj_pose', [0, 0], 'pose', Pose)
4.3.2 标定质量评估
标定完成后,必须检查 Errors 输出。该值表示重投影误差(单位:像素)。经验阈值如下:
- 优秀:平均误差 < 0.1 像素
- 合格:平均误差 < 0.3 像素
- 不合格:平均误差 > 0.5 像素,需要重新采集图像或检查标定板
如果误差过大,优先检查是否存在图像模糊、标定板弯曲或特征点提取错误。可以使用 find_calib_object 的显示模式可视化检测结果。
4.4 案例:抓取场景中的标定实战
假设我们搭建了一个眼在手上(Eye-in-Hand)的3D抓取系统,相机安装在机器人第六轴法兰盘上。标定目标有两个:
- 确定相机内参(畸变校正)。
- 确定相机相对于机器人末端的位姿(手眼标定)。
操作步骤如下:
- 步骤1:固定标定板于工作台,确保标定板在机器人运动范围内始终可见。
- 步骤2:控制机器人运动到15个不同位姿,每个位姿下采集图像并记录机器人末端位姿(从机器人控制器读取)。
- 步骤3:对每张图像执行
find_calib_object,提取标定板角点。 - 步骤4:使用
calibrate_hand_eye算子进行手眼标定,得到相机到末端的变换矩阵。 - 步骤5:验证精度——将标定板放置在已知位置,通过视觉计算其位姿,与机器人实际示教位姿对比。
以下为手眼标定的核心代码片段:
* 假设已收集图像和机器人位姿
* 创建手眼标定模型
create_calib_data ('hand_eye_moving_cam', 'camera', 1, 1, CalibHandle)
* 设置每张图像对应的机器人末端位姿(从机器人控制器读取)
for i := 1 to NumImages by 1
set_calib_data (CalibHandle, 'tool', i-1, 'pose', ToolPose[i-1])
endfor
* 执行标定
calibrate_hand_eye (CalibHandle, Errors)
* 获取相机到末端的外参
get_calib_data (CalibHandle, 'camera', 0, 'pose', CamToToolPose)
4.5 常见误区与复盘
根据大量现场调试经验,以下问题最容易导致标定失败或精度不足:
复盘建议:每次标定完成后,保存标定图像、标定参数和重投影误差日志。当抓取精度出现异常时,首先检查标定参数是否被意外修改,其次重新评估重投影误差是否因温度变化而劣化。
最后,标定不是一次性工作。在抓取系统长期运行中,镜头松动、温度漂移或碰撞都可能导致内参变化。建议建立定期复标定机制,例如每季度或每5000次抓取循环后重新执行标定流程,并将新旧参数进行对比,确保系统始终处于最佳精度状态。