尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Halcon集成YOLO目标检测:工业视觉实战路线与避坑指南

Halcon集成YOLO目标检测:工业视觉实战路线与避坑指南 在工业视觉圈子里Halcon 和 YOLO 的关系一直有点微妙。前者是商业机器视觉的老牌劲旅算子稳定、标定精准、亚像素测量是看家本领后者是深度学习目标检测的当红方案迭代快、生态活跃、社区资源丰富。很多做产线检测的朋友都遇到过同一个问题Halcon 自带的深度学习模块能跑目标检测但训练效率和数据标注体验跟 YOLO 生态比差了一截而 YOLO 推理快、精度高可一旦要跟工业相机、PLC、运动控制卡对接又得自己写一堆胶水代码。于是Halcon 里怎么用 YOLO 做目标检测就成了一个高频问题。这篇内容就把我实际项目里跑通的几条路线拆开讲清楚包括数据怎么准备、模型怎么选、Halcon 侧怎么调用、精度怎么对齐以及那些文档里不会写的坑。1. 先搞清楚 Halcon 和 YOLO 各自在目标检测里扮演什么角色1.1 Halcon 的深度学习目标检测能力边界Halcon 从 18.11 版本开始正式引入深度学习模块到 20.11 之后目标检测相关的算子已经比较完整。它的核心思路是基于预训练的 backbone 做迁移学习支持分类、目标检测、语义分割、异常检测几大类任务。目标检测这块Halcon 提供的是类似 SSD 和 YOLO 风格的 anchor-based 检测头训练和推理都在 Halcon 自己的运行时里完成。它的优势很明显跟 Halcon 的标定、测量、形态学算子无缝衔接检测框出来之后可以直接接measure_pos、fit_circle这类算子做尺寸测量整条链路不需要跨语言。但短板也突出——标注工具只能用 Halcon 自带的deep_learning_tool或者 MVTec 的标注软件数据增强策略相对固定训练超参可调空间小遇到复杂场景比如密集小目标、严重遮挡时调优手段有限。1.2 YOLO 系列在工业场景的真实表现YOLO 从 v5 开始进入工程化爆发期到 v8、v11 以及现在社区讨论的 v26 方向核心演进逻辑一直是精度和速度的帕累托前沿。工业场景里用得最多的是 YOLOv5、YOLOv8 和 YOLOv11原因不是它们最新而是生态最成熟标注工具LabelImg、Labelme、X-AnyLabeling、数据增强Albumentations、训练框架Ultralytics、部署工具链ONNX、TensorRT、OpenVINO全都齐备。在产线检测里YOLO 的典型优势是小目标检测经过多尺度特征融合后召回率明显高于传统方法训练时可以通过 mosaic、mixup 等增强策略显著提升泛化推理侧 INT8 量化后单帧能压到几毫秒。但它的坐标输出是像素级的要做亚像素测量还得回到 Halcon 或者 OpenCV 做二次处理。1.3 两者结合的三条现实路线把 Halcon 和 YOLO 捏到一起实际项目里我走过三条路各有适用场景路线核心思路适用场景维护成本路线AYOLO训练 Halcon推理用 YOLO 生态训练导出 ONNXHalcon 用read_dl_model加载已有 Halcon 授权不想引入 Python 运行时中路线BYOLO训练 YOLO推理 Halcon后处理YOLO 独立部署检测结果通过文件/网络传给 Halcon产线已有 YOLO 服务Halcon 只做测量低路线CHalcon训练 Halcon推理全程用 Halcon 深度学习模块数据敏感、不允许外部框架、样本量小低但精度受限路线 A 是问得最多的也是坑最集中的。下面重点拆这条。2. 用 YOLO 训练出能喂给 Halcon 的模型2.1 数据集准备从标注到格式转换YOLO 训练需要的数据格式是每张图对应一个 txt每行class_id x_center y_center width height全部归一化到 0-1。工业场景里标注工具我推荐 X-AnyLabeling它支持 SAM 辅助标注对缺陷、零件这类边界模糊的目标效率比纯手工高很多。标注完导出 YOLO 格式后目录结构应该是这样dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml内容path: ./dataset train: images/train val: images/val nc: 3 names: [scratch, dent, stain]这里有个容易忽略的点工业图像的类别不平衡往往很严重。比如划痕样本可能只有几十张而正常样本几千张。直接训练会导致模型对少数类召回极低。我的做法是在data.yaml里不处理而是在训练时用copy_paste增强配合类别权重或者干脆对少数类做离线过采样。2.2 模型选型v5、v8 还是更新的版本工业项目里我不建议盲目追新。YOLOv5 的优点是代码结构清晰、ONNX 导出稳定、社区 issue 多YOLOv8 的优点是 anchor-free 头、训练更稳、Ultralytics 维护活跃YOLOv11 在精度上又有提升但导出到 ONNX 后某些算子对 Halcon 的兼容性需要验证。我的经验是如果最终要在 Halcon 里推理优先选 YOLOv5 或 YOLOv8因为它们的输出层结构简单Halcon 的read_dl_model对这类标准卷积检测头的支持最成熟。YOLOv11 及更新版本如果用了动态头或者特殊激活函数Halcon 加载时可能报算子不支持。模型尺寸选择上工业场景通常s或m就够了。n虽然快但小目标召回经常不够l和x在产线节拍要求下往往推理时间超标。我一般先用yolov8s跑 baseline看 mAP 和单帧耗时再决定要不要升到m。2.3 训练参数里最影响 Halcon 侧效果的几个训练时大部分参数跟常规 YOLO 项目一样但有几个直接影响后续 Halcon 推理效果输入尺寸YOLO 默认 640但 Halcon 加载模型时会按模型元数据里的输入尺寸走。如果产线图像分辨率很高比如 5000x4000直接 resize 到 640 会丢小目标。我的做法是训练时用imgsz1024或1280导出 ONNX 时保持这个尺寸Halcon 侧也按这个尺寸预处理。NMS 参数YOLO 训练时的 NMS 是内置的但导出 ONNX 时可以选择是否包含 NMS。如果 Halcon 侧要做自己的 NMS导出时就去掉如果想让 Halcon 直接用就保留。我倾向于去掉因为 Halcon 的nms相关算子可以更灵活地调 IoU 阈值。置信度阈值训练时不用设但导出后要在 Halcon 侧设。这个值直接决定漏检和误检的平衡后面会细说。训练命令示例yolo detect train modelyolov8s.pt datadata.yaml epochs200 imgsz1024 batch8 device0训练完成后验证集上的 mAP0.5 至少要到 0.85 以上再考虑部署工业场景对漏检容忍度极低。2.4 导出 ONNX 时的关键设置导出这一步是路线 A 成败的关键。Ultralytics 的导出命令yolo export modelbest.pt formatonnx imgsz1024 opset12 simplifyTrue几个要点opset建议 11 或 12太高了 Halcon 可能不支持太低了某些算子表达不了。simplifyTrue会做图优化去掉冗余节点对 Halcon 加载友好。如果模型里有SiLU激活Halcon 较新版本支持老版本可能报错需要替换成ReLU重新训练或导出。导出后一定要用onnxruntime跑一遍确认输出 shape 和数值正常再拿去 Halcon 加载。3. Halcon 侧加载 YOLO 模型并做推理3.1 Halcon 深度学习模型的加载流程Halcon 加载 ONNX 模型用read_dl_model但并不是所有 ONNX 都能直接读。Halcon 对 ONNX 的支持有自己的算子白名单遇到不支持的层会直接报错。加载流程大致是read_dl_model (best.onnx, DLModelHandle) get_dl_model_param (DLModelHandle, input_dimensions, InputDimensions)如果报错先用get_dl_model_param查支持的参数列表或者用 Halcon 自带的dl_model_inference示例验证。常见的不支持算子包括自定义的Focus层、某些版本的Concat轴设置、动态 reshape 等。一个实用的排查方法用 Netron 打开 ONNX看最后几层。如果输出是[1, 25200, 85]这种 YOLOv5 风格的Halcon 处理起来比较直接如果是[1, 84, 8400]这种 YOLOv8 风格的需要做转置和解析。3.2 预处理让 Halcon 的输入和 YOLO 训练时一致YOLO 训练时的预处理是letterbox resize保持长宽比灰边填充、归一化到 0-1、RGB 通道顺序。Halcon 侧必须完全复现这套流程否则精度会掉。Halcon 里做 letterbox 的步骤* 读取图像 read_image (Image, test.png) get_image_size (Image, Width, Height) * 计算缩放比例 Scale : min(1024.0 / Width, 1024.0 / Height) NewWidth : round(Width * Scale) NewHeight : round(Height * Scale) * 缩放 zoom_image_size (Image, ImageZoomed, NewWidth, NewHeight, bilinear) * 创建灰边画布并粘贴 gen_image_const (ImageCanvas, byte, 1024, 1024) paint_region (ImageCanvas, ImageCanvas, ImageCanvas, 128, fill) * 这里需要计算粘贴位置略去具体坐标计算归一化和通道转换用convert_image_type和trans_from_rgb配合。注意 Halcon 默认图像是 BGR 还是 RGB 取决于相机YOLO 训练用的是 RGB所以如果相机出的是 BGR必须转。3.3 推理与输出解析Halcon 推理用apply_dl_modelapply_dl_model (DLModelHandle, ImagePreprocessed, [], DLResult)输出是一个 tuple具体结构取决于模型。对于 YOLOv8 导出的 ONNX输出通常是[1, 84, 8400]84 4 个框坐标 80 个类别分数COCO或者 4 nc自定义。Halcon 拿到的结果需要自己解析前 4 行是cx, cy, w, h需要转换成row1, col1, row2, col2。后面是类别分数取最大值对应的类别。然后做置信度过滤和 NMS。Halcon 有nms相关算子但更灵活的做法是自己写循环做 IoU 计算因为工业场景经常需要按类别设不同阈值。3.4 后处理从检测框到测量结果检测框出来之后才是 Halcon 真正发挥价值的地方。比如检测到一个零件接下来要做圆度测量* 假设检测框是 Row1, Col1, Row2, Col2 gen_rectangle1 (ROI, Row1, Col1, Row2, Col2) reduce_domain (Image, ROI, ImageROI) * 边缘提取 edges_sub_pix (ImageROI, Edges, canny, 1, 20, 40) * 圆拟合 fit_circle_contour_xld (Edges, algebraic, -1, 0, 0, 3, 2, Row, Col, Radius, ...)这条链路是 Halcon 的强项也是为什么很多项目宁愿绕一圈也要把 YOLO 塞进 Halcon 的原因。4. 精度对齐与性能调优的实战细节4.1 为什么 Halcon 推理结果和 YOLO 原版对不上这是路线 A 最常见的坑。同一张图YOLO 原版推理和 Halcon 推理结果差几个像素甚至漏检原因通常有这几个预处理不一致letterbox 的填充值、插值方式、归一化系数任何一个不同都会导致偏移。YOLO 默认填充 114/255归一化是除以 255Halcon 侧必须一致。通道顺序BGR vs RGB这个错了精度会崩。输出解析YOLOv8 的输出需要转置如果直接按 YOLOv5 的方式解析框全错。NMS 阈值YOLO 默认 IoU 0.45Halcon 侧如果设 0.5重叠目标会被多检。我的做法是先用一张图在 Python 里跑 YOLO 拿到框坐标再在 Halcon 里跑逐像素对比。差超过 2 个像素就说明预处理有问题。4.2 置信度阈值和 NMS 阈值的调法工业场景调这两个值有明确的方法论置信度阈值先设 0.25 跑一批测试图统计漏检和误检。如果漏检多降到 0.15如果误检多升到 0.4。不要一次调太多每次 0.05 步进。NMS IoU 阈值密集目标比如一堆小零件用 0.3-0.4稀疏目标用 0.5-0.6。如果发现同一个目标出两个框降 IoU如果相邻目标被合并升 IoU。这两个值没有万能解必须按产线实际图像调。我一般会留一个配置文件不同产品切换时加载不同阈值。4.3 推理速度优化从 200ms 压到 30msHalcon 侧推理速度受几个因素影响输入尺寸1024 比 640 慢一倍以上。如果小目标不多降到 640 能省很多时间。批处理Halcon 支持 batch 推理但产线通常单帧流batch 意义不大。CPU/GPUHalcon 深度学习可以用 GPU但需要 CUDA 版本匹配。如果产线工控机没独显CPU 推理 1024 尺寸可能要 200ms 以上这时候要么降尺寸要么换轻量模型。模型量化Halcon 支持 INT8 量化但需要校准集。量化后速度能提升 2-3 倍精度掉 1-2 个点。对节拍要求高的场景值得做。实测数据i7-12700 RTX 3060模型输入尺寸设备单帧耗时yolov8s640GPU8msyolov8s1024GPU18msyolov8s1024CPU210msyolov8m1024GPU35ms4.4 模型更新时的版本管理产线模型不是训一次就完事。每次新增缺陷样本、调整阈值、换产品型号都可能要重新训练。我的做法是模型文件按产品_日期_版本命名比如scratch_20240601_v3.onnx。Halcon 程序里模型路径做成配置项不硬编码。每次更新模型先用历史测试集跑一遍回归确认旧类别不掉点。保留最近三个版本的模型文件出问题能快速回滚。5. 那些文档里不会写的坑5.1 Halcon 版本对 ONNX 算子支持的差异Halcon 20.11 和 23.11 对 ONNX 的支持差别很大。20.11 对SiLU、Hardswish这些激活函数支持不完整加载 YOLOv8 模型经常报错。23.11 之后支持好很多但仍有部分算子限制。如果项目允许尽量用 23.11 或更新版本。如果只能用老版本训练时就把激活函数换成ReLU或者导出时做算子替换。5.2 图像通道和位深的隐形陷阱工业相机出的图可能是 8 位灰度、16 位灰度、24 位彩色。YOLO 训练用的是 8 位 RGB。如果 Halcon 侧直接拿 16 位图去推理数值范围不对结果全乱。必须先用convert_image_type转成 byte再转 RGB。灰度图要复制成三通道否则 Halcon 可能报维度不匹配。5.3 多类别时的类别索引对齐YOLO 训练时names列表的顺序就是类别索引。Halcon 侧解析输出时类别索引必须跟训练时一致。我见过有人训练时names: [ok, ng]Halcon 侧按[ng, ok]解析结果所有 OK 品被判成 NG。这种错误排查起来很费时间建议在配置文件里把类别映射写死两边共用。5.4 内存泄漏与长时间运行稳定性Halcon 的apply_dl_model在循环里调用时如果不释放中间结果内存会持续增长。产线 24 小时运行几小时后就可能 OOM。解决办法是每次循环结束clear_obj清理图像对象模型句柄只在程序启动时加载一次不要反复read_dl_model。5.5 模型文件路径中的中文和空格Halcon 对路径中的中文和空格支持不好read_dl_model遇到中文路径可能直接失败。模型文件放在纯英文、无空格的路径下比如D:/models/scratch_v3.onnx。这个坑很隐蔽因为报错信息不会提示路径问题。6. 什么情况下该放弃 Halcon 内推理改用混合架构路线 A 虽然能把 YOLO 塞进 Halcon但维护成本不低。如果项目满足以下条件我会建议改用路线 B产线已经有独立的推理服务比如用 TensorRT 部署的 YOLOHalcon 只做测量。模型更新频繁每次都要重新导出 ONNX 再验证 Halcon 兼容性太耗时。团队里没人熟悉 Halcon 深度学习模块的调试。路线 B 的架构是YOLO 服务通过 TCP 或共享内存把检测框传给 Halcon 程序Halcon 只负责图像采集、测量、结果输出。这样两边解耦YOLO 侧可以用最新的部署工具链Halcon 侧专注它擅长的测量。通信协议用简单的 JSON 或者自定义二进制都行延迟通常在 1-2ms对产线节拍影响可以忽略。我自己在最近一个 3C 零件检测项目里用的就是路线 B。YOLO 用 TensorRT INT8 部署单帧 6msHalcon 收到框之后做圆度和平面度测量整个节拍控制在 50ms 以内。模型迭代时只动 YOLO 侧Halcon 程序完全不用改维护效率比路线 A 高很多。如果非要在 Halcon 里跑 YOLO那就把预处理和后处理的代码封装成独立函数模型路径、阈值、类别映射全部配置化。这样至少换模型的时候不用改主逻辑。另外Halcon 的深度学习调试工具比较弱遇到精度问题很难定位建议在 Python 侧先把模型调好确认无误再移植到 Halcon不要两边同时调。
返回列表