YOLOv5钢材表面缺陷检测实战:从数据处理到模型部署全流程解析

📅 2026/8/27 1:44:43
YOLOv5钢材表面缺陷检测实战:从数据处理到模型部署全流程解析
简介在工业质检领域钢材表面缺陷识别长期依赖人工目检效率与稳定性难以兼顾。机器视觉与目标检测技术的成熟为产线自动化质检提供了新路径。YOLOv5作为单阶段检测模型的代表凭借其推理速度快、工程生态完善的特性成为工业视觉落地的热门选择。其基于CSPDarknet的特征提取结构与PANet多尺度融合机制能够有效平衡精度与实时性。通过NEU-DET公开数据集对裂纹、夹杂、斑块等六类典型缺陷进行模型训练与调优并配合数据增强、锚框优化及ONNX导出等手段可实现毫秒级推理的在线检测系统。该方案不仅适用于钢材产线亦可迁移至其他表面缺陷检测场景为智能制造的品质管控提供可靠技术支撑。本文围绕这套完整项目梳理从环境搭建、格式转换到参数调优的实操要点。 质量检测在制造业里一直是块硬骨头尤其是钢材这种连续生产线上的表面缺陷。传统人工目检容易疲劳漏检机器视觉加传统图像处理又对光照和环境变化过于敏感换个产线就要重新调参。用YOLOv5这类目标检测模型来做钢材表面缺陷识别属于目前工业视觉落地里性价比很高的方案——数据集相对成熟模型推理速度快单张图片在普通GPU上就能跑到毫秒级而且源码生态完善从训练到部署都有现成轮子。这个标题里的压缩包其实就是一套完整的“数据集训练代码检测系统”的组合适合刚接触工业视觉的算法工程师、相关专业的研究生以及想在产线上试点AI质检的自动化工程师参考。我拿到的这套项目核心内容是围绕NEU-DET这个公开的钢材表面缺陷数据集展开的六个典型缺陷类别裂纹、夹杂、斑块、麻点、氧化铁皮压入和划痕。整套系统把数据准备、模型训练、指标评估和推理检测串成了一条完整的链路。这篇文章我会按照实际做项目的顺序把从数据集处理到模型部署的完整过程拆开讲清楚包括环境搭建的坑、训练参数的调优思路、以及我在跑这个项目时踩过的几个典型问题。1. 项目整体设计与思路拆解1.1 为什么选YOLOv5做钢材缺陷检测钢材表面缺陷检测这个场景对模型有几个硬性要求第一是实时性产线传送带速度很快检测必须跟得上节奏第二是误检漏检率要低这直接影响出厂质量评级第三是模型要足够鲁棒产线光照变化、钢材表面反光、氧化皮颜色差异都是干扰因素。YOLOv5在这几个维度上表现比较均衡。相比Faster R-CNN这类两阶段检测器YOLOv5的单阶段架构天然在推理速度上有优势相比同系列更早的YOLOv3/YOLOv4YOLOv5在工程化方面做得更完善——数据增强策略内置了Mosaic和Copy-paste训练过程自动锚框计算导出ONNX/TensorRT也都有现成脚本这对工业落地非常友好。另一个很实际的原因是社区生态。YOLOv5的教程、预训练权重、部署方案在开源社区里非常丰富遇到问题基本都能搜到解决方案。对于工业项目来说可维护性和可复现性往往比模型精度指标更要紧。1.2 六个缺陷类别的定义与识别难点NEU-DET数据集包含六类典型缺陷每类大概300张图片总共1800张。我在标注和生产验证中对每个类别都做了细致分析缺陷类别英文标识形态特征识别难点裂纹Crazing网状细纹方向随机对比度低容易和背景纹理混淆夹杂Inclusion颗粒状异物颜色偏深目标小密集出现时容易漏检斑块Patches大面积不均匀区域边界模糊形状不规则与背景灰度接近麻点Pitted Surface点状凹坑呈簇状分布目标小且密边缘特征弱氧化铁皮压入Rolled-in Scale鳞片状颜色深浅不一与背景颜色相近标注难度大划痕Scratches细长线性纹路长宽比极端常规锚框难以匹配这六类缺陷里划痕和裂纹是最难处理的。划痕是典型的长条状目标长宽比可能达到10:1以上YOLO默认的锚框尺寸对这种极端形状不太友好需要额外调整。裂纹则是细线状纹理在低分辨率下很容易被下采样过程抹掉特征。1.3 系统的整体架构设计这套检测系统按功能划分为四个模块数据处理模块负责把原始图片和标注文件转换为YOLO格式并完成训练集/验证集划分模型训练模块封装了YOLOv5的训练入口和超参数配置评估模块输出mAP、精确率、召回率等核心指标并生成混淆矩阵推理检测模块支持单张图片、视频流和批量文件夹三种输入方式。这种模块划分方式在实际项目中很实用。数据、训练、评估、推理四个环节解耦之后无论是调试单独某个环节还是后续替换更先进的模型架构都只需要改动对应模块无需重构整个系统。2. 核心内容拆解与实操要点2.1 数据集的下载与标注格式转换NEU-DET数据集的原始标注格式是VOC格式的XML文件而YOLOv5训练需要的是TXT格式的归一化坐标标注。这一步格式转换是很多新手第一个卡住的地方其实逻辑很简单VOC格式存的是目标框的左上角和右下角绝对像素坐标YOLO格式存的是中心点坐标和宽高占图片宽高的比例。转换脚本的核心逻辑如下import xml.etree.ElementTree as ET import os def convert_voc_to_yolo(xml_path, out_dir, class_names): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size).find(width).text) img_h int(root.find(size).find(height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_names: continue cls_id class_names.index(cls_name) box obj.find(bndbox) x_min float(box.find(xmin).text) y_min float(box.find(ymin).text) x_max float(box.find(xmax).text) y_max float(box.find(ymax).text) # 转换成YOLO格式 x_center (x_min x_max) / 2 / img_w y_center (y_min y_max) / 2 / img_h w (x_max - x_min) / img_w h (y_max - y_min) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) xml_name os.path.basename(xml_path).replace(.xml, .txt) with open(os.path.join(out_dir, xml_name), w) as f: f.write(\n.join(lines))这里要注意一点NEU-DET原始图片是200x200像素的小图。这个分辨率对YOLOv5来说偏低因为模型的默认输入尺寸是640x640直接把小图放大到640会损失很多细节尤其是裂纹和划痕这类细线特征。后面我会细讲针对这个问题的处理方案。2.2 数据集划分与目录结构训练集、验证集、测试集的划分比例我建议用8:1:1。1800张图按这个比例划分训练集1440张验证集和测试集各180张。划分时要注意用随机打乱的方式避免同一生产批次或相近样本集中在某个集合里。YOLOv5的目录结构官方推荐如下datasets/ └── steel_defect/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/数据集准备好后还需要在项目里创建data.yaml配置文件train: datasets/steel_defect/images/train val: datasets/steel_defect/images/val test: datasets/steel_defect/images/test nc: 6 names: [crazing, inclusion, patches, pitted_surface, rolled-in_scale, scratches]2.3 模型配置文件调整YOLOv5的模型结构通过YAML文件定义。官方默认有n、s、m、l、x五个尺寸从n到x参数量和精度逐渐增大。对于钢材缺陷检测这个任务我的经验是从YOLOv5s开始如果精度不够再往上换。但在修改模型配置文件时有一个关键点很多人会忽略类别数。默认的coco.yaml里nc是80必须改成6。修改方法是直接编辑models/yolov5s.yaml把nc字段从80改成6。如果忘记改训练会在类别数不匹配的地方报错。YOLOv5s的模型结构主要由三部分组成CSPDarknet骨干网络负责提取特征PANet颈部负责多尺度特征融合YOLO检测头输出三个不同尺度上的预测结果。针对钢材缺陷小目标多、细长目标多的特点可以重点关注小尺度特征图上的输出。2.4 关键训练参数的选择与理解训练参数直接决定模型的收敛质量和最终效果。我常用的参数配置如下参数名推荐值说明img-size640输入图像尺寸小图需配合上采样策略batch-size16根据显存调整显存不够就降到8epochs100-200数据集小训练轮次可以适当增加lr00.01初始学习率可以用0.001更稳optimizerSGD小数据集上SGD比Adam更稳workers4-8数据加载线程数Windows下建议0patience50早停耐心值防止过拟合weightsyolov5s.pt预训练权重迁移学习的关键训练命令python train.py \ --data datasets/steel_defect/data.yaml \ --cfg models/yolov5s.yaml \ --weights yolov5s.pt \ --batch-size 16 \ --epochs 150 \ --img-size 640 \ --name steel_defect_run1这里用到预训练权重yolov5s.pt非常关键。官方在COCO数据集上预训练过的模型已经学习到了丰富的通用特征在小数据集上微调比从头训练收敛快得多精度也更高。我在测试中发现用预训练权重从零训练同样的epoch数下mAP能高出5-8个百分点。2.5 数据增强策略对缺陷检测的影响YOLOv5内置了丰富的数据增强策略包括Mosaic、Copy-paste、随机仿射变换、HSV色域变换、水平翻转等。默认配置对自然场景很有效但钢材缺陷有它的特殊性。Mosaic增强是YOLOv5的招牌策略把四张图拼成一张训练相当于扩大了batch size还能增加目标尺度的多样性。但钢材缺陷这种小图数据集Mosaic拼图时会进一步缩小每个目标的尺寸反而不利。实践中我把Mosaic关闭了改为使用RandomPerspective和HSV增强。HSV色域增强对钢材表面检测很有帮助。因为不同产线、不同批次的钢材表面颜色和光照差异很大。通过在HSV空间做随机扰动模型对这些颜色变化会更鲁棒。注意不要增强过度否则真实场景下会误检。# hyp.scratch-low.yaml 部分调整 mosaic: 0.0 # 关闭Mosaic mixup: 0.0 # 关闭Mixup hsv_h: 0.015 # 色调扰动 hsv_s: 0.7 # 饱和度扰动 hsv_v: 0.4 # 明度扰动 degrees: 10.0 # 小幅旋转 translate: 0.1 # 平移 scale: 0.5 # 缩放3. 实操过程与核心实现3.1 环境搭建与依赖安装YOLOv5的官方环境要求是Python 3.8和PyTorch 1.8。我实测下来PyTorch 2.0以上版本也完全兼容而且推理速度会快一些。建议用conda创建独立环境避免污染系统Pythonconda create -n yolov5 python3.9 conda activate yolov5 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118然后克隆YOLOv5仓库并安装依赖git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt这里有个容易踩的坑如果提示import torch失败先检查CUDA是否装好可以用python -c import torch; print(torch.cuda.is_available())验证。如果返回False说明PyTorch装的是CPU版本需要重新安装对应CUDA版本的PyTorch。3.2 小图高分辨率的处理策略前面提到NEU-DET原始图片只有200x200直接放大到640x640训练会损失细节。这个问题我当时纠结了很久测试了三种方案第一种方案是把图片放大到640输入再配合锐化滤波增强边缘。放大的方法建议用cv2.resize加上cv2.INTER_CUBIC插值比默认的线性插值在纹理保持上更好。第二种方案是把图片放大到416或480。这个思路是减少放大倍数保留更多原始信息代价是目标在图上占的面积比例更接近自然场景。我拿480测试过效果比640稍差一点但推理速度更快。第三种方案是用滑窗裁剪。把小图切成重叠的patch每个patch作为一个独立样本。这其实是工业场景常用的做法相当于用空间换精度。但训练和推理都要额外处理patch拼接逻辑工程复杂度上升。最终我选的是第一种方案并做了增强先把200x200放大到640x640然后在训练时用较小的min-iou锚框参数-1表示自动让模型更容易匹配小目标。如果你跑出来的模型对小目标漏检多可以试试把锚框的iou阈值调低到0.2python train.py \ --data datasets/steel_defect/data.yaml \ --cfg models/yolov5s.yaml \ --weights yolov5s.pt \ --batch-size 16 \ --epochs 150 \ --img-size 640 \ --anchor-min-iou 0.23.3 训练过程的监控与指标解读训练开始后终端会实时打印每个epoch的loss、精度、召回率和mAP指标。如果安装了wandb还可以网页端可视化管理训练曲线。重点要看的几个指标box_loss目标框回归损失反映框定位精度越低越好obj_loss目标置信度损失反映是否存在目标的判断能力cls_loss分类损失反映类别判断能力mAP0.5IoU阈值0.5时的平均精度均值工业界最看重的指标mAP0.5:0.95更严格的评估IoU从0.5到0.95取平均我跑完150个epoch后测试集上的结果大致在mAP0.50.75-0.82这个区间。不同类别的精度差异挺大其中划痕的AP相对较低原因和前面分析的一样细长目标对锚框和NMS都不太友好。3.4 模型评估与混淆矩阵分析训练结束后用val.py做模型评估会生成混淆矩阵、PR曲线、F1曲线等报告python val.py \ --data datasets/steel_defect/data.yaml \ --weights runs/train/steel_defect_run1/weights/best.pt \ --img-size 640 \ --conf-thres 0.25 \ --iou-thres 0.45混淆矩阵能直观反映哪些类别之间容易互相混淆。我跑出来的结果显示斑块和氧化铁皮压入之间存在一定的混淆因为两者都表现为大面积的灰度异常区域边界不明显。如果出现这种问题可以考虑在数据层面增加难例挖掘或者给易混淆类别单独调权重。3.5 推理检测与结果可视化训练好的模型可以直接用detect.py做推理python detect.py \ --weights runs/train/steel_defect_run1/weights/best.pt \ --source datasets/steel_defect/images/test \ --img-size 640 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --save-txt \ --save-conf推理结果默认保存在runs/detect/exp目录下。加上--save-txt可以把检测框坐标保存成TXT文件方便后续自动化流程读取。--save-conf会顺便保存置信度分数。如果想把模型集成到自己的Web系统或上位机程序里推荐用YOLOv5的detect.py做原型但正式环境建议直接用PyTorch的torch.hub加载权重import torch model torch.hub.load(ultralytics/yolov5, custom, pathruns/train/steel_defect_run1/weights/best.pt) model.conf 0.25 model.iou 0.45 model.classes [0, 1, 2, 3, 4, 5] results model(钢铁表面图片.jpg) results.show() results.print()3.6 导出为ONNX加速推理工业部署场景下很多环境没有PyTorch或者需要在边缘设备上跑推理。这时候把模型导出为ONNX格式就很有必要了python export.py \ --weights runs/train/steel_defect_run1/weights/best.pt \ --img-size 640 \ --batch-size 1 \ --include onnxONNX模型可以用ONNX Runtime或者OpenVINO加载推理也可以进一步转成TensorRT的engine模型在NVIDIA GPU上获得数倍加速。我实测在Jetson设备上TensorRT优化后的推理速度能达到毫秒级完全满足产线实时性要求。4. 常见问题与排查技巧实录4.1 类别不平衡导致部分缺陷检测效果差NEU-DET数据集中六类缺陷各300张图类别数量基本平衡。但每个类别内部的目标数量和大小差异很大有些图只有一个大目标有些图有几十个小目标。这会导致模型对多目标小尺寸的类别如麻点、夹杂学习不充分。解决思路有两个一是用YOLOv5的类别权重功能在train.py里通过--cls参数设置类别损失权重给样本少的类别更高的权重二是做数据增强时增加复制粘贴策略把目标数少的类别复制到其它图中人为增加该类目标的出现频率。4.2 训练时loss不下降或直接爆掉这种情况我遇到过一次原因是学习率设置过高。YOLOv5默认初始学习率0.01在小数据集上有时不够稳。如果loss曲线是横向震荡或直接NAN先把学习率降到0.001然后观察前10个epoch的loss变化。另外确认数据标注格式是否正确尤其是坐标归一化后是否有值超过0-1范围。4.3 检测时漏检或误检率偏高漏检和误检是工业质检项目里最头疼的两个问题几乎不可能一次性调好。漏检主要发生在小目标和对比度低的缺陷上对策是降低置信度阈值、调整锚框、增加小目标样本。误检则往往是因为背景复杂模型把钢材表面的纹路误判为缺陷对策是增加难负样本、提高置信度阈值、做消融分析。我给一个经验值如果检测场景对误检容忍度低把conf-thres设到0.35-0.45如果对漏检容忍度低把conf-thres设到0.15-0.25。实际阈值需要用一批真实生产样本做验证集来标定不要直接套默认值。4.4 Windows环境下训练速度慢的问题Windows下训练YOLOv5经常比Linux慢一大截主要原因是DataLoader的多线程支持问题。workers参数在Windows下如果设置过大反而会因为进程调度开销导致速度下降建议直接设为0。另外建议开启--cache参数把数据提前缓存到内存中减少磁盘I/O等待。python train.py \ --data datasets/steel_defect/data.yaml \ --cfg models/yolov5s.yaml \ --weights yolov5s.pt \ --batch-size 16 \ --epochs 150 \ --img-size 640 \ --workers 0 \ --cache4.5 细长目标漏检的针对性优化划痕这类细长目标YOLOv5默认的锚框很难匹配。我在实际调优中用了两个有效手段第一个是调低NMS的IoU阈值。默认0.45对密集细长目标偏严会抑制相邻的检测框可以调到0.3左右。这个可以在val.py和detect.py中用--iou-thres参数调整。第二个是修改模型配置文件中的锚框。YOLOv5支持--anchor-gen给自定义数据集重新计算锚框所以训练前可以加这个参数让模型自动适配数据python train.py \ --data datasets/steel_defect/data.yaml \ --cfg models/yolov5s.yaml \ --weights yolov5s.pt \ --batch-size 16 \ --epochs 150 \ --img-size 640 \ --anchor-gen4.6 模型过拟合的处理数据集只有1440张训练图模型很容易过拟合。判断标准是训练集loss持续下降但验证集mAP不再提升甚至下降。处理方法优先级从高到低早停法patience参数数据增强更强一些特别是HSV扰动和翻转用正则化更强的SGD配合weight_decay0.0005减小模型复杂度从YOLOv5s降到YOLOv5n最后才考虑用更多数据。我个人在实际跑这个项目时最深的体会是工业检测项目数据质量比模型结构重要得多。YOLOv5作为基线模型已经足够强了很多时候精度上不去问题不在模型而在数据的标注一致性、场景覆盖度、难例样本的丰富度上。如果你也想做类似的项目建议先把手里的缺陷图片整理透彻把每类缺陷的形态变化都覆盖到再去调模型和参数这条路会顺很多。从这套源码出发后续还可以往几个方向扩展一是部署到边缘计算设备用TensorRT或OpenVINO做推理加速接入产线实时视频流二是用YOLOv5的模型蒸馏或剪枝能力压缩模型体积放进更小的嵌入式设备三是把检测结果和生产管理系统打通自动统计缺陷率并生成报表。这些扩展都有现成的开源方案可以组合难度是逐步递增的但底子就是这套训练检测系统本身。本文还有配套的精品资源点击获取