简介:面向工业自动化视觉工程师与Halcon初学者,这份学习笔记以图像分类为主线,系统梳理Halcon深度学习从数据准备、模型创建到训练与部署的完整流程,内容贴近实战,尤其注重视觉任务中的参数细节与常见坑点,适合零基础入门与进阶提升。资源包共39个文件,包含24张流程与效果示意图、12个XML配置/关系文件及3个rels关联文件,整体仅1.7MB,内部以Word笔记为主体,辅以图片直观展示每个操作节点,XML文件则对应文档结构和样式信息,便于学习者按章节阅读。目前已有3146人学习下载,学习者可从中获得完整分类模型构建思路、数据标注要点、训练参数调优方法以及模型验证阶段的排错技巧,对照图片和文档逐步实操,能有效缩短上手周期,是一份高密度的Halcon深度学习实战参考资料。
1. Halcon 深度学习到底怎么学:一份从零开始的分类学习笔记
很多做视觉检测的同行,遇到纹理缺陷、复杂背景下的分类问题,第一反应是上 SVM、调阈值,结果在产线上改参数改到失去耐心。Halcon 深度学习其实已经把这条路缩短了不少:不用自己写卷积网络,HDevelop 里就能完成数据准备、训练、评估和部署。我一开始被一堆算子绕晕,光是preprocess_dl_dataset和模型参数就卡了几天。后来把踩过的细节整理成《Halcon深度学习-从零开始学习,学习笔记(都是细节)-分类完整版.rar》,整套流程走下来,分类任务的关键节点都在里面。这份笔记适合刚接触 Halcon 深度学习、正要处理图像分类项目的算法工程师和设备调试人员,也适合想从传统视觉工具链切换过来的老手快速上手。
2. 先搞懂分类任务在 Halcon 里怎么跑:从传统特征到深度学习的转轨
2.1 为什么分类任务更适合交给 Halcon 深度学习
传统视觉做分类,核心是先做分割,再提取几何特征、灰度特征或纹理特征,最后喂给分类器。这套老流程有两个明显的头疼点:第一,图像的光照、角度、轻微形变一变,分割参数就得跟着调,很多时候是按下葫芦浮起瓢;第二,特征是自己设计的,本质上是人脑在找规律,而不是数据在找规律。Halcon 深度学习把这两个问题绕过去了:输入图像,输出类别,中间的特征提取由网络自己完成。对一线工程来说,最大的收益是不用维护几十个特征参数,只要把数据集整理好,剩下的交给训练。
另一个实际原因是 Halcon 的深度学习和 HDevelop 的联动做得比较顺。数据加载、预处理、训练、评估、导出模型,都是在同一套开发环境里完成,不需要像开源框架那样去管 Python 环境、CUDA 配置和推理框架转换。工业现场常见的典型分类任务,比如工件表面缺陷分类、零件正反判别、产品型号分拣,用 Halcon 深度学习分类都能覆盖。当然它的灵活性不如 PyTorch、TensorFlow,但对大多数落地项目来说,够用而且可控。
2.2 分类任务的完整流程拆解:从图片文件夹到模型文件
Halcon 深度学习分类任务的完整闭环,可以拆成五个环节:数据集读取、数据集划分、预处理、模型训练、模型评估与导出。后面还有一个部署环节,但那是另一个话题。整个流程的核心是DLDataset这个数据结构,它把图像路径、标签、训练/验证/测试分组信息都装在一起。和开源框架最大的不同是,Halcon 把数据管理也做成了算子,流程是高度结构化的。
下面的代码示意了从磁盘读取分类数据集的常规做法,也是分类任务里反复强调的起步动作:
* 读取分类数据集,ImageDirectory 下每个子目录代表一个类别 read_dl_dataset (DLDataset, 'data', ['class_0', 'class_1'], ['class_0', 'class_1'], []) * 查看样本总数,确认读取成功 get_dl_dataset (DLDataset, 'num_samples', NumSamples)逻辑说明:read_dl_dataset的第一个输出参数是数据集句柄DLDataset;第三个参数是类别目录名列表,第四个参数是类别显示名列表。Halcon 会扫描根目录下指定子目录里的图片文件,并为每个文件打上类别标签。我一般让目录名和类别显示名保持一致,避免后续代码里来回映射。最后一个参数是通用参数元组,通常传空元组。
参数说明:类别目录名列表的顺序就是模型输出层的类别顺序,这个顺序很关键,训练和推理阶段如果顺序不一致,结果会张冠李戴。get_dl_dataset用来查询数据集里的属性,num_samples返回样本总数,num_classes和class_names也常用。建议每次读取数据后先查一遍,确认图片数量和自己预期一致,再往下走。
读进来之后要划分训练、验证、测试集。Halcon 提供split_dl_dataset做这件事,可以按比例划分,也可以指定每类样本数。比手工切文件夹省心得多,而且能保证划分结果记录在DLDataset里,训练和评估都直接用这个结构。
* 按比例划分数据集,前70%训练,15%验证,15%测试 split_dl_dataset (DLDataset, ['train', 'validation', 'test'], [0.7, 0.15, 0.15], [], DLDatasetSplit)逻辑说明:split_dl_dataset的第二个参数是分组类型列表,第三个参数是比例列表,两者长度一致。函数返回新的数据集句柄DLDatasetSplit,内部的样本被打上了分组标记。训练时只取标记为train的样本,验证时取validation,测试时取test。
参数说明:比例列表不一定要和为 1,比如[0.6, 0.2]也可以。但要注意,如果数据量很小,比如每类只有几十张,我建议加大验证集比例,或者干脆先不切测试集,把所有数据都参与训练和验证,等模型稳定了再补测试数据。
需要特别强调的是,Halcon 深度学习分类流程里,DLDataset是一个字典结构,初学者容易把它当成普通图像数组,导致后面算子调用时句柄对应不上。我用下来的习惯是每个阶段都给数据集句柄取不重名的变量名,比如DLDatasetRaw、DLDatasetSplit、DLDatasetTrain,避免调试时覆盖掉原始数据。在流程里,create_dl_model是创建模型的关键一步,下面单独说。
2.3 模型创建与迁移学习:为什么先从预训练模型开始
Halcon 提供了基于预训练模型的初始化方式,比如pretrained_dl_classifier.hdl,它是在大型自然图像数据集上预训练过的网络,可以直接迁移到自己的分类任务上。使用预训练模型可以显著减少迭代轮数,尤其当自己的数据集不够大的时候,效果比从头训练好得多。
* 创建基于预训练权重的分类模型 create_dl_model ('pretrained_dl_classifier.hdl', DLModelHandle)逻辑说明:这一行会加载预训练网络结构,并返回模型句柄DLModelHandle。之后对模型的所有参数设置都通过set_dl_model_param完成。这里有一个容易踩的细节:create_dl_model需要在preprocess_dl_dataset之前调用,因为预处理算子的参数,比如目标图像尺寸,正是从模型句柄里读取的。有些初学者先做预处理再创建模型,发现尺寸对不上,其实就是调用顺序反了。
参数说明:如果 Halcon 安装目录中没有对应的预训练模型文件,create_dl_model会直接报错。这往往不是代码问题,而是安装时没选深度学习组件。不同版本 Halcon 自带的预训练模型文件名可能不同,建议先看安装目录下的.hdl文件再写代码。
2.4 与传统视觉流程的对接:什么时候该转深度学习
不是所有分类问题都要上深度学习。如果目标物和背景对比度极高、位置固定、光照稳定,传统视觉可能更快更稳。但如果你发现以下信号,就可以考虑转 Halcon 深度学习:图像中目标形态差异大,规则不好总结;背景复杂,分割后特征重叠严重;缺陷样本和正常样本的边界模糊,传统特征分类精度卡在某个瓶颈上;现场有多个相似型号需要区分,改规则改到怀疑人生。
从工程节奏上,深度学习方案初期会比传统视觉慢,因为要准备数据、训练模型,但一旦数据集成形,后续换型号、加类别,只需要补样本重新训,往往比重新调阈值快。这也是为什么自动化设备厂越来越愿意在可能多品类生产的场景上预埋深度学习方案。选型时还要考虑硬件成本:训练阶段建议用支持深度学习的独立显卡,显存最好 8GB 以上;推理可以 CPU,但速度会慢。如果现场只有老工控机、没有显卡,部署时就要评估 CPU 推理耗时是否能满足节拍。
下面是分类流程中会反复用到的核心算子清单,方便你对照学习笔记快速定位。
| 算子 | 作用 | 常见使用阶段 |
|---|---|---|
| read_dl_dataset | 从目录结构读取图像与标签 | 数据准备 |
| split_dl_dataset | 划分训练、验证、测试集 | 数据准备 |
| create_dl_model | 创建、初始化分类模型 | 训练前 |
| preprocess_dl_dataset | 批量预处理数据集 | 训练前 |
| train_dl_model | 执行模型训练 | 训练 |
| evaluate_dl_model | 评估模型精度与混淆矩阵 | 评估 |
| apply_dl_model | 对单张图像推理 | 部署 |
这个清单基本覆盖了分类任务的全部主线。你在这份学习笔记里看到的每个细节,都会落到这七个算子周围。接下来要做的,就是把数据集这个地基打好。
3. 从零准备一份能训的分类数据集:目录结构、标注检查与预处理参数
3.1 硬件与 Halcon 版本选择:先把地基打牢
很多新手拿到学习笔记,第一个问题不是算子,而是“我的机器能不能跑”。这里我给出一个相对务实的判断标准。训练阶段,Halcon 深度学习主要依赖支持 CUDA 的独立显卡,型号和驱动环境直接决定能否识别设备。显存大小直接影响batch_size上限。我的经验是 8GB 显存可以从batch_size = 8开始试探,4GB 以下优先考虑 CPU 训练小数据集。CPU 也能训,就是慢,几百张图片可能要跑几个小时,但用来验证流程完全够。
怎么确认 Halcon 能不能看到你的计算设备?HDevelop 里直接调用query_available_compute_devices:
query_available_compute_devices (DeviceIdentifiers) * 如果 DeviceIdentifiers 为空,说明没有可用的 GPU 加速设备逻辑说明:这个算子会返回当前机器上可用的计算设备标识符,Halcon 会识别独立显卡以及 CPU。拿到标识符后,通常还会用get_compute_device_info查看设备的显存大小和名字,判断是不是可以跑深度学习训练。如果设备列表有多个项,可以显式指定其中一个,避免选到集成显卡。
参数说明:如果你的机器明明有独立显卡,但DeviceIdentifiers返回空或者只有 CPU,那问题基本出在显卡驱动、CUDA 环境和 Halcon 版本匹配上。这不是你代码的问题,是环境变量的问题。如果这一步检查不过,后面所有训练算子都会报错或者异常慢,所以我会在项目一开始就把设备检查写成一个单独的.hdev脚本,每次换机器先跑一遍。
3.2 数据集的目录结构:命名规则与标签顺序
数据是深度学习的粮食,分类任务对数据目录结构的要求其实很严格。Halcon 的read_dl_dataset期望看到的是“每个类别一个文件夹”的结构。推荐的组织方式如下:
data/ train/ class_0/ img_001.png img_002.png class_1/ img_001.png val/ class_0/ class_1/ test/ class_0/ class_1/注意,目录名或者类别名不要用中文,不要带空格,也不要用特殊字符。Halcon 在处理路径时,中文在部分系统区域设置下会乱码,导致读取不到图像。我一般统一用小写英文加下划线的命名方式,比如defective、normal。类别显示名可以在read_dl_dataset里单独指定,即使目录名是class_0,也可以显示为normal,但为了避免中途换环境出幺蛾子,代码里显示名也用英文。
读取代码如下:
* 读取 data 目录下的分类数据 read_dl_dataset (DLDatasetRaw, 'data', ['class_0', 'class_1'], ['class_0', 'class_1'], [])逻辑说明:这里把data作为根目录,class_0、class_1作为类别目录列表,Halcon 会扫描根目录下这两个子目录里面的所有图片文件。注意它不会递归扫描多层目录,所以不要在其中再嵌套子目录,否则会漏掉样本。这个细节我翻过车:一开始想按日期分组存放图片,结果训练时样本数远少于预期,查了半天才发现是嵌套目录被忽略了。
参数说明:如果图片不是 png/jpg 而是 bmp、tif,需要在通用参数里指定文件扩展名或格式相关参数。不同版本的 Halcon 对格式的支持略有差异,但思路是确保所有图片都能被正确识别,而不是在训练时报“找不到图像”。
3.3 预处理:不只是缩放到模型输入尺寸
预处理是 Halcon 深度学习里最容易出错的一环。初学者以为预处理就是 resize,但实际上 Halcon 的preprocess_dl_dataset会根据模型参数完成缩放、通道转换、归一化等一系列操作。它输出一个预处理后的数据集句柄,训练时就以这个句柄为准。
在预处理之前,先要确定模型输入尺寸并设置到模型上:
set_dl_model_param (DLModelHandle, 'image_width', 224) set_dl_model_param (DLModelHandle, 'image_height', 224) preprocess_dl_dataset (DLDatasetSplit, 'train', DLDatasetTrain, 'none', [], []) preprocess_dl_dataset (DLDatasetSplit, 'validation', DLDatasetVal, 'none', [], []) preprocess_dl_dataset (DLDatasetSplit, 'test', DLDatasetTest, 'none', [], [])逻辑说明:set_dl_model_param把模型输入分辨率设置为 224x224,这是预训练分类模型的常见输入尺寸。然后分别对训练、验证、测试分组执行preprocess_dl_dataset。预处理完成后,数据集句柄里就包含了预处理后的图像数据,后续算子直接使用。
参数说明:preprocess_dl_dataset的第三个参数是分组名,第四个参数是数据增强策略,这里'none'表示不做增强。最后一个元组可以传'color_space'之类的通用参数。如果图像本身是灰度图,但模型输入是三通道,Halcon 会自动复制灰度到三通道;但如果你把彩色图按灰度处理,可能会丢失纹理特征,所以数据加载阶段就要明确色彩通道。
关于数据增强,Halcon 提供了augment_dl_dataset算子,可以对训练集做随机翻转、旋转、缩放、加噪。数据增强的强度不宜过大,否则会把真实分布破坏掉。我的习惯是先不加增强,跑通整个流程,然后再逐步加上,观察验证集精度变化。这个策略能帮你判断提升来自增强还是来自模型本身。
预处理相关的常见参数可以整理成下面一张表:
| 参数名 | 典型值 | 作用 |
|---|---|---|
| image_width | 224 | 模型输入宽度 |
| image_height | 224 | 模型输入高度 |
| color_space | 'rgb' | 输入图像色彩空间 |
| batch_size | 8 | 每次迭代样本数 |
| learning_rate | 0.0005 | 初始学习率 |
| max_iterations | 200 | 最大迭代步数 |
这里面的数值都需要结合自己的图像和显存情况调整,未必是标准答案。学习笔记里对每个参数都有更细的说明,但原则是先跑通、再优化。
3.4 样本检查:训练前花十分钟看预处理结果
训练前我强烈建议把预处理后的图像实际看一遍。Halcon 可以在调试窗口显示样本,也可以导出成文件。检查两个点:一是图像是否被缩放变形,二是类别标签和图像内容是否匹配。尤其是缩放出错时,图像会被拉伸,有些目标特征直接变了形,训练出来的模型精度自然上不去。
* 遍历前 50 个预处理样本,显示图像与标签 for Index := 0 to 49 by 1 get_dl_dataset (DLDatasetTrain, Index, 'image', ImagePreprocessed) get_dl_dataset (DLDatasetTrain, Index, 'class_id', ClassID) dev_display (ImagePreprocessed) * 可以在这里设置断点,确认图像和标签对应关系 endfor逻辑说明:get_dl_dataset按索引取预处理后的图像和类别 ID。通过窗口循环显示,你可以直观检查是否出现类别错乱、图像全黑、通道异常等问题。这一步只需要几分钟,能省掉后面训练完才发现数据不对的返工。
参数说明:Index是样本索引,'image'是取值键名,'class_id'是类别索引。注意类别 ID 是整数,想看到类别名就要再拿class_names去映射。在循环里也可以随机抽,不用一定从 0 开始。
4. 把模型真正训起来:训练参数设置、Loss 阅读与模型评估输出
4.1 训练前的最后检查:类别数量、模型参数与数据集一致性
开始训练前,先做一次参数体检。用get_dl_model_param读取模型关键参数,确保和数据集一致。最容易翻车的三个点:类别数量、输入尺寸、设备选择。
get_dl_model_param (DLModelHandle, 'num_classes', NumClasses) get_dl_model_param (DLModelHandle, 'image_width', ImageWidth) get_dl_model_param (DLModelHandle, 'image_height', ImageHeight) get_dl_model_param (DLModelHandle, 'classes', ClassNames)逻辑说明:get_dl_model_param的第二个参数是参数名,第三个参数是返回值。这里分别取分类数、输入宽高和类别名列表。与数据集中的类别数量对比,如果NumClasses不等于数据集里的类别数,训练一定会报错或者结果混乱。
参数说明:'classes'返回的是字符串元组,这个元组的顺序就是模型输出层各个类别的顺序。在这个阶段,建议把类别顺序打印出来,和read_dl_dataset里传的顺序核对一遍。Halcon 的报错信息有时候不直接说明是哪两类顺序反了,所以这个检查很有必要。
此外还要设置训练相关参数。我常用的初始值如下:
set_dl_model_param (DLModelHandle, 'learning_rate', 0.0005) set_dl_model_param (DLModelHandle, 'batch_size', 8) set_dl_model_param (DLModelHandle, 'max_iterations', 200) set_dl_model_param (DLModelHandle, 'momentum', 0.9)逻辑说明:学习率0.0005是迁移学习场景下比较稳的起点,比默认的0.001略低,能避免预训练权重被破坏。batch_size根据显存调整,8 是从小到大的中间值。max_iterations决定训练多少个迭代步,可以先用 200 跑通,再根据 Loss 收敛情况调整。动量0.9是标准配置,一般不用动。
参数说明:learning_rate过大容易造成训练 Loss 抖动甚至下不去;过小则收敛慢。batch_size太大容易显存溢出,太小则梯度噪声大。在工业项目里,我建议优先保证训练能稳定跑完,再谈精度,所以参数都往保守设置。
4.2 执行训练并读懂 Loss 曲线
一切就绪后,调用train_dl_model开始训练。这一步会中断 HDevelop 的图像窗口显示,弹出训练进度窗口,实时绘制训练和验证 Loss 曲线。你也可以把训练结果存下来,用于分析和复盘。
train_dl_model (DLModelHandle, DLDatasetTrain, DLDatasetVal, [], [], DLTrainResult)逻辑说明:train_dl_model的输入分别是模型句柄、预处理后的训练集和验证集。输出DLTrainResult是一个字典,里面记录了每次迭代的 Loss 和验证精度。训练过程中,Halcon 内部会自动在若干迭代步后用验证集评估一次,不需要手动打断。
参数说明:如果验证集为空,训练时不会显示验证曲线。所以前期split_dl_dataset一定要留出验证集。另外训练过程不是完全可复现的,即使相同参数跑两次,结果也可能有细微差异,这是由随机初始化等原因造成的,不用过度担心。但从工程角度,我会保留每次训练的结果文件,方便对照。
训练结束后,读取 Loss 曲线数据可以这样做:
* 从训练结果字典中读取训练 Loss 序列 get_dict_tuple (DLTrainResult, 'train_loss', TrainLossSequence) * 取出最后一个 Loss 值,判断是否收敛 TupleLast (TrainLossSequence, LastLoss)逻辑说明:DLTrainResult是 Halcon 的字典类型,get_dict_tuple按键名取数据。这里取train_loss得到一维数组,再用TupleLast取最后一个值。如果LastLoss还在明显下降,说明训练轮数不够,可以继续训或者用更大迭代次数再跑一轮。
参数说明:字典键名在不同 Halcon 版本里可能有差异,我也见过validation_loss、train_accuracy这些键。如果get_dict_tuple报找不到键,就先用get_dict_param列出所有键名,再从中挑对应的字段。
4.3 评估:用混淆矩阵判断模型是不是真的可用
训练完成不代表模型就能上线。分类任务必须看评估结果,尤其是混淆矩阵。Halcon 提供evaluate_dl_model一键在测试集上评估:
evaluate_dl_model (DLModelHandle, DLDatasetTest, [], DLResult, DLEvalResult) get_dict_tuple (DLEvalResult, 'confusion_matrix', ConfusionMatrix)逻辑说明:evaluate_dl_model的输出DLResult是每个样本的预测结果,DLEvalResult是统计结果,里面包含confusion_matrix、accuracy、precision、recall等字段。拿到混淆矩阵后,就能看出哪些类别互相搞混。
参数说明:混淆矩阵的行是真实类别,列是预测类别,对角线是正确样本数。看混淆矩阵时不要只盯着总精度,更要看易混类别的比例。比如两个类别相似度高,相互误判率 30%,总精度 85%,这种模型上产线会频繁错分,需要继续补样本或调预处理。
评估结果还可以进一步用于模型选择。如果验证集精度和测试集精度差距过大,说明模型过拟合了训练集,要考虑增强数据或减小模型容量。Halcon 里没有自动早停,需要自己根据曲线判断迭代次数。
4.4 欠拟合与过拟合:只看训练 Loss 不够
我见过不少新手,训练结束只看最后一个 Loss,认为 Loss 足够低就万事大吉。实际上,训练 Loss 低可能只是记住了训练样本。判断模型是否过拟合,最快的方法是看验证集 Loss 从哪个迭代步开始回头向上。如果训练 Loss 持续下降、验证 Loss 开始反弹,说明模型开始死记训练集了。这时可以用的招数:降低学习率、加大数据增强、增加训练样本、更早停住迭代。
Halcon 的深度学习笔记里很少直接提“早停”这个词,但工程上非常关键。我在项目里的做法是:先用一个max_iterations跑全量训练,拿到完整 Loss 曲线,再根据最优验证 Loss 对应的迭代步反推合理轮数,最后用这个轮数重新训练一版。虽然多花一次训练时间,但能换来稳定得多的结果。显存允许的情况下,也可以多跑几个不同的batch_size,把训练时间和精度记录下来,作为后续类似项目的起点。
5. Halcon 深度学习分类的避坑手册:四条典型翻车现场
这一章我把自己实际踩过的坑按「现象 → 原因 → 解决」的方式拆开,基本覆盖了从环境到部署的高频问题。
5.1 现象:create_dl_model报错找不到模型文件
现象:在 HDevelop 里执行create_dl_model ('pretrained_dl_classifier.hdl', DLModelHandle),弹出错误提示,内容类似 "Model file ... not found"。
原因:这个文件不在 Halcon 的搜索路径下,或者安装 Halcon 时没有安装深度学习扩展组件。很多精简版或定制版 Halcon 不带.hdl预训练模型,问题根本不在代码,而是环境不完整。
解决:先在 Halcon 安装目录下搜索pretrained_dl_classifier.hdl是否存在。如果不存在,重装完整版并勾选深度学习组件;如果存在,把该文件所在目录加入 HDevelop 的搜索路径,或者直接用绝对路径。检查搜索路径可以用:
get_system ('search_path', SearchPath)看到SearchPath后,把预训练模型所在目录追加进去,再重新执行create_dl_model。这个问题不是算法问题,别在算子参数上浪费时间。
5.2 现象:训练开始没几步,程序直接退出或显存溢出
现象:train_dl_model刚跑起来,显卡风扇狂转,随后程序崩溃,控制台或对话框提示 out of memory;在任务管理器看显存被占满。
原因:batch_size设置过大,超出显卡显存。另一个可能原因是设备选择错误,把训练任务指定到了集成显卡而不是独立显卡,导致性能极差或直接报错。
解决:先把batch_size降到 2 或 4,跑通流程后再逐步调大。同时用query_available_compute_devices确认设备列表,用set_compute_device明确选择独立显卡。代码示例如下:
query_available_compute_devices (DeviceIdentifiers) * 如果有多块设备,这里手动选择索引为0的独立显卡 set_compute_device (0)参数说明:set_compute_device的参数是设备索引,索引顺序由query_available_compute_devices返回。如果机器有双显卡,Halcon 可能识别到集成显卡,需要显式指定指向独立显卡。另外,关闭其他占用显存的程序,比如另一个 HDevelop 实例或正在做渲染的软件。CPU 训练可以作为备选,把设备索引指向 CPU,但要接受速度慢。
5.3 现象:训练精度高,测试精度一塌糊涂
现象:训练集准确率 99%,验证集或测试集准确率只有 70%。训练 Loss 曲线一路向下,验证 Loss 明显反弹。
原因:典型的过拟合。常见诱因是训练样本太少、模型容量过大,或者训练集和测试集分布不一致。还有一个容易被忽略的坑:数据划分前没有清洗重复或近似重复的图像,同一个目标的不同命名被分到训练和测试两个集合里,导致测试结果虚高,实际上线就露馅。
解决:检查是否在read_dl_dataset之前做过图像去重。用get_dl_dataset统计每个类别样本数,确保每类至少几百张。增加数据增强,比如随机亮度、镜像、小角度旋转。同时降低学习率、增大max_iterations,让训练更平滑。如果验证 Loss 在第 80 个迭代步开始回升,就把max_iterations设为 75 再训。
增加数据增强时,可以用augment_dl_dataset,但要注意增强强度:
* 对训练集做随机镜像和旋转增强 augment_dl_dataset (DLDatasetTrain, DLDatasetTrainAug, ['mirror', 'rotate'], ['random'], [], [])逻辑说明:augment_dl_dataset的第三个参数指定增强算子,第四个参数指定强度,'random'表示随机应用。增强会复制样本而不是覆盖原图,所以数据集会变大。如果增强太激进,模型会把背景噪声也学进去,所以要控制强度并观察验证集变化。
参数说明:镜像、旋转是最安全的增强方式;亮度、对比度增强要小心,工业图像的光照本身是重要的判断信息,动太多会把真实分布破坏掉。
5.4 现象:推理结果在 HDevelop 里正常,部署后全是同一类
现象:同样一张图像,在 HDevelop 里用apply_dl_model跑结果是正常的,但在程序的部署接口调用却输出同一个类别,像是卡死在一个分类上。
原因:部署端没有正确处理模型加载,或读取了错误的模型路径,导致模型根本没有被加载,程序实际使用的是随机初始化权重。也可能部署端传入的图像通道数和训练时不一致,比如训练时是三通道彩色,部署时传了单通道灰度图。
解决:在部署代码里,先用read_dl_model读取训练导出的.hdl模型,并调用一次get_dl_model_param核对类别顺序:
read_dl_model ('classifier.hdl', DLModelHandle) get_dl_model_param (DLModelHandle, 'classes', ClassNames) apply_dl_model (DLModelHandle, Image, [], DLResult)逻辑说明:这三行是部署端的标准动作。read_dl_model加载模型,get_dl_model_param确认类别顺序,apply_dl_model执行推理。如果ClassNames和训练时不一致,问题出在模型文件本身,重新导出即可。
参数说明:部署端不要自己手工写 resize 和归一化,直接使用apply_dl_model内置的预处理机制,避免两套预处理逻辑不一致。同时用count_channels确认输入图像通道数,必要时用compose3把灰度图拼成三通道。
5.5 现象:中文类别名在部署端乱码
现象:训练时用read_dl_dataset指定类别显示名为中文,HDevelop 里正常,但保存的模型在跨语言环境的机器上读取后,类别名变成乱码。
原因:Halcon 的.hdl模型文件保存的是字符串,但中文编码在不同操作系统区域设置下不兼容。比如在中文 Windows 下训练,到英文 Windows 下读取,字符串按系统默认代码页解码就乱了。
解决:训练阶段类别名统一使用英文、数字和下划线。部署展示层需要中文,可以在代码里维护一个“模型类别名 → 界面中文名”的映射表。这样既保证模型文件跨平台一致,又能在界面上显示中文。这个技巧在需要做多语言界面的项目里很实用。
6. 最后一步:把训练好的分类模型接到产线程序里
6.1 模型导出与跨环境加载
训练完后,把模型保存成独立文件:
write_dl_model (DLModelHandle, 'classifier.hdl')这个文件包含网络结构和权重。部署机上只需要 Halcon 运行时,不需要完整训练环境。读取模型用:
read_dl_model ('classifier.hdl', DLModelHandle) apply_dl_model (DLModelHandle, Image, [], DLResult) get_dict_tuple (DLResult, 'class_ids', ClassID)apply_dl_model会返回分类结果,class_ids是预测类别 ID,再映射到类别名。推理阶段尽量不要自己写预处理,直接交给算子内部逻辑处理,这样训练和部署的一致性有保障。
6.2 模型上线前的最后一个习惯
我每次训练完,不会直接导出部署,而是强制在原始测试集上跑一遍评估,保存混淆矩阵到项目目录。这个习惯帮我挡住了至少三次“训练精度漂亮、现场一用就废”的翻车。具体做法是:在write_dl_model之前,先执行evaluate_dl_model,查看accuracy;如果测试集精度和验证集精度相差超过 2 个百分点,就回去查数据分布或预处理。
另外,部署代码里要保留一个模型版本号字段,推荐把日期和精度写进文件名,比如classifier_v0.95_20250115.hdl。这样现场出了问题,运维人员能直接说清用的是哪一版模型,而不是打开一堆文件挨个猜。从那以后,我每次训练完都会强制走一遍测试集,同时记下模型版本,这个动作已经成了固定流程。希望帮到你。
本文还有配套的精品资源,点击获取