Halcon手眼标定全流程:眼在手外与眼在手上九点标定详解
1. 手眼标定到底在标什么先把坐标系这件事聊透做机器视觉项目绕不开的一个坎就是手眼标定。很多人第一次听到这个词觉得玄乎其实说白了就一件事让相机看到的像素坐标和机械手能走到的物理坐标建立起一个靠谱的换算关系。没有这个关系相机告诉机械手“目标在图像第 320 行、第 240 列”机械手根本不知道往哪儿动。我接触过的项目里标定没做好导致抓偏、贴歪、点胶跑位的案例比算法本身出问题的还多。所以这篇就把 Halcon 手眼标定从“眼在手外”到“眼在手上”的九点标定全流程拆开讲尽量把每个环节的“为什么”说清楚。先明确两个核心概念这是后面所有操作的基础眼在手外Eye-to-Hand相机固定在支架上不动看着工作台。机械手在相机视野里运动。相机坐标系和机械手基坐标系是固定的标定的是相机与机械手基座之间的关系。眼在手上Eye-in-Hand相机装在机械手末端跟着手一起动。相机看到的画面随机械手位姿变化标定的是相机与机械手末端工具坐标系之间的关系。这两个场景的标定思路完全不同。眼在手外标定一次基本就固定了眼在手上每次换工具或者碰撞后都可能需要重新标。九点标定是这两种场景下最常用的入门方法因为它只需要机械手走九个点配合相机识别九个点的像素坐标就能解出变换矩阵。适合谁看这篇如果你正在做上下料、定位抓取、点胶、贴合这类项目手里有 Halcon 和一台能走点位记录的机械手那这篇就是给你写的。不需要你有多深的数学背景但需要你愿意动手把九个点老老实实走完。2. 九点标定为什么是九点原理与方案选型拆解2.1 九点标定的数学本质九点标定本质上是在求解一个二维仿射变换。相机看到的是像素坐标 (u, v)机械手走的是物理坐标 (x, y)两者之间的关系可以写成x a*u b*v c y d*u e*v f这里有 6 个未知数。理论上 3 个不共线的点就能解出来那为什么大家都用九点因为实际现场有镜头畸变、机械手重复定位误差、标定点识别误差点越多最小二乘拟合越稳。九个点组成 3x3 网格覆盖整个工作视野能把视野边缘的畸变也纳入拟合比三个点靠谱得多。Halcon 里对应的算子是vector_to_hom_mat2d输入像素点和物理点两组坐标输出一个 2D 齐次变换矩阵。这个矩阵就是后面所有坐标转换的核心。2.2 标定板标定和九点标定的区别这是热词里问得最多的问题之一。我直接给结论对比项九点标定标定板标定标定对象像素坐标到物理坐标的映射相机内参焦距、畸变和外参需要机械手需要必须走点不需要静态拍多张即可输出结果2D 仿射/透视矩阵相机内参矩阵 畸变系数适用场景平面定位抓取需要去畸变、3D 测量精度影响受机械手精度影响大受标定板精度影响大简单说九点标定解决的是“像素到物理”的映射标定板标定解决的是“相机本身准不准”。如果你的项目是平面抓取镜头畸变不大九点标定足够。如果要做高精度测量或者 3D 应用得先做标定板标定把内参和畸变修正好再做九点标定。2.3 眼在手外和眼在手上的方案差异眼在手外的标定流程相对简单相机固定机械手末端装一个尖点工具比如针尖走九个点相机同时拍到这九个点记录像素坐标和机械手基座坐标直接拟合。标定完成后相机视野内任意像素点都能换算成机械手基座坐标。眼在手上就麻烦一些。相机跟着手走标定时通常有两种做法机械手末端装标定针相机看固定在工作台上的标定板机械手走九个不同位姿每个位姿拍一次标定板记录机械手末端位姿和标定板在相机中的位姿解 AXXB 方程。简化做法固定一个标记点在工作台上机械手带着相机走九个位姿每个位姿让标记点出现在图像不同位置记录机械手末端坐标和标记点像素坐标拟合出相机到末端的变换。第一种精度高但复杂第二种适合快速上手。这篇主要讲第二种简化九点法因为它更容易在现场落地。注意眼在手上的标定结果和工具坐标系强相关。如果你换了夹爪或者工具标定矩阵必须重做否则抓取会系统性偏移。3. 实操前的硬准备环境、工具与参数确认3.1 Halcon 环境与 license 确认Halcon 的安装和 license 配置是第一步。我见过太多人卡在 license 上代码写完了跑不起来。Halcon 的 license 通常绑定网卡 MAC 地址换机器或者换网卡后需要重新申请。安装完成后建议先跑一下 Halcon 自带的示例程序确认HDevelop能正常打开和运行。环境变量方面如果你要用 C 或 Qt 调用 Halcon需要配置HALCONROOT、HALCONARCH等变量并把bin目录加入PATH。Qt 调用 Halcon 的典型做法是在.pro文件里链接halconcpp.lib然后包含HalconCpp.h。这一步配置不对编译会报一堆链接错误。3.2 标定工具与机械手配合九点标定需要一个能在图像中稳定识别的标记。常见选择尖点工具机械手末端装针尖相机从上方拍识别针尖位置。优点是直接对应工具中心点TCP缺点是针尖在图像中可能不够清晰。圆形标记在工作台或末端装一个高对比度圆点用find_circle或find_shape_model识别圆心。稳定性好推荐。棋盘格角点精度高但需要机械手走点时角点正好在视野内操作稍麻烦。机械手方面你需要能手动示教九个点并记录每个点的基座坐标眼在手外或末端坐标眼在手上。建议用机械手的示教器走点同时用 Halcon 的采集助手实时抓图确保每个点都能被稳定识别。3.3 标定前的参数确认清单动手之前把这几个参数确认清楚能省掉后面大量返工相机分辨率与视野范围确保九个点都在视野内且边缘点不要贴边。镜头畸变情况如果畸变明显先做标定板标定去畸变再九点标定。机械手重复定位精度一般要求优于标定精度的 1/3。比如你要 0.1mm 精度机械手重复定位得在 0.03mm 以内。工作平面高度九点标定是 2D 的所有标定点必须在同一高度平面。如果高度变化需要做 3D 标定或者分层标定。光照稳定性标定时的光照要和实际运行时一致否则标记识别会漂。4. 眼在手外九点标定全流程实操4.1 九个点的走位策略九个点怎么走直接影响标定质量。我的习惯是走一个 3x3 网格覆盖相机视野的 70% 到 80% 区域不要贴边。具体做法在视野中心走第一个点记录机械手基座坐标 (x0, y0)同时用 Halcon 抓图识别标记像素坐标 (u0, v0)。沿 X 方向等间距走三个点间距根据视野宽度定比如视野 200mm间距取 50mm。沿 Y 方向同样走三行形成 3x3 网格。走点时注意机械手每次移动后要等稳定再抓图避免振动导致图像模糊。抓图后立即保存图像和对应坐标不要等九个点走完再一起处理容易乱。4.2 Halcon 识别标记并提取像素坐标假设我们用圆形标记Halcon 代码大致如下* 读取图像 read_image (Image, calib_point_1.png) * 转灰度 rgb1_to_gray (Image, GrayImage) * 阈值分割 threshold (GrayImage, Regions, 100, 255) * 连通域 connection (Regions, ConnectedRegions) * 筛选圆形区域 select_shape (ConnectedRegions, SelectedRegions, circularity, and, 0.8, 1.0) * 拟合圆 fit_circle_contour_xld (SelectedRegions, algebraic, -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)这里Row和Column就是标记中心的像素坐标。实际项目中我建议用find_shape_model做模板匹配稳定性比阈值分割好尤其是光照有波动的时候。4.3 坐标数据整理与矩阵拟合九个点走完你会得到两组数据像素坐标(u1, v1)到(u9, v9)机械手基座坐标(x1, y1)到(x9, y9)在 Halcon 里拟合* 像素坐标数组 Px : [u1, u2, u3, u4, u5, u6, u7, u8, u9] Py : [v1, v2, v3, v4, v5, v6, v7, v8, v9] * 机械手坐标数组 Qx : [x1, x2, x3, x4, x5, x6, x7, x8, x9] Qy : [y1, y2, y3, y4, y5, y6, y7, y8, y9] * 拟合变换矩阵 vector_to_hom_mat2d (Px, Py, Qx, Qy, HomMat2D)得到的HomMat2D就是标定矩阵。后面用affine_trans_point_2d就能把任意像素坐标转成机械手坐标affine_trans_point_2d (HomMat2D, u, v, x, y)4.4 标定精度验证方法标定完不能直接上生产必须验证。我的做法是在视野内随机选 5 个不在标定点上的位置。用相机识别这些位置的标记通过标定矩阵算出机械手坐标。让机械手实际走到这些坐标用针尖比对偏差。记录每个点的偏差计算平均误差和最大误差。一般平面抓取项目平均误差控制在 0.1mm 以内算合格。如果超过 0.2mm需要排查是机械手精度问题还是标定点识别问题。实操心得验证时一定要用标定点之外的点用标定点验证等于自己骗自己。我见过有人用九个标定点回代误差 0.01mm结果实际抓取偏了 0.5mm就是因为标定点拟合过度。5. 眼在手上九点标定全流程实操5.1 眼在手上标定的核心差异眼在手上相机装在机械手末端标定的是相机坐标系到机械手末端工具坐标系的变换。简化九点法的思路是在工作台上固定一个标记点机械手带着相机走九个位姿每个位姿让标记点出现在图像的不同位置记录机械手末端坐标和标记点像素坐标拟合出变换关系。这里有个关键点机械手末端坐标是工具坐标系不是基座坐标系。如果你记录的是基座坐标需要先通过工具坐标系转换到末端。Halcon 里可以用hom_mat3d_compose组合变换。5.2 九个位姿的设计原则眼在手上的九个位姿设计比眼在手外讲究。因为相机跟着手动标记点在图像中的位置会随位姿变化。我的建议九个位姿覆盖机械手工作空间的一个平面区域Z 高度保持一致。每个位姿下标记点都要在相机视野内且尽量分布在图像不同区域。位姿变化时尽量让相机光轴保持垂直向下避免大角度倾斜导致标记变形。具体走位可以是在 XY 平面上走 3x3 网格每个点机械手末端旋转角度保持一致比如都保持 0 度这样标定出来的是纯平移关系。如果需要考虑旋转可以增加位姿变化但九点法一般只解平移和缩放。5.3 Halcon 实现代码与数据记录眼在手上的 Halcon 代码和眼在手外类似区别在于记录的机械手坐标是末端坐标* 假设已获取九个位姿的像素坐标和末端坐标 Px : [u1, u2, u3, u4, u5, u6, u7, u8, u9] Py : [v1, v2, v3, v4, v5, v6, v7, v8, v9] * 末端坐标工具坐标系 Qx : [tx1, tx2, tx3, tx4, tx5, tx6, tx7, tx8, tx9] Qy : [ty1, ty2, ty3, ty4, ty5, ty6, ty7, ty8, ty9] * 拟合 vector_to_hom_mat2d (Px, Py, Qx, Qy, HomMat2D)得到的矩阵表示像素坐标 - 末端坐标。实际抓取时相机看到目标像素坐标通过矩阵算出末端需要移动到的坐标再结合当前末端位姿计算出机械手应该走的基座坐标。5.4 眼在手上标定的验证与补偿眼在手上的验证比眼在手外麻烦因为相机在动。我的做法是标定完成后让机械手走到一个任意位姿相机拍标记点通过矩阵算出末端坐标。对比机械手实际末端坐标计算偏差。如果偏差大检查标定点识别是否稳定或者机械手末端坐标记录是否准确。眼在手上还有一个常见问题相机安装角度偏差。如果相机光轴和工具轴线不平行标定矩阵会包含一个旋转分量导致不同位姿下抓取偏移不一致。解决办法是在标定前用机械手走一个纯旋转观察标记点在图像中的移动轨迹如果轨迹是圆弧而不是点说明有角度偏差需要先机械调整相机安装。注意眼在手上标定后如果机械手碰撞或者相机松动标定矩阵会失效。建议每次开机或者换班时用标记点快速验证一次偏差超过阈值就重新标定。6. 常见问题与排查技巧实录6.1 标定误差大的排查思路标定误差大是最常见的问题。我整理了一个排查表现象可能原因排查方法整体偏移标定点识别中心不准检查标记识别算法用模板匹配替代阈值边缘误差大镜头畸变未校正先做标定板标定去畸变随机误差大机械手重复定位差同一点走多次看坐标波动局部误差大标定点分布不均重新设计九点分布覆盖全视野旋转后误差大相机安装角度偏差检查相机光轴与工具轴线平行度6.2 标记识别不稳定的处理标记识别不稳定标定矩阵就会漂。常见原因和解决办法光照变化固定光源标定和运行时保持一致。如果现场光照不可控用find_shape_model做模板匹配比阈值分割抗干扰。标记对比度低换高对比度标记比如黑白圆点。或者用背光照明。标记部分遮挡确保九个点走位时标记完整出现在视野内不要被工具或夹具挡住。图像模糊机械手移动后等稳定再抓图或者用短曝光加光源。6.3 机械手坐标记录错误的避免机械手坐标记录错误是隐蔽性最强的问题。我踩过的坑记录的是基座坐标但标定需要末端坐标导致矩阵完全错误。九个点的坐标记录顺序和图像顺序不一致拟合出来乱七八糟。机械手走点时用了不同的工具坐标系导致坐标基准不统一。避免方法走点时用表格记录每走一个点立即填写像素坐标和机械手坐标并标注序号。走完九个点后先检查坐标数据是否有明显异常值再拟合。6.4 Halcon 版本与算子兼容问题Halcon 不同版本的算子可能有差异。比如vector_to_hom_mat2d在旧版本和新版本中参数基本一致但find_shape_model的参数在不同版本中有调整。如果你从网上抄代码注意版本匹配。另外Halcon 的 license 如果过期程序会在运行时突然报错建议在项目里加 license 检查逻辑。7. 标定结果的工程化落地与维护7.1 标定矩阵的保存与加载标定矩阵不能每次开机重新算必须保存下来。Halcon 里可以用write_tuple保存矩阵write_tuple (HomMat2D, calib_matrix.tup)加载时read_tuple (calib_matrix.tup, HomMat2D)如果项目用 C 或 Qt 调用 Halcon可以把矩阵保存到配置文件或者数据库程序启动时加载。建议同时保存标定日期、标定点数据、误差统计方便追溯。7.2 标定失效的快速检测生产线上标定失效如果不能及时发现会导致批量不良。我的做法是在工作台固定一个验证标记每次开机或者换班时让相机拍这个标记通过标定矩阵算出机械手坐标和实际走到的坐标比对。偏差超过阈值就报警提示重新标定。这个验证标记的位置要固定且不在标定点上这样能真实反映标定状态。7.3 多相机多工位的标定管理如果项目有多个相机或者多个工位每个相机和工位都需要独立标定。建议建立标定档案记录每个相机的标定矩阵、标定时间、标定人、误差数据。换相机或者换工位时直接调用对应的标定文件避免混淆。7.4 标定精度的长期稳定性标定精度会随时间和环境变化。机械手磨损、相机松动、温度变化都会影响。建议定期复检比如每周一次。复检方法和验证一样用固定标记比对。如果偏差趋势性增大说明硬件有问题需要检修。我个人在实际操作中的体会是九点标定看起来简单但真正做好需要耐心。九个点走位、识别、记录、拟合、验证每一步都不能马虎。尤其是验证环节很多人省掉结果上线后问题一堆。另外标定矩阵不是一劳永逸的现场环境变化后一定要复检。最后分享一个小技巧标定时用手机拍下九个点的走位和标记识别画面后面排查问题时能快速定位是哪个点出了问题。