
简介基于YOLOv5的布匹缺陷检测项目面向工业质检、计算机视觉学习者与算法竞赛选手提供了从官方数据集格式转换、滑动窗口切图到模型训练与检测推理的完整Python实现。压缩包内包含8个文件以6个Python脚本为主覆盖数据预处理、YOLO格式标注转换、训练与测试流程另有项目说明Markdown和任务示例Notebook便于理解源码结构和快速运行。包体仅25KB轻量精炼适合已有一定深度学习基础、希望参考工业检测落地思路的用户。当前已有363人学习浏览资源将官方广东赛题数据组织为code、train_data、models、weights等清晰目录并给出convertTrainLabel.py、process_data_yolo.py等关键脚本可直接复现布匹缺陷标注与训练流程帮助读者掌握YOLOv5在细粒度瑕疵识别中的工程化方法。1. 布匹缺陷检测难点与yolov5的选型理由产线上布匹以每分钟几十米的速度通过相机视野检测装置能在每个缺陷上停留的时间往往只有零点几秒。人工目检在这个节奏下漏检率超过 10% 并不罕见而布匹表面纹理的周期性又让传统视觉方案吃尽苦头——阈值分割会把纬线交织误判成污渍边缘检测面对褶皱和阴影时噪声大得没法看。这也是为什么基于深度学习的布匹缺陷检测算法能在近两年快速替换掉老一代机器视觉方案它不再靠人工设计特征而是直接从图像里学出“哪些纹理异常属于缺陷”。yolov5 在这个场景里是个务实的选择。它不像两阶段检测器那样慢精度又比早期单阶段模型稳部署生态在工控机和 Jetson 这类设备上已经非常成熟。拿到一份“python源码项目说明数据集.zip”的项目包实际上就是在围绕这四块工作环境搭建、数据准备、模型训练、验证部署。这篇文章就按这条路径把每一段会踩的坑和能用上的参数讲透新手能照步骤跑通熟手也能找到锚框设置、超参数调优和部署细节上的增量信息。2. 布匹缺陷检测为什么先跑通yolov5环境2.1 小目标与纹理背景决定了yolov5而不是yolov8布匹缺陷检测的难点不在“有没有缺陷”而在“缺陷太小且和背景太像”。一根断掉的纬纱在 640x640 的输入图上可能只占 10 个像素宽、几十个像素长和正常织纹混在一起。yolov5 的 PANet 结构对这类小目标比早期 YOLOv3 友好得多它把高层语义信息和底层纹理细节反复融合缺陷即使只占几个像素也能在特征图里留下响应。另一个关键机制是自适应锚框训练时 yolov5 会根据你的数据集自动重新聚类锚框尺寸而不是死守 COCO 的默认值。至于为什么不直接上 yolov8核心原因是部署半径。布匹缺陷检测的落地端通常是工控机甚至边缘盒子yolov5 的 ONNX 导出、TensorRT 加速、C 推理示例在社区里积累得最多遇到问题搜得到答案yolov8 某些新模块在这些老设备上的算子支持反而没那么全。模型大小对比上也说明问题s 版本只有 14 MB 左右在产线要求的实时性下性价比最高。在布匹数据上不同缺陷的长宽比差异很大锚框设置直接决定小目标召回率。做数据准备时可以先粗略统计一下缺陷类型典型长宽比对锚框的要求破洞接近 1:1小方形锚框污渍1:1 到 2:1中小尺寸锚框缺纬1:5 以上极扁长锚框褶皱3:1 到 5:1长条锚框如果某个类别的长宽比统计结果突变比如油渍全是圆形而缺纬全是细长条就把这些极端形状的量级信息记下来后面训练时关闭自动锚框或手动指定范围防止 autoanchor 把所有锚框都拉到中性尺寸。2.2 yolov5环境配置的最小命令与显卡选择拿到源码包后第一步不是改代码而是把依赖环境装到和作者一致的状态。yolov5 官方推荐 Python 3.8 到 3.10PyTorch 1.8 以上即可但不同版本之间算子实现有差异建议先按源码里的 requirements.txt 安装而不是自己拼版本。环境配置的完整流程通常是conda create -n fabric python3.8 -y conda activate fabric cd yolov5-master pip install -r requirements.txtrequirements.txt 里的核心依赖大致包括 torch、torchvision、opencv-python、numpy、matplotlib、pyyaml、tqdm、seaborn 等。安装时有一点容易忽略如果机器有 NVIDIA 显卡要在安装 torch 之前先确认 CUDA 版本用nvidia-smi看驱动支持的 CUDA 版本再到 PyTorch 官网选对应的安装命令否则 pip 默认装 CPU 版 torch训练速度差几十倍。没有独显的环境也能跑但 batch size 要压到 4 以下且一定要开--cache缓存数据否则 CPU 和磁盘会成为瓶颈。装完后用一条推理命令验证环境是否通python detect.py --weights yolov5s.pt --source ./test.jpg --conf-thres 0.25yolov5s.pt 如果本地没有会自动从 GitHub 下载跑通后会在runs/detect/exp下生成标注了检测框的结果图。这一步能确认 torch 版本、CUDA 可用性和 opencv 读取路径都没问题。如果报 CUDA 不可用检查torch.cuda.is_available()返回值而不是盲目重装整个环境。2.3 用预训练权重先看单张布匹图的检测效果很多人习惯直接拿自己的数据集开始训练但我建议先用 COCO 预训练权重跑几张布匹图哪怕检测结果全是错的也无所谓。目的有三个确认推理管线完整观察模型在纹理背景上会产生什么类型的误检为后面判断训练是否收敛留一个“差基线”。执行时注意--conf-thres不要设太高布匹缺陷普遍对比度低预训练模型给的置信度本来就不会高。python detect.py --weights yolov5s.pt --source ./fabric_samples/ --conf-thres 0.1 --save-txt加--save-txt后每张图的检测结果会以小写类别代号和归一化坐标写到runs/detect/exp/labels目录下。如果预训练模型在布匹图上除了误检什么都没有甚至误检框都没有属于正常现象——COCO 的类别里没有“破洞”和“缺纬”模型只能提取一些底层纹理特征。观察的是它把背景召回的程度误检框特别密集说明特征提取在周期性纹理上不稳定这对后续布匹缺陷检测算法调参有参考价值训练时数据增强就要侧重打破纹理周期。提示跑推理时如果 GPU 显存占用很高但帧率极低多半是显存里同时加载了多个 batch 或开了--augment调试阶段默认参数即可。3. 布匹缺陷数据集的标注、格式转换与增强3.1 缺陷类别划分与样本量策略布匹缺陷检测算法里数据准备比模型结构更决定上限。先定义类别常见的工业缺陷分类包括破洞、污渍、褶皱、缺纬、跳花、油渍等具体以项目说明文档里的标注规范为准。分类粒度会影响训练难度把“油渍”和“水渍”并成一类“污渍”模型更容易学分成多类则每类样本量被摊薄小样本类别容易欠拟合。我的建议是第一版训练控制在 4 到 8 类先保证每类的可区分性再考虑细分。样本量上有一个经验线每个类别至少 500 个标注实例且小目标相对原图面积小于 1%的占比不能太低。如果实际收集到的画面里大面积缺陷占多数训练出来的模型会对小缺陷不敏感。观察布匹数据集的常见做法是跑一轮统计脚本打印所有标注框的宽高分布和面积分布如果发现宽度小于 32 像素的框占比过低说明数据集存在明显的尺度偏差需要在增强阶段有意补充。import os import cv2 label_dir datasets/fabric/labels stats {small: 0, total: 0} for f in os.listdir(label_dir): if not f.endswith(.txt): continue img_path os.path.join(datasets/fabric/images, f.replace(.txt, .jpg)) h, w cv2.imread(img_path).shape[:2] with open(os.path.join(label_dir, f), r) as fp: for line in fp: _, cx, cy, bw, bh map(float, line.split()) box_w, box_h bw * w, bh * h stats[total] 1 if box_w * box_h w * h * 0.01: stats[small] 1 print(small ratio:, stats[small] / stats[total])这段脚本从 YOLO 格式的标签文件里读归一化坐标乘回原图宽高后计算标注框面积占比。小于 1% 的框计入小目标统计。如果 ratio 低于 0.3后面训练时要重点依赖 mosaic 和 copy-paste 增强来补偿小缺陷样本不足的问题。3.2 标注工具选型与XML转YOLO格式的Python转换脚本布匹图像标注最常见的工具是 LabelImg但它默认输出 PASCAL VOC 格式的 XML 文件而 yolov5 训练需要 YOLO 格式的 txt。虽然新版 LabelImg 可以直接切到 YOLO 模式但对小缺陷标注来说XML 格式更方便做跨工具迁移和后续检查代码里做一次统一转换也更可控。转换脚本是必须的工具链一部分import xml.etree.ElementTree as ET import os classes [hole, stain, fold, missing_weft] def convert(xml_path, out_dir): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): cls obj.find(name).text if cls not in classes: continue box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) cx (xmin xmax) / 2 / img_w cy (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{classes.index(cls)} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) out_name os.path.splitext(os.path.basename(xml_path))[0] .txt with open(os.path.join(out_dir, out_name), w) as fp: fp.write(\n.join(lines)) for f in os.listdir(annotations): if f.endswith(.xml): convert(os.path.join(annotations, f), labels)坐标必须除以整张图的宽高归一化而不是缩放到 640x640——yolov5 训练时内部会做 letterbox 缩放标签如果基于固定尺寸归一化会错位。保留 6 位小数是为了在 4000x3000 的大图上也不丢亚像素精度。转换完成后抽样打印几个 txt 文件检查坐标是否落在 0 到 1 区间小于 0 大于 1 一定是标注框越界或写错了分母。3.3 从自定义数据集到注册机制的data.yaml配置yolov5 使用 data.yaml 描述数据集路径和类别映射这个文件虽然短但路径写错是训练失败最常见的原因。一个可用的配置模板如下train: /data/fabric/train/images val: /data/fabric/val/images nc: 4 names: [hole, stain, fold, missing_weft]train 和 val 指向存放图片的目录yolov5 会自动在同级 paths 下找 labels 目录。所有训练图片和标注文件的文件名要一一对应且都在对应子目录里否则报 “image not found” 或标签缺失。names 的索引顺序必须和转换脚本里 classes 列表完全一致这一步错了模型会拿“破洞”的标签去学“污渍”的特征训练曲线还看不出异常。数据划分上按 9:1 切训练集和验证集并且要保证划分是按“布匹卷”而不是按“单张图”做的。同一卷布相邻位置的图像纹理高度相似如果它们同时出现在训练集和验证集里验证指标会虚高部署到新布种上立刻露馅。切分时直接按目录或文件名前缀分组。3.4 针对布匹纹理的增强组合亮度抖动、mosaic与小目标复制粘贴布匹检测场景里数据增强的核心目标是打破纹理周期性和模拟现场光照波动。yolov5 内置的 hyp 配置文件里默认开了 mosaic、flipr、hsv_h、hsv_s、hsv_v 等增强但对布匹来说默认亮度抖动幅度不够。现场产线的光源会因为电压波动和灯管老化出现缓慢变化建议把 hsv_v 从默认 0.4 往 0.5 到 0.6 调让模型见过更多明暗变化。yolov5超参数中的 mosaic 对布匹缺陷尤其重要。一个 batch 里拼接 4 张图等于把 4 个不同纹理区域的缺陷组合进同一张训练图模型被迫学会在纹理变化的背景下找缺陷而不是记住某块背景。对小目标可以再配合 copy-paste 增强从其他图里把标注好的缺陷裁剪下来随机贴到当前图上并同步生成新标签。这种方法对布匹缺陷检测算法特别有效因为织物纹理相对均匀贴入的缺陷在视觉上不突兀且能把稀缺的小缺陷样本复用几十次。hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.5 mosaic: 1.0 copy_paste: 0.3 fliplr: 0.5copy_paste 开启后训练时间会变长因为每次迭代都要做随机裁剪和粘贴的额外计算。显存紧张时优先保证 batch size 而不是增强强度batch 小到 4 以下时增强带来的随机性反而会把梯度方向搅乱。4. yolov5训练布匹缺陷模型的参数设置与调优4.1 模型配置文件里修改nc与depth_multiple训练自己的数据集时第一步要改的是models/yolov5s.yaml里的类别数。yolov5 6.0 之后把类别数从 data.yaml 挪到了模型文件里网上大量旧教程还停留在改 data.yaml 的 nc 字段照做会导致模型输出维度和标签维度对不上训练直接报维度错误。修改要点如下nc: 4 depth_multiple: 0.33 width_multiple: 0.50nc 改成自己的类别数。depth_multiple 和 width_multiple 控制网络深度和宽度0.33 和 0.50 对应的是 s 版本。如果显卡显存不紧张可以换models/yolov5m.yaml提高精度布匹缺陷检测里 m 版本比 s 版本通常能多出 2 到 3 个点的 mAP代价是推理时间增加约 40%。工控机上如果 deadline 紧优先考虑 s 版本加更好的数据增强来补精度。4.2 训练命令与关键参数说明配置完成后启动训练用下面这条命令作为起点python train.py --img 640 --batch 16 --epochs 200 --data fabric.yaml --weights yolov5s.pt --hyp hyp.scratch-low.yaml --cache-ram参数含义逐一说明--img 640是输入分辨率。布匹缺陷小理论上 1280 能保留更多细节但显存占用是平方级增长、推理速度也显著下降。我先用 640 训练一版看小目标表现如果缺纬这类细长缺陷召回不够再单独用 1280 微调而不是全程跑大图。--batch 16取决于显存8 GB 显存跑 s 版本 640 分辨率大约能支撑 16 到 24显存溢出时优先减 batch 而不是减分辨率。--epochs 200对缺陷检测足够数据量大或类别多就加到 300。--weights yolov5s.pt加载 COCO 预训练权重做迁移学习是收敛速度的关键除非要做对比实验否则不要用--weights 从头训练。--cache-ram把数据集一次性读入内存能极大减少磁盘 I/O 等待。训练日志里重点观察两个指标box_loss和cls_loss。如果 box_loss 持续下降但 cls_loss 在某个点后不再变化说明缺陷类别之间的可区分性不够可能是标注类别定义模糊或者背景干扰太强这时候加更多数据比加大模型更有效。4.3 hyp.scratch-low.yaml里值得手动改的超参数yolov5 的超参数配置里不是所有参数都需要动但有几个对布匹缺陷检测影响明显。打开data/hyps/hyp.scratch-low.yaml关注这几项参数作用布匹场景建议lr0初始学习率默认 0.01数据量少时降到 0.005lrf最终学习率系数保持默认 0.01warmup_epochs预热轮数3 到 5batch 小的时候用更大值mosaicmosaic 增强概率布匹纹理复杂或样本少时保持 1.0fliplr水平翻转左右镜像对大多数缺陷有效保持 0.5warmup 机制值得多说一句训练初期模型权重是随机的直接上大学习率会让梯度方向剧烈震荡前几个 epoch 先用小学习率“预热”等 loss 从初始值降下来再切到正常学习率。布匹数据集如果只有几百张图warmup_epochs 调到 5 以上能明显减少前 20 轮训练曲线的大幅抖动。4.4 autoanchor重算与训练中断恢复yolov5 会在训练开始时自动对数据集做 k-means 锚框聚类日志里会打印 AutoAnchor 相关的提示。内置的锚框面积是一组 9 个不同尺度的框如果聚类结果和默认值差异过大训练早期阶段的定位损失会偏高。我的做法是先跑 20 个 epoch从runs/train/exp下的anchors.png查看聚类分布如果大部分缺陷的长宽比集中在图的一角说明 anchor 初始化偏移了需要把自动计算出来的新锚框填入模型 yaml 并关闭 autoanchor 重训。转移学习时不要手动修改锚框让预训练阶段给够时间通常 100 轮后模型自己会适应。中断恢复用--resume runs/train/exp可以接着上次的权重和优化器状态继续训练epoch、学习率调度都会自动接上。布匹缺陷训练动辄十几个小时跑了一半断电是常事建议训练命令写进 shell 脚本里配合 nohup 或 tmux 运行避免终端意外关闭导致进程被杀。5. 布匹缺陷检测的mAP验证与部署技巧5.1 val.py验证与per-class AP分析训练结束后第一件事不是急着部署而是跑验证python val.py --weights runs/train/exp/weights/best.pt --data fabric.yaml --img 640 --conf-thres 0.001 --iou-thres 0.6验证集上输出的 mAP 指标里mAP0.5和mAP0.5:0.95的差距在布匹场景通常比通用目标检测大因为小缺陷在 IoU 阈值提高后边界稍微偏一点就判负。产线验收时如果允许单帧漏检再由后续帧补回我通常更看重 mAP0.5 和召回率而不是死磕 0.95。建议把验证输出里 per-class 的 AP 表拉出来看破洞 AP 低而污渍 AP 高时大概率是破洞样本尺度太小优化方向是提高输入分辨率或在增强阶段做针对性过采样而不是统一调置信度阈值。5.2 导出ONNX并搭一个最小Python推理接口部署第一步是导出与训练框架解耦的模型格式yolov5 对 ONNX 支持成熟python export.py --weights runs/train/exp/weights/best.pt --include onnx --opset 11用 ONNX Runtime 的好处是不依赖 PyTorch 环境现场只需要安装 onnxruntime 和 opencv。一个最小可用的推理脚本结构如下import cv2 import numpy as np import onnxruntime as ort session ort.InferenceSession(best.onnx) input_name session.get_inputs()[0].name def letterbox(img, size640): h, w img.shape[:2] r min(size / h, size / w) new_w, new_h int(w * r), int(h * r) resized cv2.resize(img, (new_w, new_h)) canvas np.full((size, size, 3), 114, dtypenp.uint8) x, y (size - new_w) // 2, (size - new_h) // 2 canvas[y:ynew_h, x:xnew_w] resized return canvas, r, x, y img cv2.imread(test.jpg) padded, r, x, y letterbox(img) blob padded[:, :, ::-1].transpose(2, 0, 1)[None].astype(np.float32) / 255.0 outputs session.run(None, {input_name: blob})[0]letterbox 预处理保持原始宽高比缩放多余部分用灰色填充这一步必须和训练时一致否则坐标映射会错位。yolov5 的 ONNX 输出形状是(1, 25200, 5nc)25200 是三个尺度特征图所有候选框的总数5 对应 cx、cy、w、h 和 objectness。后处理要做置信度阈值过滤和 NMS置信度可以按类别分别设置破洞这类小缺陷的分数普遍偏低conf_thres 给 0.15污渍相对好检测给 0.3统一阈值会漏掉前者或放大后者的误检。5.3 产线上值得用的三个部署技巧布匹检测部署和普通目标检测有个典型差异输入不是独立图片而是连续运行的视频流。利用这个时间连续性可以做帧间轨迹叠加——同一缺陷在连续多帧里位置连续变化单帧置信度略低于阈值的候选框如果前后帧在同一位置都出现了就认为它是真实缺陷反之单帧高置信度但前后帧消失的大概率是飞花或者反光噪声。这个策略能把漏检率再降一个档次比盲目调低阈值安全得多。第二个技巧是光照自适应。现场灯管老化、电压波动都会改变布面亮度训练时虽然做了亮度增强但极端情况下照度变化超过模型见过的范围。部署端可以在相机前加平场校正或按区域统计灰度均值并做线性调整把输入图的亮度分布拉回训练集的分布区间。第三个技巧是部署后用一段带标注的新产线数据做在线验证把不同时段的模型预测结果存成日志定期统计误检和漏检属于哪一类缺陷——决策要跟着数据走不要凭感觉调超参数。本文还有配套的精品资源点击获取