
简介这份资源面向具备一定C#基础、希望将深度学习落地到机器视觉场景的开发者围绕Halcon 21.11与VS2019联合开发完整演示物体识别与图像分割的标注、训练、验证全流程。压缩包共57个文件约5.39MB以cs源码、resx与resources资源、hobj模型对象、dll动态库、config配置及exe可执行文件为主另含hdev脚本与sln解决方案覆盖界面控件、几何绘制、键盘模拟等辅助模块目录按UI、Method、Properties等分层组织便于按模块阅读与二次开发。已有515人学习下载。读者可据此理解Halcon深度学习接口在C#中的调用方式掌握从数据标注、模型训练到验证评估的完整链路并参考现成的视图控件与工具类快速搭建自己的识别与分割应用适合作为项目原型或学习范例。1. Halcon 深度学习落地从标注到验证C# 上位机怎么把活干完产线上来了一批新工件表面有六种缺陷客户要求三天内出一个能跑在工控机上的识别程序。你打开 Visual Studio引用 halcondotnet.dll准备用 C# 写上位机界面但模型训练那一步卡住了——Halcon 的深度学习不是纯 C# 能闭环的标注、训练、评估这三块得在 HDevelop 里先跑通再把模型导出给 C# 调用。这个流程我走过不止一遍翻车最多的地方不是代码写错而是标注格式和数据集划分没对齐导致训练 loss 正常但验证精度死活上不去。这篇要讲的就是这条链路用 Halcon 的标注工具做物体识别和图像分割的数据准备在 HDevelop 里配置训练参数并跑通导出模型后在 C# 上位机里加载推理最后用一套可复现的验证方法确认模型能不能上线。适合两类人一是做视觉上位机的 C# 工程师需要把 Halcon 深度学习嵌进现有框架二是刚接触 Halcon 深度学习的视觉工程师想搞清楚从标注到部署每一步的实际参数和边界。下面按标注、训练、C# 集成、验证、避坑的顺序展开每一步都给可抄的命令和参数。2. 标注与数据集Halcon 深度学习的第一道门槛2.1 物体识别和图像分割的标注差异Halcon 深度学习支持三类任务分类、物体检测Detection、语义分割Segmentation。物体识别通常对应 Detection标注的是矩形框加类别标签图像分割对应 Segmentation标注的是每个像素的类别输出是分割掩膜。两者的标注文件结构完全不同Detection 用 .hobj 或 COCO 格式的 JSONSegmentation 用像素级标注图加类别映射表。我一般先用 HDevelop 的deep_learning_annotation工具做标注。Detection 标注时每个目标画一个矩形类别名要和后续训练配置里的 class_names 完全一致大小写都不能差。Segmentation 标注更费时间但 Halcon 提供了半自动工具先用传统算子做粗分割再手动修边缘。比如用threshold加connection先分出大致区域导出成标注初稿再在标注工具里微调。标注完成后目录结构建议这样组织dataset/ train/ images/ img_001.png img_002.png annotations/ img_001.json img_002.json val/ images/ annotations/ test/ images/ annotations/train/val/test 的比例按 7:2:1 切如果样本少于 500 张至少保证 val 有 50 张以上否则验证精度波动会很大。2.2 用 HDevelop 脚本批量检查标注质量标注完不要直接开训先跑一遍检查脚本。下面这段 HDevelop 代码遍历标注文件检查每个 JSON 里的类别名是否在预定义列表里以及框的宽高是否小于 5 像素太小的框训练时会被忽略* 检查标注文件中的类别名和框尺寸 ClassNames : [scratch, dent, stain, crack, burr, normal] MinWidth : 5 MinHeight : 5 AnnotationDir : dataset/train/annotations list_files(AnnotationDir, [files], Files) for Index : 0 to |Files| - 1 by 1 read_dict(Files[Index], [], [], DictHandle) get_dict_tuple(DictHandle, categories, Categories) for CIndex : 0 to |Categories| - 1 by 1 if (sum(ClassNames Categories[CIndex]) 0) disp_message(3600, 未知类别: Categories[CIndex] 文件: Files[Index], window, 12, 12, red, true) endif endfor get_dict_tuple(DictHandle, bbox, BBoxes) for BIndex : 0 to |BBoxes| - 1 by 1 W : BBoxes[BIndex][2] - BBoxes[BIndex][0] H : BBoxes[BIndex][3] - BBoxes[BIndex][1] if (W MinWidth or H MinHeight) disp_message(3600, 框过小: Files[Index], window, 12, 12, yellow, true) endif endfor clear_dict(DictHandle) endfor逻辑说明read_dict读取 Halcon 的字典格式标注文件get_dict_tuple取出类别列表和边界框坐标。sum(ClassNames Categories[CIndex])利用 Halcon 的元组比较做类别名匹配返回 0 表示不在列表里。框宽高检查是为了过滤掉标注时误画的极小框这类框在训练时会被 Halcon 自动忽略但会在日志里刷警告提前清掉省得干扰排查。参数说明MinWidth和MinHeight设 5 像素是经验值如果你的图像分辨率低于 640×480可以降到 3高于 2000×2000 可以提到 10。ClassNames必须和训练配置里的完全一致包括顺序Halcon 按索引映射类别 ID。2.3 数据增强参数的取舍Halcon 深度学习训练时自带增强但增强参数不能乱开。Detection 任务常用的增强有旋转、缩放、亮度变化、镜像。镜像要注意如果缺陷有方向性比如划痕方向左右镜像会引入错误标签这时候要关掉 mirror。Segmentation 任务对几何变换更敏感旋转角度超过 15 度时边缘像素的类别可能失真我一般把旋转限制在 ±10 度。在 HDevelop 的训练配置里增强参数通过set_dl_model_param设置* 设置数据增强参数 set_dl_model_param(DLModelHandle, augmentation_rotate, 10) set_dl_model_param(DLModelHandle, augmentation_scale_min, 0.9) set_dl_model_param(DLModelHandle, augmentation_scale_max, 1.1) set_dl_model_param(DLModelHandle, augmentation_brightness, 0.1) set_dl_model_param(DLModelHandle, augmentation_mirror, false)逻辑说明augmentation_rotate控制随机旋转角度范围单位是度。augmentation_scale_min/max控制缩放比例0.9 到 1.1 表示缩小 10% 到放大 10%。augmentation_brightness是亮度偏移比例0.1 表示 ±10%。augmentation_mirror设 false 关闭镜像有方向性缺陷时必须关。参数说明旋转角度超过 15 度时Detection 的框可能超出图像边界被裁掉导致训练样本丢失。缩放范围超过 0.8 到 1.2 时小目标可能缩到 5 像素以下被忽略。亮度变化超过 0.2 时暗缺陷可能被增强成过曝区域反而干扰训练。3. 训练配置与 HDevelop 实操把模型跑起来3.1 创建模型和加载预训练权重Halcon 深度学习支持从头训练和迁移学习。样本少于 1000 张时强烈建议用预训练模型做迁移。Halcon 自带几个预训练网络Detection 常用pretrained_dl_classifier_compact.hdl和pretrained_dl_classifier_enhanced.hdl前者速度快适合工控机后者精度高但推理慢。创建 Detection 模型的代码* 创建物体检测模型 read_dl_model(pretrained_dl_classifier_compact.hdl, DLModelHandle) set_dl_model_param(DLModelHandle, type, detection) set_dl_model_param(DLModelHandle, class_names, [scratch, dent, stain, crack, burr, normal]) set_dl_model_param(DLModelHandle, image_width, 640) set_dl_model_param(DLModelHandle, image_height, 480) set_dl_model_param(DLModelHandle, image_num_channels, 3)逻辑说明read_dl_model加载预训练模型文件这个文件在 Halcon 安装目录的dl文件夹下。set_dl_model_param设置模型类型为 detection类别名列表以及输入图像尺寸。图像尺寸要和标注时的图像尺寸一致否则训练时会自动缩放小目标可能缩没了。参数说明image_width和image_height设 640×480 是平衡速度和精度的常用值。如果缺陷目标小于 20×20 像素建议提到 1024×768。image_num_channels设 3 表示 RGB 三通道如果输入是灰度图设 1 可以省显存。3.2 训练参数设置和迭代控制训练参数里最关键的是学习率、batch size 和迭代次数。Halcon 的 Detection 训练用train_dl_model_batch逐批训练学习率通过set_dl_model_param设置* 设置训练超参数 set_dl_model_param(DLModelHandle, learning_rate, 0.001) set_dl_model_param(DLModelHandle, momentum, 0.9) set_dl_model_param(DLModelHandle, weight_decay, 0.0005) set_dl_model_param(DLModelHandle, batch_size, 4) set_dl_model_param(DLModelHandle, max_epochs, 100) set_dl_model_param(DLModelHandle, lr_step, 30) set_dl_model_param(DLModelHandle, lr_factor, 0.1)逻辑说明learning_rate初始学习率0.001 是迁移学习的常用起点。momentum动量项0.9 是标准值。weight_decay权重衰减防过拟合0.0005 适合小数据集。batch_size批大小4 是 8GB 显存下的安全值。max_epochs最大迭代轮数。lr_step和lr_factor控制学习率衰减每 30 轮学习率乘以 0.1。参数说明学习率超过 0.01 时迁移学习容易把预训练权重冲垮loss 会震荡不降。batch size 设太大比如 16在 8GB 显存上会 OOM设太小比如 1梯度噪声大收敛慢。max_epochs设 100 是起点如果验证精度在第 60 轮还在涨可以加到 150如果第 30 轮就平了减到 60 省时间。3.3 训练过程监控和中断恢复训练时用train_dl_model_batch循环每轮结束后在验证集上跑evaluate_dl_model看精度。下面这段代码展示训练循环和精度记录* 训练循环每轮记录验证精度 for Epoch : 1 to MaxEpochs by 1 train_dl_model_batch(DLModelHandle, TrainDataloader, TrainResults) evaluate_dl_model(DLModelHandle, ValDataloader, ValResults) get_dl_model_param(DLModelHandle, learning_rate, CurrentLR) Precision : ValResults[precision] Recall : ValResults[recall] disp_message(3600, Epoch Epoch LR CurrentLR P Precision R Recall, window, 12, 12, black, true) if (Precision 0.95 and Recall 0.90) break endif endfor逻辑说明train_dl_model_batch跑一轮训练evaluate_dl_model在验证集上算精度和召回。get_dl_model_param取当前学习率确认衰减是否生效。精度和召回同时达标就提前停省时间。参数说明精度阈值 0.95 和召回 0.90 是工业检测的常见要求具体看客户标准。如果召回优先漏检代价高把召回阈值提到 0.95精度可以降到 0.90。训练中断后恢复Halcon 支持write_dl_model保存中间模型下次用read_dl_model加载后继续训练但优化器状态不保存恢复后前几轮 loss 会跳一下正常现象。4. C# 联合 Halcon模型部署到上位机4.1 C# 项目引用 Halcon 库和环境配置C# 调用 Halcon 深度学习模型需要引用halcondotnet.dll这个文件在 Halcon 安装目录的bin/dotnet35或bin/dotnetcore下。新建 C# WinForms 或 WPF 项目后在解决方案里添加引用然后把 Halcon 的运行时目录加到系统 PATH 或项目输出目录。环境变量配置# 把 Halcon 的 bin 目录加到 PATH setx PATH %PATH%;C:\Program Files\MVTec\HALCON-23.11\bin\x64-win64逻辑说明Halcon 的运行时依赖halcon.dll和hdevengine.dll等原生库C# 通过 P/Invoke 调用。PATH 里没有这些库的目录时运行时会报DllNotFoundException。参数说明Halcon 版本号按实际安装的改23.11 是当前常用版本。如果项目是 64 位用x64-win64目录32 位用x86-win32。注意 Halcon 的 license 文件要放在bin目录下或者通过set_system(license_file, ...)指定路径否则初始化会失败。4.2 在 C# 中加载模型并推理C# 里用HDevEngine或直接调HOperatorSet加载模型。推荐用HDevEngine把 HDevelop 的推理过程封装成外部过程C# 调用过程名传参这样逻辑改动不用重编译 C#。下面是加载模型并推理的 C# 代码using HalconDotNet; public class HalconInference { private HTuple modelHandle; private HDevEngine engine; public void LoadModel(string modelPath) { // 加载训练好的模型 HOperatorSet.ReadDlModel(modelPath, out modelHandle); // 设置推理时的 batch size HOperatorSet.SetDlModelParam(modelHandle, batch_size, 1); } public HTuple Infer(HObject image) { HTuple result; // 调用推理算子 HOperatorSet.ApplyDlModel(modelHandle, image, all, out result); return result; } }逻辑说明ReadDlModel加载.hdl模型文件SetDlModelParam设 batch size 为 1推理时逐张处理。ApplyDlModel执行推理返回结果元组包含类别 ID、置信度、边界框坐标。参数说明batch_size推理时设 1 延迟最低设 4 吞吐高但延迟增加。ApplyDlModel的第三个参数all表示返回所有输出也可以指定segmentation或detection只取需要的部分。返回的边界框坐标是归一化的要乘以图像宽高还原像素坐标。4.3 推理结果可视化和数据回传推理完要把结果画到图像上C# 里用 Halcon 的绘图算子public void DrawResults(HObject image, HTuple result, HWindow window) { // 获取边界框和类别 HTuple bbox result.TupleSelectRange(0, 3); HTuple classIds result.TupleSelect(4); HTuple confidences result.TupleSelect(5); window.ClearWindow(); window.DispObj(image); for (int i 0; i classIds.Length; i) { if (confidences[i].D 0.5) continue; // 置信度过滤 double row1 bbox[i * 4].D * imageHeight; double col1 bbox[i * 4 1].D * imageWidth; double row2 bbox[i * 4 2].D * imageHeight; double col2 bbox[i * 4 3].D * imageWidth; window.SetColor(red); window.DispRectangle1(row1, col1, row2, col2); window.DispText(classNames[classIds[i].I], image, row1, col1, red, box, false); } }逻辑说明TupleSelectRange取边界框的四个坐标TupleSelect取类别 ID 和置信度。置信度低于 0.5 的框不画减少误检干扰。坐标从归一化值乘以图像宽高还原。参数说明置信度阈值 0.5 是起点误检多就提到 0.7漏检多就降到 0.3。DispText的最后一个参数false表示不画文字背景框画面更干净。5. 验证与调优怎么确认模型能上线5.1 验证集评估指标解读Halcon 的evaluate_dl_model返回 precision、recall、f1_score、mAP 等指标。Detection 任务重点看 mAPmean Average PrecisionSegmentation 任务看 IoUIntersection over Union。mAP 低于 0.7 时模型基本不可用0.7 到 0.85 需要调优0.85 以上可以考虑上线。评估代码* 在测试集上评估模型 evaluate_dl_model(DLModelHandle, TestDataloader, EvalResults) get_dict_tuple(EvalResults, mAP, MAP) get_dict_tuple(EvalResults, precision, Precision) get_dict_tuple(EvalResults, recall, Recall) disp_message(3600, mAP: MAP P: Precision R: Recall, window, 12, 12, black, true)逻辑说明evaluate_dl_model在测试集上跑推理并算指标结果存在字典里。get_dict_tuple取出 mAP、precision、recall。参数说明mAP 的计算依赖 IoU 阈值Halcon 默认 0.5。如果客户要求更严格的定位精度把 IoU 阈值提到 0.75mAP 会下降 10% 到 20%属正常。5.2 误检和漏检的排查方法误检多时先看置信度分布。把测试集所有推理结果的置信度导出来画直方图。如果误检的置信度集中在 0.5 到 0.6说明阈值设低了提到 0.7 能过滤大部分。如果误检置信度高于 0.8说明模型把背景学成了目标要检查标注里有没有漏标的目标被当成背景。漏检多时看召回率。召回低于 0.8 时先检查训练集里该类别的样本数是否少于 100少了就补样本。如果样本够检查增强参数是否把目标转没了把旋转角度和缩放范围调小试试。5.3 模型导出和 C# 端性能测试训练完用write_dl_model导出模型write_dl_model(DLModelHandle, defect_detection.hdl)导出后在 C# 端跑 100 张测试图记录单张推理耗时。工控机上单张 640×480 图像的推理耗时应在 50ms 以内超过 100ms 要考虑换 compact 模型或降分辨率。C# 端计时用StopwatchStopwatch sw new Stopwatch(); sw.Start(); var result Infer(image); sw.Stop(); Console.WriteLine($推理耗时: {sw.ElapsedMilliseconds} ms);逻辑说明Stopwatch测单次推理耗时跑 100 次取平均。第一次推理会包含模型加载时间从第二次开始计。参数说明耗时超过 100ms 时先把image_width和image_height降到 480×360 试试精度掉不超过 5% 的话可以接受。还不行就换pretrained_dl_classifier_compact.hdl从头训compact 模型推理速度比 enhanced 快 2 到 3 倍。6. 避坑与排查标注训练验证里的血泪经验6.1 标注类别名不一致导致训练报错现象训练启动时报Unknown class name或class_names mismatch。原因标注 JSON 里的类别名和set_dl_model_param里的class_names列表不一致比如标注里写的是scratch配置里写的是Scratch大小写不同。解决用 2.2 节的检查脚本先跑一遍把所有标注文件的类别名统一。Halcon 的类别名区分大小写建议全用小写加下划线。6.2 图像尺寸和标注尺寸不匹配现象训练 loss 正常下降但验证精度始终低于 0.5推理时框的位置偏移很大。原因标注时的图像尺寸和set_dl_model_param里的image_width/image_height不一致Halcon 自动缩放图像时把标注框也缩放了但缩放比例没对齐。解决标注前先确认图像尺寸训练配置里的尺寸和标注尺寸保持一致。如果必须缩放用scale_image先统一缩放图像和标注再训练。6.3 C# 调用时报 DllNotFoundException现象C# 程序在开发机上跑正常部署到工控机上报DllNotFoundException: halcon.dll。原因工控机上没装 Halcon 运行时或者 PATH 里没有 Halcon 的 bin 目录。解决把 Halcon 安装目录的bin/x64-win64整个文件夹拷到工控机在 C# 程序启动时用SetDllDirectory指定路径或者把 bin 目录加到系统 PATH。注意 license 文件也要一起拷否则初始化会报 license 错误。6.4 推理结果置信度普遍偏低现象所有推理结果的置信度都在 0.3 到 0.5 之间没有高于 0.7 的。原因训练时学习率设太大模型没收敛或者训练轮数不够模型欠拟合。解决把学习率从 0.001 降到 0.0001训练轮数从 100 加到 200。如果还不行检查训练集里正样本和负样本的比例负样本背景图太多时模型会偏向预测背景置信度普遍低。负样本比例控制在 1:3 以内。6.5 模型文件太大导致 C# 加载慢现象C# 端ReadDlModel耗时超过 3 秒界面卡顿。原因模型文件超过 100MB加载时要把权重全部读进内存。解决用set_dl_model_param把模型量化成 int8文件大小能压到原来的 1/4推理速度也能提升。量化代码set_dl_model_param(DLModelHandle, quantization, int8) write_dl_model(DLModelHandle, defect_detection_int8.hdl)逻辑说明quantization设int8把浮点权重转成 8 位整数精度损失通常在 1% 到 3%。参数说明量化后要在测试集上重新评估mAP 掉超过 5% 就放弃量化改用裁剪模型层数的方式压缩。7. 把验证做成自动化脚本一个省后悔药的习惯训练完手动跑评估、手动记录指标、手动对比不同参数的效果这套流程跑三次以上就会烦。我后来的习惯是写一个 HDevelop 脚本把训练、评估、导出串成一条流水线每次改参数只改脚本开头的配置区跑完自动输出对比表格。这样调参时不会漏掉某次实验的记录也不会因为手动操作引入不一致。脚本结构大概是这样配置区放数据集路径、类别名、学习率、batch size、增强参数训练区跑训练循环评估区在测试集上算 mAP、precision、recall导出区把模型和指标写到一个 CSV 里。每次实验的 CSV 追加一行跑十次后打开 CSV 就能看出哪个参数组合最好。* 自动化训练评估流水线配置区 ConfigFile : experiment_config.txt read_tuple(ConfigFile, [], [], Config) LR : Config[0] BatchSize : Config[1] Epochs : Config[2] AugRotate : Config[3] * 训练区 set_dl_model_param(DLModelHandle, learning_rate, LR) set_dl_model_param(DLModelHandle, batch_size, BatchSize) set_dl_model_param(DLModelHandle, augmentation_rotate, AugRotate) for Epoch : 1 to Epochs by 1 train_dl_model_batch(DLModelHandle, TrainDataloader, TrainResults) endfor * 评估区 evaluate_dl_model(DLModelHandle, TestDataloader, EvalResults) get_dict_tuple(EvalResults, mAP, MAP) get_dict_tuple(EvalResults, precision, Precision) get_dict_tuple(EvalResults, recall, Recall) * 导出区追加到 CSV open_file(experiment_log.csv, append, FileHandle) fwrite_string(FileHandle, LR , BatchSize , Epochs , AugRotate , MAP , Precision , Recall \n) close_file(FileHandle) write_dl_model(DLModelHandle, model_lr LR _bs BatchSize .hdl)逻辑说明配置区从文本文件读参数改参数不用改脚本。训练区按配置跑训练。评估区算指标。导出区把参数和指标追加到 CSV同时按参数组合命名保存模型文件方便回溯。参数说明experiment_config.txt每行一个参数顺序和Config索引对应。CSV 用逗号分隔Excel 直接打开就能排序筛选。模型文件名带参数组合避免覆盖。这个习惯帮我省了很多后悔药。有一次客户反馈模型在产线上漏检率突然升高我翻出 CSV 发现是三天前改了一版增强参数旋转角度从 10 度提到 20 度把细长划痕转没了。如果没有 CSV 记录根本想不到是增强参数的问题。把验证自动化不是为了省事是为了在出问题时能快速定位到是哪次改动引入的。希望帮到你。本文还有配套的精品资源点击获取