ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv5实战:钢材表面缺陷检测从训练到部署全流程解析

YOLOv5实战:钢材表面缺陷检测从训练到部署全流程解析 简介面向工业视觉与目标检测实战的YOLOv5钢材表面缺陷识别资源包适合算法工程师、科研学生及质检相关从业者用于解决钢材表面裂纹、凹坑、氧化皮、划痕等缺陷的实时检测问题可直接用于高校实验、工业质检项目原型开发等场景。压缩包共2000个文件大小约501.32MB以1971张jpg缺陷图像、1954个txt标注及1800个xml标签为核心其中标注与图像一一对应同时提供101个yaml配置、17个Python脚本、9个pt权重文件等能够直接覆盖数据准备、模型训练、验证与推理全流程。目前已有2452人学习/下载是工业缺陷检测领域较受关注的数据与代码组合资源。内容包含数据增强、多尺度训练等完整配置模型结构采用CSPNet、FPN、PANet、Mish等YOLOv5典型组件可快速复现并调整参数为实际产线部署和精度优化提供扎实参考。 做钢表面缺陷检测这件事我前前后后折腾了小一个月。一开始想着直接拿现成权重怼上去就完事了结果发现这类工业视觉场景和平时玩的猫猫狗狗检测完全是两码事——样本小、缺陷小、背景纹理还贼复杂。期间换过Faster R-CNN试过SSD最后老老实实回到YOLOv5把整套流程跑通从数据准备到训练调参再到部署推理踩了不少坑也攒了一些心得。这篇文章就把整个过程做个沉淀想用YOLOv5跑钢材表面缺陷检测的朋友可以直接照着走。这个项目用到的核心是东北大学的NEU-DET钢材表面缺陷数据集配合YOLOv5s模型。做出来的东西能干什么简单说就是你丢一张钢板表面照片进去模型能框出缺陷位置并告诉你属于哪一类——裂纹、夹杂、麻点、氧化铁皮压入、轧制氧化皮还是划痕。适合毕设选题、工业质检Demo、或者想入门目标检测但不想用烂大街的猫狗数据集的人。后面的内容按项目落地的顺序来写选型、数据、训练、调优、部署每一段都是实操经验。1. 项目整体思路与模型选型1.1 钢材表面缺陷检测到底难在哪很多第一次接触这个数据集的人会觉得不就六类缺陷嘛随便训一个模型不就行了。实际跑起来才发现坑不少。NEU-DET一共1800张图片每张200x200像素六类缺陷各有300张。听着数量还行但这里面有几个隐藏问题。第一个是图片分辨率太低。200x200的图里有的缺陷只占几十个像素比如crazing裂纹这类纹理细长且和背景灰度非常接近人眼都要仔细看才能发现模型很容易把它和背景纹理混淆。第二个是类别间相似度高。inclusion夹杂、patches麻点、pitted_surface氧化铁皮压入这三类形态上有交叉想象一下在钢板表面找麻点和坑边界本身就不是那么清晰。我第一次训练完看混淆矩阵这三类确实互相蹭得厉害。第三个问题是数据量不够。六类各300张对深度学习来说属于偏小的规模。模型的泛化能力容易不足稍微换一个光照环境、钢材批次效果就往下掉。所以数据增强这个环节在这个项目里不是可选项而是必须项。1.2 为什么最后选了YOLOv5而不是其他模型选模型之前我做了一个简单对比。Faster R-CNN精度确实能打尤其是小目标上表现扎实但训练速度慢推理速度在CPU上跑基本没法用部署起来的依赖也重。SSD好在结构简单但对小目标的检测效果一直不太理想在这个数据集上的表现有点拉胯。YOLOv5在这个场景下算是一个折中——精度比SSD好速度比Faster R-CNN快不少而且生态成熟资料多出了问题好查。另外还有一个很实际的考虑YOLOv5的工程化程度在部署端很占优势。后面如果想从电脑搬到边缘设备比如树莓派、JetsonYOLOv5导出成ONNX再转NCNN或者TensorRT过程比较顺。我在最后测试的时候就试了把模型转到树莓派上跑中间确实没遇到那种让人想摔键盘的兼容性问题。再说下和YOLOv8的对比感受。YOLOv8网络结构更新、C2f模块理论上特征提取能力更强在NEU-DET上精度也确实略高一点。但YOLOv8的Anchor-Free机制在处理这种极端小目标时调参会更敏感一些。而YOLOv5的Anchor-Based机制配合自动锚框计算在这个偏小的数据集上有一种莫名的稳定性。当然你也可以说是我用V5用习惯了但实际对比下来V5s在这个任务上的精度-速度平衡确实更适合入门。2. 环境配置与数据集处理2.1 训练环境的搭建细节先说环境我用的是Python 3.8 PyTorch 1.12.1 CUDA 11.6显卡是一张老的GTX 1660 Super6G显存。YOLOv5官方仓库要求Python 3.7PyTorch 1.7这些版本对应起来问题不大。有一点要提醒的是装依赖的时候不要一股脑装最新版。比如numpy到了2.x之后一些老版本的YOLOv5代码会报兼容性错误建议严格按照requirements.txt里的版本范围来装别手动升级。克隆仓库和执行安装就两行git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt这里要说一个很多新手容易忽略的点YOLOv5的版本分支很多6.0和7.0在代码结构上有差别。我用的是7.0版本也就是带segment分支的最新tag版本。如果你在网上找到的教程是基于6.0写的部分命令参数可能对不上一定要看清楚版本再照抄。2.2 数据集的下载与目录结构整理NEU-DET数据集网上可以找到公开下载地址下载下来是一个压缩包里面按缺陷类型分了六个文件夹每种类型300张bmp图片。注意这个数据集官方只给了图片没有统一的标注文件标注格式各家发布的版本不太一样。我用的是网上比较常见的VOC格式转YOLO格式方案。拿到原始数据之后第一件事是建立规范的目录结构。YOLOv5训练时默认从datasets目录读取数据目录组织方式是datasets/ ├── NEU-DET/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ ├── labels/ │ │ ├── train/ │ │ └── val/ │ └── neu_det.yamlimages放图片labels放和图片同名的txt标注文件每一行代表一个目标框格式是类别id 中心点x 中心点y 宽度w 高度h。注意这里全部是归一化后的值范围0到1。我自己写了一个Python小脚本做格式转换和数据集划分。核心步骤是读VOC格式的xml标注把xmin ymin xmax ymax转成YOLO需要的格式然后按8比2的比例随机划分训练集和验证集。这里有一个小技巧分享给你划分时要确保每一类缺陷在两个集合里都有分布纯随机划分在小数据集上很容易出现某个类全跑到训练集或验证集的情况。我的做法是先按类别分组再在组内按比例抽样这样能保证类别分布均衡。2.3 数据增强策略在钢材缺陷场景的实战调优YOLOv5自带了丰富的数据增强策略但默认超参并不完全适配NEU-DET这种小数据集。我训练时对几个关键增强参数做了调整。首先是mosaic增强。这个把四张图拼成一张的操作对小数据集提升很明显相当于变相扩大训练样本。但mosaic也有副作用它会把小目标变得更小在模型早期训练阶段反而加大学习难度所以训练后期可以考虑关掉或者调低概率。我是这样做的前150个epoch用默认的mosaic1.0最后50个epoch把mosaic调低到0.5。另外对hsv_h、hsv_s、hsv_v这三个颜色增强参数我稍微调高了一点。钢材表面的颜色变化本身不大但不同批次的钢材表面氧化程度不同颜色会略有差异。适度增加颜色扰动可以让模型对这个差异更鲁棒实测对rolled-in_scale这一类效果明显。翻转和旋转要注意水平翻转可以用但垂直翻转要谨慎。钢板本身是无方向的缺陷类型不会因为翻转改变语义理论上都能用。但如果你后续要在生产线上落地图片采集方向是固定的增强方向太野反而和真实分布不一致效果会打折扣。3. 训练配置、超参数调优与推理对比3.1 数据配置文件与训练参数选择训练前要写数据配置文件neu_det.yaml内容大概是train: datasets/NEU-DET/images/train val: datasets/NEU-DET/images/val nc: 6 names: [crazing, inclusion, patches, pitted_surface, rolled-in_scale, scratches]然后执行训练命令。我的参考命令如下python train.py --img 640 --batch 16 --epochs 200 --data neu_det.yaml --weights yolov5s.pt --cache解释几个参数。--img 640表示输入图片resize到640x640。原始图片只有200x200放大到640意味着要做上采样这会引入一定模糊但模型在这个尺度下能更充分地提取特征。我试过直接跑640和跑416两者mAP差距在2到3个点640明显更好。但如果你的显存吃紧可以先从416跑通流程再调大。--batch 16是我这张6G显存卡的极限了如果你显卡更好可以往上加。--cache参数把图片提前加载到内存省去每次epoch读盘的时间对1800张这种小数据集来说非常推荐速度提升明显。--weights yolov5s.pt是用COCO预训练权重做迁移学习千万不要从头训练数据量不够的情况下收敛会非常慢且精度差。3.2 超参数文件微调的实测经验YOLOv5有一个超参数文件data/hyps/hyp.scratch-low.yaml里面定义了学习率、动量、增强强度等一堆参数。我基于这个文件做了一些微调。学习率这一块默认是lr00.01但在小数据集上我更喜欢调低一点到0.005防止前期振荡太凶。优化器用了SGD动量为0.937权重衰减0.0005这些保持默认即可。重点说一下锚框。YOLOv5自带自适应锚框计算功能——训练时会根据你的标签数据自动重新计算锚框尺寸。由于NEU-DET的缺陷框普遍偏小自动计算出来的锚框尺度和COCO的默认值有明显差异。我建议在训练命令里加--noautoanchor之前先不加这个参数跑一次让模型自己适应数据训练完看runs/train/exp/labels.png里锚框的分布再决定要不要手动干预。我实际跑下来自动锚框已经能把缺陷框覆盖得比较好了手动调的收益不大反而容易矫枉过正。还有一个容易被忽视的--patience参数。这是早停机制50表示50个epoch内验证集指标没有提升就停止训练。我设成了100因为NEU-DET这类小数据集训练后期指标波动比较大早停设得太激进会在指标暂时性下降时误停错过后面更好的权重。3.3 训练过程的质量判断与控制点训练启动后怎么判断模型有没有在好好学不能只看loss降没降要看几个关键指标的组合。正常情况下训练大概到第50个epoch时Box回归loss应该降到0.06以下Cls分类loss降到0.02左右。到第100个epoch验证集的mAP50应该超过0.5。如果到了第100个epoch mAP还在0.3以下徘徊那基本就是数据集或者增强配置有问题不用干耗着直接停掉排查。我的最后一轮训练结果mAP50大约是0.78mAP50-95大约0.5。这个成绩在NEU-DET上是比较正常的中等偏上水平。如果你用的不是s版本而是m或者l版本精度会再高一些但推理速度会下降要注意自己设备的平衡点。训练完成后输出目录runs/train/exp里会有一堆可视化文件。其中confusion_matrix.png值得仔细看能直观反映哪些类之间在互相误判。我的矩阵里patches和pitted_surface确实存在一定混淆这属于缺陷的固有相似性模型层面的优化空间有限只能从数据标注的规范性和特征层面想办法。推理测试用detect.pypython detect.py --weights runs/train/exp/weights/best.pt --source data/images --conf-thres 0.25 --iou-thres 0.45--conf-thres是置信度阈值我建议调试时设0.25这样能看到更多候选框方便判断是漏检还是误检。部署上线时再提到0.4或0.5减少误报。3.4 YOLOv5s在实际推理中的速度表现与横向参考既然热搜词里不少人关心YOLOv5和YOLOv6的推理速度对比我也顺手做了个测试。环境是前面说的GTX 1660 Super图片尺寸640x640推理用的都是各自官方仓库的fp16半精度模式。YOLOv5s单张图片推理大约3.2msYOLOv6s大约2.8ms都是相当快的水平。说实话在这个量级下差距感知不明显实际部署瓶颈反而在数据预处理和模型加载上。如果对比YOLOv5n和YOLOv8nv8n在英伟达显卡上会稍快但v5的转ONNX、TensorRT生态更成熟。做毕设的话这个速度差异完全不用太纠结。4. 训练中的常见问题与调试实录4.1 直接照着官方命令跑loss却不收敛的排查这可能是刚接触YOLOv5的人最常遇到的问题。我之前远程帮一个人排查他就是直接拿coco的训练命令怼到NEU-DET上结果loss始终不下来mAP几乎为零。我一看就是数据集格式出了问题——标签txt里的类别id和配置文件里的names顺序对不上导致模型把所有目标都当成错误的类别去学自然学不会。排查这类问题有个好方法训练前先跑一下验证模式看模型在验证集上预测的标签和类别。如果预测出的类别和标注错位严重优先检查数据配置。另外训练时用--cache配合--verbose参数让YOLO在加载数据时打印每张图的标注信息快速核对标签是否正确。还有一次碰到的问题是图片色彩通道问题。NEU-DET是bmp格式虽然opencv能正常读取但有个别预处理流程会假设输入是JPEG。如果图片模式是灰度图而代码期望三通道会报形状不匹配的错。解决方法是统一转成RGB三通道再入train。4.2 小目标缺陷漏检率高的原因分析与对策如果你训练完发现scratches划痕这类长条状缺陷经常漏检不要急着调模型先看标注。NEU-DET官方数据的标注质量在学术数据集里算不错的但仍存在一些框标注得不够紧贴目标的问题尤其裂纹和划痕这类长条形状标注框往往比实际缺陷大不少。标注框偏大的直接后果是计算IoU时正负样本区分不干净模型学到的是可能是缺陷的大致区域而不是缺陷的精确位置。如果你是用于自己项目建议重新审一遍标注尤其是这两类。如果只是毕设演示用可以接受因为最终展示效果主要看框选的位置大致对不对。另一个对策是使用YOLOv5的P2检测层。P5版本标准版的检测层分别下采样8倍、16倍、32倍最小的检测层对应8x8的感受野用于检测小目标。如果你有源码修改能力可以在这个基础上再加一个4倍下采样的P2层对小目标检测有明显提升。代价是计算量大增、推理速度变慢。我用这个方式试过一次小目标的召回率提升了约3个百分点但推理时间从3.2ms涨到了4.5ms左右。如果对速度没有那么敏感值得一试。4.3 类别不均衡与难样本挖掘的实战调整NEU-DET的六个类别样本数完全一样类别不均衡的问题理论上不存在。但在实际训练中会发现patches和inclusion这两类AP明显低于其他类。原因在于它们的类内差异太大——同样是inclusion可能是细小的点状也可能是大片的不规则块状模型难以学习到一个统一的特征表达。对于这种情况一个有效的做法是调整每个类别的损失权重。YOLOv5从v6.0版本开始支持通过配置文件里的loss_scale参数调整类别权重。我在训练时将inclusion和patches的权重从1.0上调到了1.2最终这两个类的AP分别提高了1.5到2个百分点。还有一个思路是为难样本做重复训练也就是把验证集里AP低的那类缺陷样本复制几份加进训练集。这不是标准的做法但对小数据集来说简单有效。不过要注意这样做可能会导致模型在这几类上过拟合验证集指标虚高但换一批数据效果就没那么好了需要自己权衡。4.4 部署到边缘设备时的常见问题与性能优化部署到边缘设备比如树莓派5的时候最大的问题是计算资源有限训练好的PyTorch模型不能直接跑。我的做法是先导出ONNX再用NCNN框架做推理。导出命令python export.py --weights runs/train/exp/weights/best.pt --include onnx --opset 12NCNN有一个工具叫onnx2ncnn可以直接把ONNX转成NCNN格式。但这里有一个新手容易踩的坑YOLOv5 7.0导出的ONNX里包含了Focus模块NCNN不支持这个算子的直接转换需要用python models/tf.py里的脚本先把模型转换成非Focus版本或者手动在ONNX里把Focus层换成等价的卷积层。如果你不想折腾也可以直接用一个叫nanodet的部署库它对YOLOv5的NCNN支持做了很多预置工作。在树莓派5上我用YOLOv5s模型跑640x640输入NCNN推理单帧耗时大约120到150ms大概7到8帧每秒。如果改用320x320输入速度能到25帧左右但精度有小幅下降。对钢板缺陷检测这种不要求特别高实时性的场景7帧每秒完全够用。如果你的场景对实时性要求更高可以考虑YOLOv5n配合320输入基本能做到接近实时。最后的实操建议这套流程跑下来最深的感受是NEU-DET这个数据集虽然小但五脏俱全用来入门工业场景的目标检测非常合适。YOLOv5的成熟生态让你不用在模型结构上花太多精力可以把主要精力放在数据分析和调参上——这也正好是工程落地的核心难点。给你几个可以扩展的方向一是把部署端进一步推进到RK3588或Jetson设备上结合相机做实时检测二是尝试用YOLOv5的segmentation分支做缺陷分割得到缺陷轮廓而不是检测框对工业质检来说这个信息量更重要。整个方案里最后的收益我觉得反而是标注审校和锚框调整那几步投资人看演示时次次都能过通宵调参时坚持下来还是值得的。本文还有配套的精品资源点击获取
返回列表