☰
钢材表面缺陷检测实战:YOLOv5训练与部署优化全解析
2026/10/17 8:14:49 网站建设 项目流程

1. 项目概述与核心目标

做工业视觉的人应该都清楚,钢材表面的质量检测一直是钢铁厂最头疼的环节之一。传统的人工肉眼检测不仅效率低下,而且质量不稳定——一个工人盯着传送带上的钢板看八小时,难免疲劳漏检,尤其是在高速产线上,钢材运行速度动辄每分钟几十米,人眼根本跟不上。这个项目要解决的,正是这个问题:用深度学习目标检测模型,对钢材表面的各类缺陷做自动识别和定位。

核心目标很明确——在保证检测精度的前提下,尽可能提升检测速度,让模型能部署到实际产线上。项目主力模型选用了Yolov5,同时把Yolov7、Yolov8、Yolov10都跑了一遍做横向对比,看看不同版本的模型在同一批钢材缺陷数据上表现到底差多少,方便后续选型时心里有数。

适合谁来参考?如果你正在做工业质检相关的项目,或者想在缺陷检测场景下车一下YOLO系列模型的实战效果,这篇文章可以直接当参考。我会把数据准备、标注格式转换、训练配置、模型评估、部署推理整个过程的关键细节都拆开讲,包括一些常规文档里不会写的坑。

先看一下项目整体技术选型为什么这么定。

组件选择理由
检测框架Yolov5(主力)社区生态成熟、部署方案多、速度和精度平衡好
对照模型Yolov7 / Yolov8 / Yolov10验证不同版本的性能差异,覆盖新旧技术路线
缺陷类型氧化皮、划痕、麻点、夹杂、边裂等钢铁产线最常见且难检的缺陷类别
部署框架ONNX Runtime + 量化产线工控机算力有限,需要轻量化部署

实际做下来,我的个人结论是:Yolov5在钢铁缺陷检测这种“速度要求高、缺陷尺寸跨度大、实时性要求强”的场景下依然非常能打,但新版本在训练便捷性和小目标召回率上确实有提升。下面把每个环节展开讲。

2. 数据准备与预处理流程

2.1 钢材缺陷数据集的采集与特性分析

钢材表面缺陷检测的数据,跟通用目标检测数据有一个明显不同:缺陷的种类有限,但每一类的形态差异大、样本数量不平衡。比如氧化皮在热轧过程中经常出现,样本量可能上千张;而边裂这种只在特定工况下出现的缺陷,可能只有几十张。这种长尾分布,在模型训练时极其容易类别倾斜,小样本类别的召回率会非常难看。

我是先从公开的钢材缺陷数据集入手做预实验的,然后再配合现场采集的产线图片做增量训练。这样做的原因很简单:先用公开数据把模型的训练流程跑通,确认整体链路没问题,再用真实产线数据提升模型在特定场景下的表现。钢材缺陷数据的标注比通用目标检测要麻烦,主要原因在于缺陷的边缘不清晰,比如麻点是一群细小凹坑聚集的区域,它的边界框本身就存在模糊性。

还有一个很多新手容易忽略的问题:钢材表面存在纹理干扰。热轧钢板的表面不是纯色的,它会有氧化层、水渍痕迹、光照不均带来的明暗变化,这些都会干扰模型的学习。同样的划痕,在不同光照条件下呈现的灰度分布完全不同,这对模型的泛化能力是个很大的考验。

2.2 标注格式与数据划分策略

标注环节我直接用了LabelImg工具,输出VOC格式的XML文件,然后统一转换成YOLO需要的TXT格式。转换时注意一个关键点:YOLO格式的坐标是归一化的center_x, center_y, width, height,需要除以图片的宽高。别小看这一步,很多人跑出来的模型框位置不准,回头排查发现是坐标没归一化或者是用错了坐标系。

标注类别我建议用英文缩写命名,中文名虽然在显示时方便,但容易在部分框架里出现编码问题。我的类别定义如下:

# categories.txt scale_plate # 氧化皮 scratch # 划痕 pitted_surface # 麻点 inclusion # 夹杂 crazing # 裂纹

数据划分要遵循“按产线批次拆分,而不是按图片随机拆分”的原则。原因是同一块钢材的连续图像之间高度相似,如果按图片随机划分,训练集和验证集会出现数据泄漏,导致验证精度虚高,部署到现场却表现拉胯。按批次拆分能让模型面对的是“没见过的钢材表面”,更贴近真实推理场景。

数据增强方面,我不仅用了Yolov5自带的Mosaic、HSV扰动、随机翻转,还特意加了轻微的高斯模糊和随机灰度变化。原因前面说了,钢表面图像存在纹理干扰,而灰度变化能模拟不同光照条件下的成像差异,高斯模糊能模拟运动模糊——这些都会在真实产线上出现。

3. Yolov5训练配置与参数调优

3.1 模型选型与网络结构分析

Yolov5提供了n、s、m、l、x五个尺寸的模型。钢材缺陷检测我最终选了Yolov5m作为主力配置,没有直接上l或x,原因是产线部署的工控机算力有限,跑大模型延迟扛不住。但yolov5s在部分小缺陷类别上的召回率又偏低,所以m是一个相对平衡的选择。

一个值得注意的差异是:Yolov5的Backbone用的是CSPNet结构,Neck部分用了PANet做多尺度特征融合,输出端是三个不同尺度的检测头。钢材缺陷的尺寸跨度非常大——氧化皮可能占据画面1/3的区域,而细小划痕可能只有几十个像素宽。这三个检测头分别负责大中小目标的检测,正好覆盖这种尺寸跨度,这也是目标检测模型相比图像分类模型更适合这个场景的根本原因。

如果你用的是Yolov8甚至Yolov10,它们的Backbone换成了C2f结构,在同等算力下特征提取能力更强一些,这些差异在后面的对比测试中会有体现。

3.2 训练超参数设置与Loss曲线分析

先看一组我实际跑通的训练参数配置:

# train_config.yaml train: dataset/train.txt val: dataset/val.txt nc: 5 depth_multiple: 0.67 width_multiple: 0.75 epochs: 200 batch_size: 16 imgsz: 640 optimizer: SGD lr0: 0.01 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3.0 cos_lr: True

这里有几个参数背后是有讲究的。imgsz我选了640而没有选1280,是因为模型需要跑实时检测。钢材表面缺陷里的细小划痕,用640分辨率确实可能漏检,但提升到1280后推理时间直接翻倍,产线节拍不允许。折中方案是训练时用640,推理时再用测试时增强(TTA)来弥补小目标漏检,但这个后面再说。

学习率策略选了余弦退火,配合前3个epoch的warmup。warmup的作用是让模型在前几百个step内用小学习率稳定下来,防止初始阶段梯度震荡太大。我试过不开warmup直接硬训,前10个epoch的loss会上下剧烈跳动,最终收敛精度也略差。

Loss曲线的判断在有缺陷检测场景里有个额外的坑:由于正负样本极端不平衡——大部分区域都是背景,少数区域才有缺陷——模型的box_loss和cls_loss在刚开始训练时会显得非常平缓,这是正常的。需要重点观察的是val/box_loss和val/cls_loss是否在持续下降,而不是盯着train loss曲线看。

3.3 类别不平衡问题的处理

钢材缺陷数据的类别不平衡问题前面提过,实际操作中我用了两种手段结合:

第一种是简单的样本重加权。对样本量小的类别(比如边裂、夹杂),在loss计算时乘以一个权重系数,让模型更重视这些样本的学习。Yolov5本身没有直接开放这个参数,需要小改一下loss计算部分的代码,实现思路是给每个类别的cls loss单独乘一个权重。

第二种是数据增强层面做针对性的样本扩充。对小样本类别做复制粘贴增强——把小缺陷的实例抠出来,随机粘贴到其他钢材表面图的安全位置。这里有个注意点:粘贴的位置要避开原始标注框区域,否则会造成标注重叠。

最终结果是样本量最小的类别,mAP@0.5也能到0.85以上,虽然相比头部类别的0.97还是有差距,但至少达到了产线可用的标准。

4. Yolov7、Yolov8、Yolov10的对比实验与选型建议

4.1 四代模型的网络结构演进与推理性能实测

把Yolov5到Yolov10放在一起做横向对比,是我这个项目里最有意思的部分。我用了完全相同的数据集、相同的训练轮数和相同的输入尺寸,来控制变量,保证对比结果有意义。

先看四代模型在同等条件下的推理性能和精度实测数据:

模型版本参数量(M)输入尺寸单张推理耗时(ms)mAP@0.5mAP@0.5:0.95
Yolov5m21.26409.80.9540.712
Yolov736.964012.50.9610.735
Yolov8m25.96408.70.9590.728
Yolov10m24.46407.90.9520.719

这张表有一个挺有意思的结论:精度最高的其实是Yolov7,但速度最慢,参数量也最大。Yolov8和Yolov10在精度上和Yolov5m基本持平,但推理速度有约10%到20%的提升。这背后是架构演进带来的红利——Yolov8用了C2f模块替代CSP结构,在同等参数下梯度流更丰富;Yolov10最大的变化则是去掉了NMS后处理,把非极大值抑制直接融入了训练过程,这省掉的几毫秒在实际推理中非常可观。

还有一个细节容易被忽略:Yolov10的端到端特性意味着部署时不需要在工程代码里写NMS逻辑,代码更简洁、出错概率也更低。但在精度上限上,它并没有明显超越Yolov8,如果只看准确率,Yolov10没有绝对优势。

4.2 各版本在不同缺陷类别上的优劣势对比

全局mAP只能反映整体水平,我把模型按缺陷类别拆开对比时发现了一些有意思的现象。

对于大尺寸缺陷比如氧化皮和夹杂,四个模型的表现非常接近,mAP都在0.97以上,几乎没有区分度。但在细小划痕和麻点这类小目标上差异就出来了:Yolov8的小目标召回率比Yolov5提升了约2.3个百分点,Yolov10在这个指标上又比Yolov8略低一点。这让我怀疑Yolov10在优化推理速度时,对小目标的检测能力有一些回退。

Yolov7在几乎所有类别上的精度都是最高的,尤其是裂纹类缺陷的mAP比Yolov5高出约4个百分点。但它的推理速度劣势在实时场景中又是硬伤。实际生产中如果对延迟要求极高且算力充足,选Yolov8m最合适;如果精度优先且产线节拍不紧张,Yolov7也值得考虑。

4.3 我的选型结论与理由

经过完整对比后,最终部署到产线的方案是Yolov5m加上TensorRT FP16量化。这个选择乍一看似乎没跟上新版本的节奏,但理由很实际:

第一,Yolov5的部署工具链最完善。ONNX导出、TensorRT转换、C++推理接口的参考资料最多,遇到问题大概率能找到现成的解决方案。Yolov8和Yolov10的部署生态这几年也在完善,但某些算子在某些推理引擎上仍然存在兼容性问题。

第二,生产环境的稳定性预期最重要。Yolov5经过长时间大规模验证,行为可预期,对工业项目这种“需要长期稳定运行”的要求来说,新版本引入的架构改动反而可能是风险源。

第三,在钢材缺陷这个场景下,Yolov5m的检测精度已经达到产线验收标准。在模型能力够用的情况下,换个模型并不会带来明显的业务价值增量。这不是说新版本不好,而是项目选型要综合考虑业务需求、部署成本和维护成本。

5. 部署推理与工程化落地的关键细节

5.1 ONNX导出与推理优化

模型训练完只是第一步,真正要上产线还需要完成转换和部署。我用的是ONNX Runtime作为推理后端,之前的损失函数和训练逻辑都兼容,导出时基本没有遇到算子兼容性问题。

导出ONNX的命令是标准的:

python export.py --weights best.pt --img 640 --batch 1 --simplify

这里有个老生常谈但值得强调的坑:导出时必须用--simplify参数对计算图做简化。我一开始没开这个参数,导出的ONNX模型里包含一些冗余的reshape和transpose节点,导致推理速度比PyTorch端还慢。开完simplify之后,ONNX Runtime的推理时间立刻降到了接近PyTorch的1.2倍。

另一个关键是输入输出的动态维度问题。产线推理时图片分辨率是固定的640x640,所以导出时直接固定shape,不要开动态维度。动态维度会让推理引擎做额外优化空间的考虑,固定shape后TensorRT还能利用半精度和内存复用进一步提速。

5.2 量化部署与端侧性能验证

FP16量化在几组测试里表现非常稳定,几乎不掉点。INT8量化则有风险——钢材表面缺陷的灰度纹理本身比较细腻,INT8量化后部分细小的划痕和麻点检测会被直接跳过。我在测试集上对比过,INT8量化的mAP下降了约6个百分点,个别小目标类别的召回率下降了15个百分点。

为了兼顾速度和精度,最终方案是TensorRT FP16推理,配合多线程流水线处理。具体来说,相机采集线程、预处理线程、推理线程、结果上报线程四个线程之间用无锁队列衔接,把单张图像的总处理时间从原始的18ms压到了11ms左右。

这里额外分享一个经验:工业现场的光照环境和训练数据的光照条件很可能不一致。如果直接上线,模型性能大概率会缩水。稳妥的做法是在产线上提前采集一批覆盖不同光照条件和不同钢种表面的测试图,先在本地做一轮针对性的验证,观察模型在新分布上的表现再决定是否直接部署。

5.3 部署架构与工控机配置

工控机的配置选择和检测节拍直接相关。我用的是入门级GPU,显存6GB,训练只用在服务器上,部署端的显存压力在图像预处理和推理这两个环节。640x640的输入,FP16推理,单个模型占用的显存大约在1.5GB到2GB之间,这个配置足够同时挂载两个模型做冗余切换。

在软件架构上,我用了两种方案做冗余:模型A/B切换和降级策略。平时默认跑Yolov5m(FP16),当检测置信度持续偏低或者推理耗时异常增加时,自动切换备用模型。同时保留一个低配的Yolov5s作为终极兜底,哪怕工控机负载过高导致帧率下降,系统也能保证不丢帧。

6. 常见问题排查与避坑指南

6.1 漏检小缺陷怎么办

细小划痕和麻点的漏检,是钢材缺陷检测里最普遍也最棘手的问题。排查思路要按顺序来:

先看输入分辨率——如果推理尺寸被压到416或者更小,小缺陷的像素宽度可能只有几个像素,特征几乎被完全抹掉,这种漏检是必然的。把输入尺寸提升到640是底线,但代价是速度下降。

再看感受野覆盖——如果缺陷尺寸只有目标框的1/10,PANet结构在深层特征图上可能已经丢失了目标响应。可以尝试在Neck部分增加一层浅层feature map的融合,或者直接用带P2检测头的Yolov8变体。

最后才是考虑数据层面——小目标样本过少,可以通过切图训练的方式把小缺陷在大图里放大后再喂给模型。我之前用滑窗切图把一张1024x1024的钢板图切成四张512x512的图训练,小划痕的召回率有明显提升。

6.2 训练Loss不收敛的排查记录

钢材次表面纹理复杂,模型很容易在初始阶段分不清缺陷和纹理边界。如果遇到Loss不收敛,首先要确认数据集有没有明显标注噪声——标注框偏移、类别错误、漏标都直接导致模型学歪。

其次要关注学习率的设置。如果初始学习率设置过大,模型很容易在前期被错标样本带到沟里。我用warmup之后,配合余弦退火,明显能压住前期震荡。

最后就是数据不平衡问题了,小样本类别学不好也会反映在整体Loss曲线无法持续下降。针对性的加权策略比盲目调参有效得多。

6.3 部署后模型性能缩水的问题

训练阶段mAP挺好看,一部署到现场发现漏检多了,这是非常经典的问题。核心原因是数据分布漂移。产线实际图像的成像条件和训练数据来自实验环境不一致,目标表面状态也存在差异。

对策是:上线前先采集现场数据做小样本微调,或者收集线上低置信度的检测结果反哺训练集,形成闭环迭代。施工地场景尤其需要这样,因为产线在调试阶段现场光照和钢种更换频繁,模型也要随之适应。

另外一个容易踩的坑是图像格式的差异——相机输出的可能是BGR顺序或者YUV格式,如果在预处理代码里没转对,模型看到的颜色和训练时不一致,性能自然打折。

7. 项目经验总结与后续优化方向

做完整套项目,我个人最大的体感是:模型选型这件事,在精度达标之后,工程生态的成熟度往往比单一指标更重要。Yolov5的部署生态帮了大忙,遇到问题都有成熟的解决方案,而新版本模型虽然技术更先进,但部署链路相对复杂,在工业项目里需要权衡这个成本。

在数据环节多投入一些时间是完全值得的。我把大量精力花在数据清洗、类别平衡处理和针对性数据增强上,这些工作对最终精度的贡献不比换一个更大模型小。工业场景的数据质量问题,往往比模型结构问题更影响最终效果。

后续有几个方向可以继续扩展:

一是引入背景建模的思路,利用产线中连续帧的信息做时序增强。钢材缺陷在很多情况下并没有清晰的外观边界,但时序上的灰度突变往往更明显。引入video-level的信息可以显著降低检测器的误报率。

二是尝试基于Transformer的目标检测模型,端到端的架构在小目标和密集场景上理论上更有优势。不过这类模型的部署成本和推理速度放在产线上是否划算,需要再评估。

三是搭建自动化的数据闭环系统:线上检测结果定期回流到数据集,经过人工抽检确认后自动加入训练集,再触发新一轮模型训练和评估。这个闭环能让模型保持迭代,适应产线的动态变化。

如果你也要做类似的工业检测项目,我的建议很简单:先把数据基础打牢,再选一个生态成熟的模型跑通全链路,最后再根据实际瓶颈决定要不要升级模型版本。这条路走下来,投入产出比是最高的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询