
简介面向针织品瑕疵检测的YOLOv9标注数据集专门为训练目标检测模型而整理适合计算机视觉工程师、算法研究人员及工业质检技术选型者使用可解决产线质检中标注样本缺失、模型难以收敛的问题。压缩包共105个文件包含52张jpg原图、52个配套txt标签文件以及1个yaml数据集配置标签按YOLOv9格式记录目标边框与类别yaml写明类别名称和数据集路径解压后即可集成到YOLOv9训练流程中。整个资源包仅5.37MB图像分辨率适合快速迭代实验能大幅降低数据准备成本。已有836人学习/下载该数据集可帮助用户快速验证瑕疵检测算法尤其适合在布料纹理、污渍、破损等复杂背景下开展模型迁移与调优。标注文件与图片一一对应目录层级简单用户只需修改路径参数即可开始训练省去重复标注时间便于专注模型结构与推理优化。1. 针织品瑕疵检测数据集这份 YOLOv9 标注包里到底装了什么做纺织质检的人都知道瑕疵样本靠肉眼一张张翻是最折磨人的事而更折磨的是翻完之后发现标注格式根本喂不进模型。这份针织品瑕疵检测数据集 zip 解压后是一套完整的 YOLOv9 训练包jpg 原图、labels 目录下的 txt 标注、加上一个 data.yaml 配置文件。文件名里密集出现的 .rf. 前缀说明它出自 Roboflow 导出流程坐标已经归一化过不需要再手工换算像素。适合三类人正在做布料 AOI 落地的工程师、拿瑕疵检测当课题的在校生、以及想验证 YOLOv9 在工业视觉上真实表现的技术选型人员。拿到它之后你的首要任务不是急着解压看图而是先搞清楚这套包的目录结构、标注格式和类别定义。2. 拆包先核对三件事目录结构、标注坐标与 YAML 配置2.1 解压路径与目录划分先做一次结构体检Roboflow 导出的数据集通常长这样images 和 labels 两个根目录下面按 train / valid / test 分好子目录。解压后第一件事就是确认这套划分是否完整别一上来就训练。在 Linux 下我习惯用下面这段命令看目录骨架unzip 针织品瑕疵检测数据集_yolov9标记.zip -d knitwear_dataset cd knitwear_dataset find . -maxdepth 3 -type d | sortunzip -d指定输出目录避免 zip 解压时把一堆文件直接散在当前目录里。find 只看目录层级不展开文件列表方便确认 images 和 labels 是否平行存在。正常情况你应该看到 train/images、train/labels、valid/images、valid/labels 这四兄弟。缺了 valid 目录的话要警惕要么是导出时没做划分要么是解压中断后面训练时 ultralytics 会自动把 train 的一部分挪作验证这样你会发现标注分布被打乱。文件数量也要做个快速核对图片和标注 txt 应该是一一对应的find . -regextype posix-extended -regex .*\.(jpg|jpeg|png) | wc -l find . -path ./*/labels/* -name *.txt | wc -l两条命令分别统计图片总数和标注文件总数。如果两者差得比较多说明有些样本没有标注这部分图在训练时会被当成背景处理。注意Roboflow 导出的文件名通常带着一段很长的哈希比如 IMG_14_JPG.rf.4b9f682814059eaf40b9fa484360129b.jpg对应同一 basename 的 txt 才是它的标签。这个哈希是平台为区分同名文件加的不是脏数据不用管它。2.2 labels 里的 txt 到底怎么写的五列归一化坐标随便挑一个 txt 文件看一下内容你会发现每一行都是五个数字head -3 train/labels/IMG_14_JPG.rf.4b9f682814059eaf40b9fa484360129b.txt输出大概是0 0.523438 0.721354 0.156250 0.208333 1 0.125000 0.468750 0.093750 0.145833这五行字段的含义分别是类别 id、归一化后的框中心点 x、中心点 y、归一化后的框宽 w、框高 h。归一化是相对原图宽高的比例取值范围在 0 到 1 之间所以无论原图是 640×640 还是 1920×1080txt 内容完全不需要改动。这是 YOLO 系列通用的标注格式YOLOv9 训练时直接读取不需要做格式转换。如果你想确认某张图的标注框是否合理可以把它还原成像素坐标我一般会写这样一小段 Python 脚本from PIL import Image import numpy as np img Image.open(train/images/IMG_14_JPG.rf.4b9f682814059eaf40b9fa484360129b.jpg) w, h img.size for line in open(train/labels/IMG_14_JPG.rf.4b9f682814059eaf40b9fa484360129b.txt): cid, cx, cy, bw, bh map(float, line.split()) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) print(cid, x1, y1, x2, y2)这段脚本的核心是把归一化坐标乘回图片宽高。打印出的四个整数就是框的左上角和右下角像素坐标可以用它配合 OpenCV 画框人工校验。注意如果算出来的 x1 或 y1 是负数或者 x2、y2 超出图片尺寸说明标注框越界了这类样本会在训练时拖累损失函数收敛。2.3 data.yaml 与类别 id 的对应关系训练脚本读取的唯一依据data.yaml 是训练时唯一的数据描述文件它决定了类别数量和类别名。Roboflow 导出的 YAML 内容大致如下train: ../train/images val: ../valid/images nc: 2 names: [hole, stain]train 和 val 指向的是相对路径这个相对是相对 YAML 文件本身所在目录而言的。nc 表示类别数量names 是类别名列表。这里的坑在于txt 标注文件第一列的整数 id是按 names 列表的下标从 0 开始编号的也就是说 id0 对应 holeid1 对应 stain。如果你改动 names 的顺序比如把 stain 放前面那么整个数据集里所有 txt 的标签含义全部错位。导出的顺序通常按字符串或平台默认排序拿到手后先用下面命令确认一下 names 和实际标注 id 是否对应for f in $(find train/labels -name *.txt | head -20); do cut -d -f1 $f | sort -u | tr \n echo done如果输出的 id 集合都在 0 到 nc-1 之间说明格式正常。出现大于等于 nc 的 id就要检查是不是导入数据时类别顺序不一致导致的脏标注。3. 训练第一步YOLOv9 环境准备与数据配置3.1 装环境ultralytics 包与依赖选择YOLOv9 的训练代码已经在 ultralytics 里统一维护了不需要再去 clone 原来的 yolov9 仓库直接 pip 安装就能跑。我建议用一个干净的 conda 环境Python 版本选 3.9 或 3.10 比较稳PyTorch 按自己显卡的 CUDA 版本装conda create -n yolov9 python3.10 -y conda activate yolov9 pip install ultralytics pip list | grep -E torch|ultralyticspip list这一步是为了确认 torch 和 ultralytics 都装上了。如果机器上没有 NVIDIA 显卡CPU 也能训练只是速度慢很多后面命令里 device 参数改成 cpu 即可。在装 ultralytics 的时候它会自动把 torch、torchvision、opencv-python 等核心依赖一起拉上来不需要手动逐个装。唯一要注意的是如果之前装过老版本的 torch建议先卸载再装避免 ultralytics 检测到 torch 版本过旧而报一堆看不懂的警告。实际测试中一版干净的 conda 环境能省掉至少半小时的依赖排查时间。3.2 改 YAML把 zip 里的 data.yaml 指到你的绝对路径Roboflow 导出的 data.yaml 里 train 和 val 用的是相对路径这在原机器上没问题但 zip 换了一台电脑解压后相对路径的基准就变了训练时经常报找不到图片。我拿到手的第一件事就是改成绝对路径同时在开头加一个 path 字段统一管理path: /home/knitwear/knitwear_dataset train: images/train val: images/valid nc: 2 names: [hole, stain]这里的 path 是数据集的根目录train 和 val 写成相对这个根目录的子路径ultralytics 会自动拼接。使用绝对路径的好处是不管你在哪个终端目录下执行训练命令数据都不会找丢。注意如果项目要换机器跑这个 path 也得跟着改最省事的做法是把 path 写成一个变量在启动训练时用命令行的方式传入但这需要你自己包一层 shell 脚本初学者没必要折腾。改完之后可以先做一个快速验证确认 YAML 指向的路径真实存在python -c import yaml; dyaml.safe_load(open(data.yaml)); print(d[path], d[train], d[val])打印结果应该是一个绝对路径加上 train 和 val 的相对路径。这一步看似多余但能提前发现路径里的空格、中文等隐藏问题比训练到一半突然报错强得多。3.3 开始训练参数取舍与模型选择YOLOv9 训练入口是yolo detect train模型权重我一般用官方预训练的 yolov9c.pt 作为起点而不是随机初始化。在瑕疵检测这种样本量不算大的工业场景迁移学习的收敛速度和最终精度都要明显好于从零训练yolo detect train modelyolov9c.pt datadata.yaml imgsz640 batch8 epochs100 device0几个关键参数逐个说model 指定预训练权重yolov9c 是中等规格版本速度和精度平衡data 指向上一步改好的 yaml 文件imgsz 是训练输入尺寸针织品瑕疵很多是小目标这里先给 640后面验证稳定后再试 1280batch 是批大小由显存决定8 是 8GB 显存左右的安全值显存不够就降到 4epochs 先给 100配合早停机制实际多数数据集在 60 到 80 轮就收敛了device0 表示用第一块 GPU。如果训练途中断了直接加resumeTrue接着跑不用重新来。训练结束后权重默认保存在 runs/detect/train/weights/ 下best.pt 是验证集上表现最好的权重last.pt 是最后一轮的权重。后续推理优先用 best.pt。4. 训练前先体检类别分布、标注质量与数据划分4.1 统计类别数量先回答样本是不是失衡工业瑕疵数据天生带有类别不均的问题。这个数据集虽然量不大但你还是要在训练前知道各类别到底占了多少比例。用一段脚本遍历 train 标签统计每个类别的框数量import glob from collections import Counter box_counter Counter() empty_files 0 total_files 0 for txt_path in glob.glob(labels/train/*.txt): total_files 1 lines txt_path and open(txt_path).read().strip().splitlines() if not lines: empty_files 1 continue for line in lines: cid int(line.split()[0]) box_counter[cid] 1 print(total label files:, total_files) print(empty label files:, empty_files) print(class distribution:, box_counter)glob会列出 train 标签目录下所有 txt 文件脚本用 Counter 统计每个类别 id 出现的频次也就是该类别在所有图片中的目标总数。empty_files 记录的是完全没有标注的 txt 文件数量这类文件对应的是纯背景图或者被漏标的原因如果占比超过 15%训练出的模型误检率会明显偏高建议删掉或补标。当某个类别的框数量只有另一个类别的十分之一时说明类别失衡严重后续需要做针对性采样比如在训练命令里把该类别图片重复几份或者手工给 loss 加权重。先看数字再决定策略别盲目上复杂的分层采样。4.2 检查标注框尺寸分布小目标占比直接决定 imgsz针织品上的断纱、污渍、起球在整张布匹图里往往只占很小一块区域这类目标如果框的尺寸太小很难被模型稳定检出。标注框的归一化宽高可以从 txt 里直接读不需要读图片import glob import numpy as np widths, heights [], [] for txt_path in glob.glob(labels/train/*.txt): for line in open(txt_path): _, _, _, w, h map(float, line.split()) widths.append(w) heights.append(h) arr_w, arr_h np.array(widths), np.array(heights) print(mean norm w/h:, arr_w.mean(), arr_h.mean()) print(p10 norm w/h:, np.percentile(arr_w, 10), np.percentile(arr_h, 10))输出的归一化宽高乘以 imgsz 就是模型眼中的像素尺寸。如果 p10 的框宽高乘以 640 后小于 32 像素说明有大量小目标这时的策略有两个一是把 imgsz 提到 1280让网络输入分辨率更高小目标的特征更充分二是做切片推理把原图裁成几个 patch 分别检测。前者显存开销大后者需要额外的拼接逻辑。无论如何先用这份分布数据确认「小目标到底有多小」再决定要不要花钱升级显卡或改代码。4.3 检查越界框与空标签最常见的脏数据来源有时候解压后你会发现部分 txt 里的坐标值超过了 0~1 的范围比如 w 或 h 大于 1导致还原后的框跑到图像外面。检查方法很简单awk { if ($3 1 || $4 1 || $5 1 || $6 1) print FILENAME, $0 } labels/train/*.txt | head -20awk 直接过滤出第三列到第六列中任一大千 1 的行即中心点坐标或宽高超出归一化范围的标注。Roboflow 导出时一般会做裁切但如果你在这之后手工编辑过标签或者数据是从其他平台转过来的这种情况就很可能出现。处理方式是直接把这一行删掉或者用np.clip把坐标值裁剪回 0~1 边界。空标签文件则需要区分情况如果是背景采样图保留没问题训练时该图就是负样本如果是漏标建议补标后回填否则就等于告诉模型这张图里没有任何目标。4.4 检查 train/valid 划分同源图片会污染验证结果Roboflow 导出包的划分通常没问题但有些来源的导出是按文件随机分的如果同一个场景拍摄的连续帧被同时分到 train 和 valid验证集指标就会虚高。检查同源泄漏的办法是对比 train 和 valid 的文件名前缀针织品瑕疵数据集里的文件名虽然带了哈希但原始文件名前面部分往往会保留序列感比如同一批拍摄的 IMG_ 开头图。实际处理中如果发现某张图的增强版本同时出现在两个集合里需要手动挪文件。这个操作没有捷径我一般用一个简单脚本按原始 basename 的前缀做分组然后对比集合差异花了十几分钟就能排查完。5. 避坑跑针织品瑕疵检测最容易翻车的 5 个地方5.1 现象训练 loss 正常下降但验证集 mAP 一直是 0原因这类问题九成出在 txt 标注的类别 id 和 data.yaml 里 names 顺序对不上。比如 txt 里写的是 0但 yaml 里第 0 个类别是背景模型学到的和评估的对不上号。解决先统计一下 train 标签里实际出现的 id 集合再对照 yaml 里的 names 逐一确认。确认错位后写一个重映射脚本把 id 统一替换比如把旧 id 2 改成新 id 0替换用 sed 即可sed -i s/^2 /0 / train/labels/*.txt5.2 现象训练卡在读图阶段报 corrupt JPEG 或无法打开图片原因zip 解压路径或文件名里带了中文、空格、特殊字符OpenCV 在 Windows 下读这种路径经常失败。这个 zip 本身就是中文名解压后目录路径大概率带着中文训练时就翻车了。解决解压后统一把根目录改名成纯英文无空格的路径比如改成 knitwear_data同时在 data.yaml 里把 path 指到新路径。从那以后凡是从网上下载的 zip我都会先检查路径 ASCII 化再解压这一步能省掉很多莫名其妙的问题。5.3 现象小瑕疵几乎检不出来大缺陷倒是很准原因用了默认 imgsz416 或 640 导致小目标特征在降采样中丢失针织品上几毫米的断纱到了 32 倍下采样后只剩几个像素。解决先看第 4 章的框尺寸统计如果确认小目标占比高把 imgsz 提到 1280batch 相应减半显存不够就开 rect 模式按比例批量推理。实测中 imgsz 从 640 提到 1280 对小瑕疵的召回提升立竿见影但训练时间也要翻倍。注意训练和推理的 imgsz 保持一致否则权重在训练分辨率下学到的特征尺度到了推理时会对不上。5.4 现象训练开始时报找不到 labels或者每一轮都在重新初始化原因没有 images/train 目录与 labels/train 目录一一对应。Roboflow 导出的数据集有时把 labels 和 images 分开放置路径由 yaml 里的 train/val 字段决定。如果 yaml 改动失误比如 train 指到了 images/train 但 labels 目录名不带多维结构ultralytics 就会报错。解决用第 2 章的 find 命令核对目录结构确认 labels 下的 train 目录存在且与 images 下的 train 目录平行然后按 3.2 修改 yaml。如果缺失 test 目录也没关系只用 train 和 valid 就能训练ultralytics 会把 valid 当作测试集来看。5.5 现象验证集 mAP 看着不错但实际拍摄图上误检一堆原因标注数据里没有背景负样本模型把纹理复杂的区域当成瑕疵。针织品的花型、织纹在局部看和起球、破洞高度相似。解决把无瑕疵的布匹图收集起来建立一个负样本目录每张图配一个空 txt 文件加进 train 里。推理降级处理时把 conf 阈值从默认的 0.25 提高到 0.4 以上再用 NMS iou 0.5 过滤重叠框。这类问题靠调验证集指标是看不出来的必须用真实产线采样图回测才算数。6. 进阶训练完先别急着部署用这三步自查训练结束不代表交付结束验证集 mAP 只是一个参考值实际场景里还要看框的贴合度和误检情况。我拿到 best.pt 之后做的第一件事是挑几张训练集和验证集里都没有的新照片跑一次预测直接看可视化结果。命令很简单yolo detect predict modelruns/detect/train/weights/best.pt sourcetest_imgs imgsz640 conf0.35 saveTruesource 放新拍的照片目录conf 比默认上调一点模拟现场的低置信度过滤。跑完去 runs/detect/predict 里看标注过的输出图重点关注两点一是没有瑕疵的布面是否被画框二是真实瑕疵的框是否紧贴瑕疵边缘。框偏大或偏小都说明定位精度不够需要回炉。然后做部署导出。YOLOv9 的权重一般要转成 ONNX 再接推理引擎常见做法是yolo export modelruns/detect/train/weights/best.pt formatonnx opset12 halfTrue dynamicTruehalfTrue 会把权重转成半精度浮点推理时显存占用减半速度变快但精度会有轻微损失如果现场对误差敏感就改成 halfFalse。dynamicTrue 让模型的 batch 维度可动态变化方便部署端以任意批大小调用。导出后拿 ONNX 在部署端跑一张图对比一下和 PyTorch 原版的输出差异如果置信度差超过 0.02就换回 FP32。从那以后只要是 Roboflow 导出的数据集我拿到手都会强制按固定顺序走一遍ASCII 路径解压、目录结构核对、YAML 绝对路径改写、标注质量统计、train/valid 同源检查五步走完才允许训练开始。这样做的直接收获是省掉了多次莫名其妙的训练中断和指标虚高。希望帮到你。本文还有配套的精品资源点击获取