布匹缺陷数据集实战:从VOC到YOLO格式转换与训练集划分指南
发布时间:2026/10/11 14:56:12 锦皓数字建站

简介布匹缺陷数据集面向纺织工业质检与计算机视觉方向的学习者和开发者用于训练和评估布匹表面缺陷的自动检测与分类模型。包内共934个文件以689张jpg缺陷图像和245个xml标注文件为主图像覆盖孔洞、色差、污渍、线条、起球、皱褶、接缝不良等多种缺陷类型xml文件提供对应的目标框与类别标注压缩包整体约927.33MB可直接用于目标检测或分类任务的训练、验证与测试划分。目前已有858人学习下载。借助这份数据读者能够实践图像预处理、CNN特征提取、迁移学习与数据增强等完整流程并针对工业质检场景调试模型泛化能力为智能制造中的自动化缺陷检测提供可复用的数据基础与实验参考。1. 布匹缺陷数据集到底能解决什么从验布工的眼睛到模型的输入做纺织质检的兄弟大概率都经历过这个场景产线上验布机跑得飞快人眼盯着布面看半小时就花漏检率直线上升。想上深度学习做缺陷检测第一步就卡住了——没有标注好的数据。公开数据集里找布匹缺陷翻来覆去就那么几个类别少、样本偏、格式还不统一。布匹缺陷数据集-dataset.rar这个标题背后指向的就是这类打包好的图像数据集合通常包含若干类常见布面瑕疵的图片和对应标注文件。它能帮你跳过最耗时的原始采集和粗标阶段直接进入模型训练和调参环节。适合两类人一是刚接手纺织质检项目、需要快速搭出 baseline 的算法工程师二是想验证某个检测方案在真实工业纹理上到底行不行的技术负责人。但数据集不是万能药拿到手之后怎么拆、怎么转、怎么划分才是决定项目能不能落地的关键。2. 拿到压缩包先别急着解压布匹缺陷数据集的目录结构与标注格式拆解2.1 常见的三种目录组织方式布匹缺陷数据集从来源上大致分三种打包习惯。第一种是按缺陷类别分文件夹每个文件夹里放该类别的原图标注信息单独放在一个 CSV 或 JSON 里记录文件名和边界框坐标。第二种是 VOC 风格每张图对应一个同名的 XML 文件里面写死了object的类别和bndbox坐标。第三种是 YOLO 风格图片放一个目录标签放另一个目录每张图对应一个.txt每行是class_id x_center y_center width height全部归一化到 0 到 1 之间。你拿到dataset.rar之后先别解压到桌面。我一般会先看一眼压缩包内的文件列表用命令行就能干# 列出压缩包内容不实际解压先看目录结构 unrar l dataset.rar | head -50 # 如果是 zip 格式 unzip -l dataset.zip | head -50这一步的目的是确认三件事有没有标注文件、标注文件和图片是不是一一对应、类别名是中文还是英文。很多翻车现场就是解压完才发现标注文件是空的或者类别名写的是“破洞”“跳线”这种中文后面训练时还得手动映射成数字。2.2 标注格式的快速校验脚本假设解压后是 VOC 格式图片在JPEGImages标注在Annotations。写个脚本快速统计类别分布和标注完整性import os import xml.etree.ElementTree as ET from collections import Counter ann_dir Annotations img_dir JPEGImages # 统计类别和缺失标注的图片 class_counter Counter() missing_ann [] for img_name in os.listdir(img_dir): base os.path.splitext(img_name)[0] xml_path os.path.join(ann_dir, base .xml) if not os.path.exists(xml_path): missing_ann.append(img_name) continue tree ET.parse(xml_path) root tree.getroot() for obj in root.findall(object): cls_name obj.find(name).text class_counter[cls_name] 1 print(类别分布:, class_counter) print(缺失标注的图片数:, len(missing_ann))这段代码的逻辑很直接遍历图片目录找同名 XML解析出每个object的name字段做计数。参数上唯一要注意的是ann_dir和img_dir的路径要跟实际解压后的目录对齐。跑完之后你会得到两个关键信息类别是否均衡、有没有图片漏标。如果某个类别只有几十张后面训练时就得考虑过采样或者数据增强。缺失标注的图片要么补标要么直接剔除别留着让训练脚本报错。2.3 类别名映射与标签清洗布匹缺陷的类别命名往往很随意同一个“破洞”可能写成hole、pothole、破洞。训练之前必须统一成英文小写加下划线并且固定一个class_id映射表。常见做法是建一个classes.txt每行一个类别名行号就是class_id。然后写个转换脚本把所有标注里的类别名替换成对应的 ID。这一步不做后面评估时混淆矩阵都没法看。提示如果数据集里同时存在 VOC 和 YOLO 两种格式的标注优先用 VOC 转 YOLO因为 VOC 的坐标是绝对像素值转换时只需要除以宽高不容易出错。3. 从 VOC 到 YOLO布匹缺陷数据集的格式转换与训练集划分实操3.1 VOC 转 YOLO 的完整脚本与四个边界坑VOC 的bndbox给的是xmin, ymin, xmax, ymaxYOLO 要的是归一化的中心点和宽高。转换公式不复杂但边界处理容易翻车。下面这个脚本我用了很多次直接抄import os import xml.etree.ElementTree as ET classes [hole, stain, broken_yarn, oil, crease] # 按你的 classes.txt 顺序 ann_dir Annotations img_dir JPEGImages out_label_dir labels os.makedirs(out_label_dir, exist_okTrue) for xml_file in os.listdir(ann_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(ann_dir, xml_file)) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) base os.path.splitext(xml_file)[0] lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name not in classes: continue cls_id classes.index(cls_name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 边界裁剪防止坐标越界 xmin max(0, min(xmin, img_w - 1)) ymin max(0, min(ymin, img_h - 1)) xmax max(0, min(xmax, img_w - 1)) ymax max(0, min(ymax, img_h - 1)) if xmax xmin or ymax ymin: continue # 跳过无效框 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) if lines: with open(os.path.join(out_label_dir, base .txt), w) as f: f.write(\n.join(lines))逻辑说明先读 XML 里的size拿到原图宽高再遍历每个object把类别名映射成 ID坐标做边界裁剪后归一化。四个边界坑分别是坐标超出图片范围、xmax小于xmin、类别名不在预设列表里、图片没有对应标注。前两个直接裁剪或跳过第三个用continue忽略第四个会导致该图没有标签文件训练时如果按图片路径找标签会报错所以划分数据集时要过滤掉。3.2 训练集、验证集、测试集的划分比例与随机种子布匹缺陷数据集的样本量通常不大几千张算多的。划分比例我一般用 7:2:1如果样本少于 1000 张就用 8:1:1保证训练集够用。划分时一定要固定随机种子否则每次跑出来的评估结果没法对比。import os import random import shutil random.seed(42) # 固定种子保证可复现 img_dir JPEGImages label_dir labels out_dir dataset_split for split in [train, val, test]: os.makedirs(os.path.join(out_dir, images, split), exist_okTrue) os.makedirs(os.path.join(out_dir, labels, split), exist_okTrue) # 只保留有标签的图片 valid_imgs [] for img_name in os.listdir(img_dir): base os.path.splitext(img_name)[0] if os.path.exists(os.path.join(label_dir, base .txt)): valid_imgs.append(img_name) random.shuffle(valid_imgs) n len(valid_imgs) n_train int(n * 0.7) n_val int(n * 0.2) splits { train: valid_imgs[:n_train], val: valid_imgs[n_train:n_train n_val], test: valid_imgs[n_train n_val:] } for split, names in splits.items(): for name in names: base os.path.splitext(name)[0] shutil.copy(os.path.join(img_dir, name), os.path.join(out_dir, images, split, name)) shutil.copy(os.path.join(label_dir, base .txt), os.path.join(out_dir, labels, split, base .txt))参数说明random.seed(42)是习惯用法换成别的数字也行但一旦定了就别改。valid_imgs只收集有标签的图片避免训练时找不到标签。划分比例通过0.7和0.2控制剩下的0.1自动归测试集。跑完之后dataset_split目录就是可以直接喂给 YOLO 训练脚本的结构。3.3 用 YOLOv8 跑通第一个 baseline 的最小命令数据集划分好之后写一个data.yamlpath: ./dataset_split train: images/train val: images/val test: images/test nc: 5 names: [hole, stain, broken_yarn, oil, crease]然后一行命令启动训练yolo detect train datadata.yaml modelyolov8n.pt epochs100 imgsz640 batch16yolov8n.pt是最小的预训练权重适合先跑通流程。epochs100对布匹缺陷这种纹理细、缺陷小的场景通常够用如果验证集 loss 还在降就加到 200。imgsz640是默认输入尺寸布匹缺陷往往很小如果显存够可以提到 1024但训练时间会翻倍。batch16根据显存调8G 显存跑 640 大概能到 16跑 1024 就只能给 4。注意第一次跑不要直接上大模型先用yolov8n确认数据管道没问题再换yolov8m或yolov8l提精度。4. 布匹缺陷检测的避坑与排查标注、增强、评估里的血泪经验4.1 标注框贴边导致模型学不到完整缺陷现象训练 loss 正常下降但推理时缺陷稍微靠近布边就漏检。原因VOC 标注时标注员习惯把框贴着缺陷边缘画甚至切掉一部分模型学到的特征不完整。解决转换 YOLO 格式时把每个框向外扩 2 到 5 个像素或者用albumentations做随机裁剪增强时留出边界余量。我一般会在转换脚本里加一个pad参数默认扩 3 像素。4.2 类别不均衡导致小类别被模型忽略现象某个缺陷类别样本只有几十张训练完混淆矩阵里这一类几乎全错。原因损失函数被大类别主导小类别梯度被淹没。解决一是在data.yaml里给每个类别配权重YOLOv8 支持cls_weights参数二是对小类别做过采样复制图片时加随机旋转和亮度扰动三是用 focal loss 替换默认分类损失但 YOLOv8 改损失比较麻烦优先用前两种。4.3 数据增强把缺陷特征增强没了现象训练时加了随机裁剪和旋转验证集精度反而比不加还低。原因布匹缺陷很多是细长条状的跳线或小点状的破洞随机裁剪可能把缺陷裁掉一半旋转后纹理方向变了模型学到的特征和实际产线不一致。解决增强策略要克制。水平翻转和亮度对比度扰动可以加随机裁剪和大幅旋转慎用。如果要用裁剪设置最小裁剪比例不低于 0.8保证缺陷主体还在。4.4 验证集和测试集分布不一致导致评估虚高现象验证集 mAP 很高上线后漏检率却下不来。原因划分数据集时没有按产线批次或光照条件分层验证集恰好都是好检的样本。解决划分前先按图片的拍摄批次、光照强度、布匹颜色做分组每组按比例抽到训练集和验证集。如果数据集里没有这些元信息至少保证随机种子固定后人工抽查验证集里有没有明显偏简单的样本。4.5 图片格式和通道数不统一导致训练中断现象训练脚本报错RuntimeError: invalid argument 0: Sizes of tensors must match。原因数据集里混了灰度图和 RGB 图或者有 PNG 带透明通道。解决统一转成三通道 JPEG。用 PIL 批量处理from PIL import Image import os img_dir JPEGImages for name in os.listdir(img_dir): path os.path.join(img_dir, name) img Image.open(path).convert(RGB) img.save(path, JPEG)这段代码把灰度图和 RGBA 图都转成 RGB覆盖保存。跑之前备份原图避免转换失败把原图毁了。5. 把布匹缺陷数据集用出复利从单模型到产线级验证的进阶习惯数据集跑通一个 baseline 只是开始。我自己的习惯是每次训练完都把模型在测试集上的预测结果可视化出来一张一张看漏检和误检的案例。布匹缺陷有个特点误检往往集中在布面纹理复杂的地方比如提花面料的经纬交织点容易被当成破洞。这时候光看 mAP 没用得把误检样本单独拎出来分析是标注问题还是模型感受野不够。进阶做法是做一个简单的产线模拟验证。把测试集图片按产线速度合成一段视频用训练好的模型逐帧推理统计每米布料的漏检次数。这个指标比 mAP 更贴近实际。如果漏检集中在某几类缺陷就针对这几类补数据、调 anchor 尺寸或者加一个专门的分类头做二次确认。还有一个后悔药级别的习惯每次改数据集划分或增强策略都新建一个版本目录别覆盖旧的。我吃过亏有一次调完增强发现效果变差想回退却发现旧划分已经被覆盖了只能重跑一遍。现在我的目录结构是dataset_v1、dataset_v2每个版本里放对应的data.yaml和训练日志。这样对比实验才有意义。最后说一个验证技巧用yolo detect val跑完验证集后把conf阈值从 0.25 调到 0.5 再跑一次看 mAP 掉多少。如果掉得厉害说明模型对低置信度样本依赖太重产线上容易误检。我一般会把产线阈值定在 0.4 到 0.5 之间宁可漏检几个也别让验布机频繁停机。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。