Yolov5实战三部曲:从数据标注到C#端集成部署

张开发
2026/4/19 3:12:50 15 分钟阅读

分享文章

Yolov5实战三部曲:从数据标注到C#端集成部署
1. 数据标注实战从LabelImg到高质量数据集第一次接触目标检测项目时最让我头疼的就是数据标注环节。当时为了做一个工业零件缺陷检测系统需要标注上千张电路板图像。试过各种标注工具后发现LabelImg依然是新手最友好的选择。这里分享几个实战中总结的高效标注技巧安装避坑指南推荐直接下载编译好的Windows版本labelImg_v1.8.1.exe避免源码安装的依赖冲突问题。记得把程序放在全英文路径中文路径会导致闪退快捷键组合拳W创建框、A上一张、D下一张、CtrlS保存这几个组合键熟练后标注效率能提升3倍以上。我习惯左手控制键盘快捷键右手微调标注框位置批量处理技巧通过修改predefined_classes.txt预设类别可以避免重复输入标签。比如做安防监控项目时提前写好person/car/dog等常见类别注意标注时要确保物体边缘留有少量背景像素太贴边的标注会影响模型学习特征提取实际项目中遇到过标注不一致的问题——同一类物体不同人标注的宽高比例差异很大。后来我们制定了标注规范对于规则物体如芯片采用1:1固定比例不规则物体如裂缝则严格沿轮廓标注。这个细节让模型mAP提升了5%左右。2. YOLOv5模型训练版本选择与调参秘籍2.1 5.0 vs 6.1版本深度对比在智能质检项目中我同时用过v5.0和v6.1两个版本。这两个版本的主要差异在于网络结构v6.1的Focus模块替换为Conv减少切片操作带来的部署问题Anchor设置v5.0默认使用P5检测头v6.1改为P6结构更适合小目标检测数据增强v6.1新增albumentations支持对工业场景的遮挡、反光更鲁棒# 训练命令参数对比示例 # v5.0典型配置 python train.py --img 640 --batch 16 --epochs 100 --data coco.yaml --weights yolov5s.pt # v6.1优化配置 python train.py --img 640 --batch 32 --epochs 150 --data coco.yaml --weights yolov5s.pt --hyp hyp.scratch-low.yaml2.2 工业场景调参经验在PCB缺陷检测中通过调整以下参数显著提升效果学习率策略采用余弦退火cosine lr比默认的线性下降更适合小数据集损失权重调整obj_loss权重为0.7缓解正负样本不平衡问题测试时增强启用--augment选项对模糊、低对比度样本更稳定遇到过最坑的问题是显存溢出CUDA out of memory。后来发现把--batch-size减半同时增大--workers到4倍CPU核心数既能保证训练速度又避免爆显存。3. ONNX模型导出避开那些深坑3.1 导出关键步骤用v6.1导出ONNX时必须添加--dynamic参数python export.py --weights best.pt --include onnx --dynamic这样生成的模型才能适配不同尺寸输入。曾经因为漏掉这个参数导致C#端推理时张量形状不匹配。3.2 模型简化技巧用onnx-simplifier处理导出的模型python -m onnxsim yolov5s.onnx yolov5s-sim.onnx这个操作能去除冗余计算节点让推理速度提升20%。但要注意过度简化可能导致某些算子不被C#支持。4. C#集成部署工业级落地方案4.1 环境配置清单NuGet必备包Microsoft.ML.OnnxRuntime (1.12.0)OpenCvSharp4 (4.5.5)Newtonsoft.Json (处理检测结果)// 初始化推理会话 var session new InferenceSession(yolov5s.onnx); var inputMeta session.InputMetadata; var inputName inputMeta.Keys.First();4.2 性能优化实战在视频分析项目中通过以下改动使FPS从15提升到32内存复用预分配输入输出Tensor避免每次推理重新分配异步流水线用Producer-Consumer模式分离图像采集和推理算子融合将sigmoid乘法替换为HardSwish激活函数最棘手的跨平台问题是在ARM工控机上部署。解决方案是编译onnxruntime的ARM64版本并关闭不必要的算子优化选项。4.3 完整调用示例// 图像预处理 Mat src Cv2.ImRead(test.jpg); Mat resized new Mat(); Cv2.Resize(src, resized, new Size(640, 640)); // 构建输入Tensor var inputTensor new DenseTensorfloat(new[] { 1, 3, 640, 640 }); for (int y 0; y 640; y) { for (int x 0; x 640; x) { var color resized.AtVec3b(y, x); inputTensor[0, 0, y, x] color.Item0 / 255f; inputTensor[0, 1, y, x] color.Item1 / 255f; inputTensor[0, 2, y, x] color.Item2 / 255f; } } // 执行推理 var results session.Run(new[] { NamedOnnxValue.CreateFromTensor(inputName, inputTensor) }); // 解析输出 var outputTensor results.First().AsTensorfloat(); var predictions ProcessOutput(outputTensor);这套代码在多个工业现场稳定运行超过1年关键是要处理好异常恢复机制——当推理超时或内存泄漏时自动重启服务。

更多文章