ARTICLE DETAIL

资讯详情

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

YOLOv5钢材表面缺陷检测:权重数据集与复现路径详解

YOLOv5钢材表面缺陷检测:权重数据集与复现路径详解 简介面向工业质检与计算机视觉开发者这是一套基于YOLOv5的钢材表面缺陷检测完整资源覆盖从模型训练到效果评估的闭环流程。包内已包含训练好的缺陷检测权重并附有PR曲线、loss曲线等训练过程文件可用于直接推理或继续调优同时提供经LabelImg标注的钢材缺陷数据集图片为JPG格式XML与TXT两种标签分别存放于不同文件夹便于接入常见训练框架。资源包共164个文件以Python脚本、YAML配置、PyTorch权重、标注文件及训练日志等类型为主整体大小约106.77MB。目前已有2275人学习下载适合需要快速落地钢材表面缺陷检测项目或希望研究YOLOv5训练流程的工程师与学生。1. YOLOv5钢材缺陷检测权重、数据集与复现路径一次给齐钢材表面的划伤、麻点、氧化铁皮这类缺陷传统视觉方案要用几十个算子和阈值来回调换一卷钢、换一个光照角度就失效维护成本极高。我拆的这份YOLOv5钢材缺陷检测资源把训练好的缺陷检测权重、labelimg标注好的数据集、完整训练曲线和日志一次打包属于典型的拿过来就能跑的项目。它适合三类人刚接触目标检测、想用现成数据跑通YOLOv5全流程的新手做工业质检、需要快速验证缺陷检测可行性的一线工程师以及想研究PR曲线、loss曲线和权重筛选方法的人。整份资源基于YOLOv5-6.0数据集图片为jpg格式标签同时提供xml和txt两种分别存放在两个文件夹中训练好的权重配合推理脚本直接出检测框。复现路径是完整的环境配置、权重推理、数据组织、训练复现、踩坑排查每一环都有对应的文件支撑不是那种只有一个权重文件、连怎么跑都说不清的半成品。下面按我实操的顺序拆开讲。2. 选型与数据准备六类缺陷标签与xml/txt双格式的对应关系2.1 为什么是YOLOv5钢材缺陷场景的选型权衡钢材表面缺陷检测在产线上是个典型的小目标、低对比度、实时性要求高场景。缺陷区域在整幅图像里占比往往很小裂纹和划伤这类缺陷细长且对比度低光照变化又大。传统方案靠阈值分割加形态学处理换一个产线、换一个光源角度就要重新调参而且很难覆盖所有缺陷形态。基于深度学习的检测器把特征提取交给卷积网络权重由数据训练而来换场景只需要补充数据重新训练这是它替代传统视觉的根本原因。在检测器选型上这份资源选用YOLOv5-6.0而不是Faster R-CNN或更早的YOLOv3核心原因是工程生态成熟。YOLOv5从5.0版本开始把Mosaic数据增强、自适应anchor计算、CIoU loss这些训练技巧默认集成开箱即用程度远高于v3。6.0版本又完善了AutoAnchor、多尺度训练和NMS后处理对钢材这种小缺陷的召回率有明显帮助。部署侧的优势更明显导出onnx、TensorRT都有现成脚本后接工控机推理不会卡在格式转换上。它的权衡也很现实YOLOv5是anchor-based的单阶段检测器对密集重叠的小缺陷定位精度理论上不如Faster R-CNN这类两阶段方案但推理速度快一个数量级。钢材质检是实时场景一秒钟要处理多帧图像YOLOv5在速度与精度之间的平衡点最合适。这份资源里权重已经训练好说明作者在二者取舍上已经调过一轮拿到手可以直接做验证。钢材表面缺陷公开数据集里最常用的是NEU-DET的六类划分这份资源的标签也符合这个习惯类别id类别名缺陷特征0crazing细裂纹网状分布对比度低1inclusion夹杂颗粒边界不规则2patches斑块状异常区域3pitted_surface麻点小面积点状凹陷4rolled-in_scale氧化铁皮压入块状暗色区域5scratches划伤线性长条类别id的排序就是训练yaml里names字段的顺序这个顺序一旦定下来整个项目里都不能变后面标注新数据、转换格式、推理可视化都要依赖它。2.2 数据集结构与xml/txt双标签换算拆开数据集图片是jpg格式标签分两个文件夹存放。xml是labelimg默认导出的Pascal VOC格式记录类别名和矩形框的绝对像素坐标txt是YOLO训练直接读取的格式每行一个目标格式为类别id 中心点x 中心点y 宽 高后四个值全部归一化到[0,1]。两份标签描述的是同一批标注框只是坐标系表达不同。典型的xml标签长这样annotation foldersteel_defect/folder filenameNEU-001.jpg/filename size width200/width height200/height depth3/depth /size object namescratches/name bndbox xmin23/xmin ymin41/ymin xmax178/xmax ymax189/ymax /bndbox /object /annotationxml里记录的是绝对像素坐标xmin/ymin是左上角xmax/ymax是右下角。对应到txt就是0 0.5025 0.5750 0.7750 0.7400一行一个目标第一个数字是类别id后面四个数字由xml坐标换算而来换算公式为center_x (xmin xmax) / 2 / width center_y (ymin ymax) / 2 / height box_w (xmax - xmin) / width box_h (ymax - ymin) / height所以xml转txt不是简单替换文件名后缀必须除以图像宽高做归一化。我一般写批量转换脚本逻辑是遍历xml、解析bndbox、按公式计算、写出txt。注意YOLO的txt要求坐标必须在[0,1]区间如果标注框超出图像边界算出的值会大于1训练时YOLOv5会直接忽略这个框这类脏数据要提前清掉。注意xml转txt脚本的类别映射表必须和训练yaml里的names顺序完全一致否则会出现模型学的是类别A推理时框上却写着类别B的错位问题。2.3 labelimg标注新数据的边界行为要扩充数据集还是用labelimg它默认导出xml需要再转txt。标注时有几个细节直接影响训练效果我踩过不止一次。第一labelimg的predefined_classes.txt里类别列表决定下拉菜单顺序但不会自动决定txt里的类别id。txt的id是在转换脚本里按names顺序映射的所以这个文件和训练yaml里的names顺序必须保持一致否则容易标错类别。第二钢材缺陷的边界很多是渐变的比如氧化铁皮和正常表面没有清晰分界线。标注时尽量贴着肉眼可见的缺陷边缘框不要为了把缺陷整个包住而把框放大很多。框里背景占比过高模型会把背景特征也学进去推理时误检率明显上升。第三xml和txt必须一一对应。漏转一张图训练时YOLOv5会直接跳过看着不报错实际有效样本变少了PR曲线整体偏低。我转换完会做一次校验对比两个文件夹的文件名集合确保每个xml都有对应txt每个jpg都有对应标签这一步能省掉后面大量排错时间。3. 环境搭建与推理复现从依赖安装到检测框输出3.1 conda环境与YOLOv5依赖安装YOLOv5-6.0的依赖不复杂核心是PyTorch、torchvision、opencv-python、numpy、matplotlib外加pyyaml、pandas、seaborn、tqdm这些工具包。建议用conda建独立环境避免污染系统Python。常见做法是Python选3.8PyTorch按显卡驱动来CUDA 11.x配torch 1.10左右这是6.0时代官方验证过的组合。conda create -n yolov5-steel python3.8 conda activate yolov5-steel pip install torch1.10.0 torchvision0.11.0 --index-url https://download.pytorch.org/whl/cu113 pip install -r requirements.txtrequirements.txt是YOLOv5-6.0仓库自带的列好了opencv-python、scipy、pyyaml、matplotlib、tqdm、requests、pandas、seaborn等依赖。安装后先验证环境python -c import torch; print(torch.__version__, torch.cuda.is_available())打印出版本号和True说明环境正常。注意torchvision版本必须和torch匹配装错最常见的报错是import torchvision时出现undefined symbol或者直接段错误。如果机器没有NVIDIA GPU把torch换成cpu版也能跑只是训练速度会慢很多推理验证倒还够用。显存方面推理8G够用训练建议至少8G且batch-size不能大这个后面避坑章节专门展开。3.2 用训练好的权重执行推理环境就绪后把权重文件放到yolov5-6.0目录下命名为best.pt然后跑detect.py。YOLOv5的推理入口核心参数就这几个python detect.py --weights best.pt --source ./test_images --img 640 --conf-thres 0.25 --iou-thres 0.45 --device 0参数取值作用--weightsbest.pt指定权重文件路径--source图片/文件夹/视频推理输入来源--img640输入尺寸缩放后送入网络--conf-thres0.25置信度阈值低于该值的框被丢弃--iou-thres0.45NMS合并重叠框的IoU阈值--device0GPU编号CPU推理写cpu这里解释一下两个阈值的作用conf-thres控制这个框里到底有没有目标设太低会冒出一堆误检框设太高会漏掉置信度偏低的真缺陷iou-thres控制NMS阶段重叠框的合并力度设太低同一个缺陷被多个框重复框住设太高相邻的两个缺陷可能被合并成一个。钢材缺陷检测我一般把conf-thres设在0.25到0.3iou-thres保持0.45。推理结果默认保存到runs/detect/exp目录每张图生成带标注框的jpg控制台同时打印每个框的类别、置信度和坐标。权重文件有三个常见版本要区分best.pt是验证集上mAP最高的权重推理优先用这个last.pt是训练最后一轮的权重不一定最优但有时泛化性反而比best好因为best可能对验证集过拟合如果出现.engine或.onnx后缀的文件那是部署格式不能在detect.py里直接跑。3.3 tutorial.ipynb里的加载与可视化流程这份资源带了一个tutorial.ipynb用jupyter notebook把加载权重、读图、推理、可视化整条链路串了起来。它把模型推理的中间环节展示出来对理解anchor和NMS后处理有直观帮助。notebook里典型的加载方式是torch.hubimport torch model torch.hub.load(ultralytics/yolov5, custom, pathbest.pt, force_reloadTrue) model.conf 0.25 model.iou 0.45 img test_images/NEU-001.jpg results model(img) results.print() results.show()这里有个坑torch.hub.load会从github拉取YOLOv5仓库代码机器访问github不稳定时加载会卡住看起来像是死机。我一般绕过hub方式直接用仓库里的attempt_load函数import sys sys.path.insert(0, ./yolov5-6.0) from models.experimental import attempt_load model attempt_load(best.pt, map_locationcpu) model.conf 0.25 model.iou 0.45attempt_load是YOLOv5官方权重加载函数支持cpu和gpu不依赖在线拉取离线环境也能跑。model.conf和model.iou是给模型设置后处理阈值效果和detect.py命令行参数一致。notebook里还会用matplotlib把原图和预测框叠加显示。如果看到检测框位置正确但置信度偏低比如都在0.3到0.5之间说明模型对这个缺陷类型学得不充分正确做法是补充该类型数据继续训练而不是盲目调低conf-thres调低了会带来大量误检。4. 训练流程复现数据划分、超参数与曲线判读4.1 目录重排与data yaml配置要复现训练第一步是把数据集组织成YOLOv5要求的目录结构再写data yaml。YOLOv5的规范是images和labels两个顶层文件夹各自下面分train和val子集。这份资源的原始标签按xml和txt分两个文件夹存放jpg在另一个位置需要先重排steel_dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── steel.yaml重排逻辑把所有jpg按比例划分到images/train和images/val比如8:2再把对应txt按相同比例划分到labels/train和labels/val。划分脚本用随机数给每张图打标再移动文件import os, random, shutil jpg_files [f for f in os.listdir(images_all) if f.endswith(.jpg)] random.seed(42) random.shuffle(jpg_files) split int(len(jpg_files) * 0.8) for i, f in enumerate(jpg_files): sub train if i split else val shutil.copy(os.path.join(images_all, f), os.path.join(images, sub, f)) txt f.replace(.jpg, .txt) if os.path.exists(os.path.join(labels_all, txt)): shutil.copy(os.path.join(labels_all, txt), os.path.join(labels, sub, txt))random.seed(42)保证划分结果可复现这一点很重要否则每次划分不同训练结果没有可比性。划分后要检查验证集里每个类别都有样本钢材缺陷中patches和scratches样本数往往偏多crazing偏少如果验证集恰好没有crazingmAP会虚高换到真实场景立刻露馅。steel.yaml的内容是关键path: ./steel_dataset train: images/train val: images/val nc: 6 names: [crazing, inclusion, patches, pitted_surface, rolled-in_scale, scratches]path是数据集根目录train和val是相对path的路径nc是类别数names的顺序就是类别id的映射顺序。这个顺序必须和训练权重时一致否则换权重推理时类别名会错位。我见过有人把names改成中文训练没问题但detect.py输出和保存结果时遇到中文偶尔出现编码错误建议保持英文名界面显示层再做映射。4.2 训练命令与超参数调整数据准备好之后训练命令如下python train.py --data steel.yaml --weights yolov5s.pt --img 640 --batch-size 16 --epochs 100 --device 0 --project runs/train-steel --name exp1--weights yolov5s.pt表示用COCO预训练的yolov5s作为初始权重这叫迁移学习比从零训练收敛快很多100个epoch基本能复现原资源里权重的精度。--batch-size受显存限制16对应8G显存OOM就降到8或4同时配合--workers 4降低数据加载压力。--img 640是输入尺寸钢材缺陷如果是小缺陷可以试试1280但显存占用翻倍、速度也慢。几个容易被忽略的参数--patience是早停参数默认100验证集指标连续多轮不提升就停止训练防止过拟合。--cache可以在内存充足时把图片缓存进内存加速训练。--multi-scale开启多尺度训练对提升小缺陷检测鲁棒性有帮助训练时间增加约30%。YOLOv5的超参数文件是data/hyp.scratch.yaml包含lr0初始学习率0.01、momentum动量0.937、weight_decay权重衰减0.0005和各类loss权重。对钢材这种背景单一、目标集中的数据集我一般不动学习率只把mixup调低或关掉。钢材缺陷特征本来就清晰mixup把两张图混合反而引入背景噪声。调试超参数的原则是一次只改一个改完跑几十个epoch看loss趋势不要一次改三个出问题都不知道是哪个改坏的。4.3 PR曲线、loss曲线的判读方法训练结束后runs/train-steel/exp1目录下会生成results.csv、PR曲线、confusion matrix、labels分布图等。这份资源里已经带了一套训练好的曲线和events.out.tfevents日志events文件是TensorBoard的训练记录可以用tensorboard --logdirruns/train-steel/exp1打开和results.csv数据互补。曲线判读是判断模型质量的基本功。PR曲线横轴是recall纵轴是precision曲线下面积就是AP。六个类别各有一条曲线曲线越靠近右上角该类别检测越可靠。钢材缺陷里通常scratches和inclusion的AP最高因为边界清晰、样本量大crazing的AP最低因为裂纹细长、对比度低且样本少。如果某条PR曲线明显凹陷说明该类别查全率或查准率有问题要针对性补数据而不是全局调阈值。loss曲线看三个box_loss定位损失、obj_loss置信度损失、cls_loss分类损失。正常情况是前10个epoch快速下降之后缓慢下降并趋于平稳。box_loss在训练后期反弹上升说明学习率太大或过拟合三个loss都降不下去一直走平大概率是标签和图像没对齐模型在学错误的标注。labels分布图也要看它展示每个类别在训练集里的目标数量。如果某个类别目标数只有几十个而其他类别几千个这个类别的AP基本不可能高。这时候要么补充该类数据要么用数据增强里专门针对少样本的策略比如对少样本类别做随机crop增强。5. 避坑排查显存、标签对齐与Docker的五个典型问题5.1 推理或训练时CUDA out of memory现象跑detect.py或者train.py程序刚开始就报CUDA out of memory后面跟一串显存地址训练根本起不来。原因最常见的是batch-size设置过大显卡显存本来就不足。其次是权重加载默认在GPU上运行如果机器上同时开了多个python进程每个进程都占显存。还有可能是notebook里多次执行推理之前的张量没释放累积占满显存。解决先看显存占用nvidia-smi确认没有别的进程占用后训练把batch-size从16降到8或4推理确认--device 0且没有其他进程。如果还不行设置环境变量限制显存分配粒度export PYTORCH_CUDA_ALLOC_CONFmax_split_size_mb:128这个变量能减少显存碎片化代价是分配效率略有下降。如果显存只有4G建议直接用CPU推理虽然慢但不会崩工业现场验证阶段完全够用。5.2 xml和txt标签数量对不上现象训练时YOLOv5不报错但训练日志里显示的图片数比数据集图片数少。检查发现xml有500个txt只有475个缺了25张图的标签。原因labelimg标注时可能有图片没保存标签就跳过了转换脚本遇到空标签文件或坐标异常的xml会跳过还有一个隐蔽原因xml里box坐标出现xmin xmax这类颠倒情况转换脚本通常直接报错或跳过导致对应txt缺失。解决写校验脚本遍历两个文件夹找出差异import os xml_dir labels_xml txt_dir labels_txt xml_files {f.replace(.xml, ) for f in os.listdir(xml_dir) if f.endswith(.xml)} txt_files {f.replace(.txt, ) for f in os.listdir(txt_dir) if f.endswith(.txt)} print(缺少txt:, xml_files - txt_files) print(缺少xml:, txt_files - xml_files)把差集里的图片重新走一遍xml转txt或者重新标注。我习惯在转换脚本里加坐标合法性检查xmin xmax且ymin ymax才写入从源头杜绝脏数据进入训练集。5.3 PR曲线mAP异常低但loss正常现象训练loss曲线正常下降但mAP0.5只有0.2左右远低于正常水平。肉眼查看检测结果发现很多缺陷没框出来。原因最常见两个一是类别id映射错位二是训练集和验证集划分后类别分布极不均匀。id错位意味着训练时第一个类别是crazing模型学到的特征和验证集上标注的对应关系对不上训练不报错mAP计算时却全部错位。解决先检查data yaml里的names顺序和xml转txt时的类别映射表逐一对比。再检查划分后的验证集确保每个类别都有样本。最有效的排查方式是把验证集图片和预测框画出来用眼睛看python detect.py --weights best.pt --source val_images --save-txt --save-conf如果检测框位置正确但类别名完全不对就是id映射问题如果检测框数量明显偏少就是conf-thres设置太高或数据分布问题。这一步花时间最多但定位问题也最准。5.4 Docker构建或启动失败现象这份资源带Dockerfile直接docker build卡在pip install步骤或者构建成功后docker run启动报错。原因YOLOv5-6.0的Dockerfile通常基于pytorch/pytorch基础镜像依赖安装要拉大量包网络不稳定会超时。启动报错则多半是容器内没有GPU直通宿主机没装nvidia-docker或者run时没加--gpus参数。解决构建时给docker配镜像加速源或者分步构建先把基础依赖装好再装YOLOv5依赖。运行时必须加GPU参数docker run --gpus all -it --ipchost --shm-size8g yolov5-steel-image--ipchost和--shm-size是PyTorch DataLoader在容器内正常运行的关键不加会报共享内存不足严重时训练直接卡死。现场机器没有GPU就别在Docker里折腾直接conda环境跑Docker方案更适合部署阶段。5.5 中文路径导致数据读取失败现象数据集放在D:/钢材缺陷检测/数据集这种带中文的目录下训练时opencv读图报错或者matplotlib画图时字体乱码、路径找不到。原因opencv的imread函数对中文路径支持不好很多版本直接返回NoneYOLOv5的LoadImages在读取时会把这类图片跳过训练集实际少了一批数据。Python在Windows下对中文路径也有编码兼容性问题。解决把数据集和项目路径全部改成英文D:/steel_defect/dataset这是最省事的做法。如果数据集已标注完不想挪位置可以用np.fromfile配合cv2.imdecode绕过编码问题import cv2 import numpy as np img cv2.imdecode(np.fromfile(钢材缺陷检测/数据集/001.jpg, dtypenp.uint8), cv2.IMREAD_COLOR)imdecode配合fromfile能读中文路径但写入结果时如果路径带中文cv2.imwrite同样会失败还得用tofile。所以结论还是项目路径用英文最省事别在这个问题上浪费时间。6. 用results.csv做收敛验证比看曲线更可靠的习惯6.1 从csv提取关键指标做趋势判断results.csv是训练过程最完整的数据记录每一行对应一个epoch包含box_loss、obj_loss、cls_loss、precision、recall、mAP0.5、mAP0.5:0.95这些字段。我有个习惯训练完第一件事不是看曲线图而是用pandas把csv读进来算最后20个epoch的均值和标准差import pandas as pd df pd.read_csv(runs/train-steel/exp1/results.csv) tail df.tail(20) print(tail[[mAP0.5, precision, recall]].describe())mAP0.5均值在0.85以上、标准差小于0.02说明训练收敛稳定权重可以直接用于推理。标准差大于0.05说明验证集上表现忽高忽低常见原因是验证集样本太少或类别分布不均这时要按类别拆开看AP找出拖后腿的类别。csv的优势是能精确量化抖动幅度曲线图只能看出大概趋势。6.2 best.pt与last.pt交叉验证另一个习惯是用best.pt和last.pt做交叉推理选权重不能只看best的mAP数字python detect.py --weights best.pt --source val_images --conf-thres 0.25 python detect.py --weights last.pt --source val_images --conf-thres 0.25对比两个目录下的检测结果。best.pt在验证集上mAP更高但偶尔对某些特定角度、特定光照下的缺陷漏检last.pt有时反而在这些边界case上表现更好这是验证集过拟合的典型信号。处理办法是把两个权重的检测结果叠加在验证集上做一次人工评判留下实际效果更好的那个。还有一个让缺陷检测更稳的小技巧推理时把输入尺寸从640提到768或896。钢材缺陷细长裂纹和划伤在640输入下可能只占十几个像素特征提取不充分。提升输入尺寸后小缺陷特征更明显代价是推理速度下降约30%产线帧率要求不高时这个交换很划算。我经历过一次best.pt比last.pt高3个点、但现场测试时漏检率反而更高的翻车从那以后每次训练完都强制走一遍双权重对比不再只信mAP数字而是在验证集上把两个权重的检测结果逐张过一遍。这份资源把数据集、权重、训练曲线放到了一起省掉了最耗时的数据准备和训练等待阶段拿到手先按第3章把推理跑通确认权重可信再按第4章复现训练最后用这一章的方法验证收敛性。希望帮到你。本文还有配套的精品资源点击获取
返回列表