简介:面向工业质检场景的针织品瑕疵检测数据集,压缩包共105个文件、5.37MB,解压后包含52张原始jpg图像、52个txt标注文件以及1个yaml配置。txt标注文件采用YOLO格式,逐行记录瑕疵对象的类别编号与归一化边界框坐标,可直接作为YOLOv9的训练标签;配套jpg图像展示真实针织面料在不同纹理、光照与拍摄角度下的形态,便于检验模型的实际鲁棒性;yaml文件定义类别名称、nc参数与数据路径,解压后配置本地路径即可接入训练流程。数据规模虽不大,但涵盖数据、标注、配置三类模块,适合用于学习目标检测数据集的构建规范、完成YOLOv9的快速验证,也可作为迁移学习、数据增强或课程设计的基础素材。目前已有836人学习下载,主要面向计算机视觉初学者、工业质检算法工程师以及需要在小样本场景中测试检测效果的开发者。
1. 针织品瑕疵检测数据集:为什么我建议直接拿 YOLOv9 标记版上手
做工业视觉的人应该都有同感:找数据集比调模型还难。尤其是纺织行业,网上能下到的瑕疵检测数据集大多是布匹、无纺布,真正针对针织品的少得可怜。这份「针织品瑕疵检测数据集 yolov9标记.zip」恰恰是拿来就能用的类型——图片已经用 YOLOv9 格式标好,解压后直接喂给 YOLOv9 训练就行。它解决的核心问题只有一个:你不用再从零标注,省掉两三天的人工打标时间,适合刚入坑瑕疵检测的工程师、做毕设的学生,以及想快速验证 YOLOv9 在自己产线上是否可行的从业者。文件名里带 .rf. 说明这些图是从 Roboflow 导出的,标注信息齐全,后面我会逐项拆开看。
2. 数据集解剖:YOLOv9 格式的目录结构、标签文件与 data.yaml 配置
2.1 从文件名看懂数据集来源和划分逻辑
先别急着解压,把文件名读一遍能省很多事。这份 zip 里的图片文件名大致分两类:一类是 IMG_14_JPG.rf.4b9f682814059eaf40b9fa484360129b.jpg 这种,一类是 z4874860538074_9917321184aecfb61fc44bb74161ee10_jpg.rf.ab1907d32b941b1e98e3d277440a355e.jpg 这种。
这两个前缀对应两种拍摄来源:IMG 开头的是手机或相机直接拍的产线照片,z487486 开头的是带设备编号的工业相机采集图。rf. 后面那串长哈希是 Roboflow 平台给每张图的唯一标识,说明这批图曾经在 Roboflow 上做过标注和导出。如果你之前用过 Roboflow 导出的数据集,会发现所有文件都遵循「原始文件名 + .rf. + 哈希值」这个约定。
解压后务必检查有没有 train / valid / test 三个子目录。Roboflow 默认按 70/20/10 或 80/10/10 划分数据集,每个子目录里图片和 txt 标签是成对出现的。我的习惯是先看 valid 目录里有没有图——如果只有 train,说明导出时没做划分,训练时得手动切分。
# 解压并检查目录结构 unzip 针织品瑕疵检测数据集_yolov9标记.zip -d knit_defect cd knit_defect find . -type f | awk -F'/' '{print $2}' | sort | uniq -c这段命令输出的应该是类似 train 310、valid 40、test 50 这样的数字分布。如果只看到一堆 图片.jpg 和对应 图片.txt 平铺在一起,那就得自己写脚本划分数据集了。注意 unzip 时中文文件名可能乱码,建议用 unzip -O GBK 选项解压,这类细节后面避坑章节专门讲。
2.2 YOLOv9 的标签格式:每个 txt 里到底写了什么
YOLOv9 和 YOLOv5/YOLOv8 一样,标签是纯文本 txt 文件,每一行表示一个目标框,格式固定为五列:
class_id x_center y_center width height但有个细节必须注意:后四列不是像素坐标,而是归一化坐标。具体计算方式是相对于图片宽度和高度的比例。比如一张 640x640 的图,一个瑕疵框的像素坐标是 (200, 300, 80, 50),那 x_center 就是 (200 + 40) / 640 = 0.375,y_center 是 (300 + 25) / 640 ≈ 0.508,width 是 80 / 640 = 0.125,height 是 50 / 640 ≈ 0.078。
0 0.375 0.508 0.125 0.078 2 0.812 0.214 0.063 0.047第一行的 0 是类别编号,后面的数字全是 0 到 1 之间的小数。为什么用归一化坐标?因为训练时 YOLO 会对输入图做 letterbox 缩放,如果标签用像素坐标,缩放后标签就全对不上目标了;归一化之后无论输入尺寸怎么变,标签比例始终不变。这也是 YOLO 系列和 Faster R-CNN 这类两阶段检测器的重大差异之一。
用下面的脚本快速统计这份数据集有哪些类别:
import os from collections import Counter label_dir = "knit_defect/train/labels" class_counter = Counter() for label_file in os.listdir(label_dir): if not label_file.endswith(".txt"): continue with open(os.path.join(label_dir, label_file), "r") as f: for line in f: parts = line.strip().split() if len(parts) == 5: class_counter[int(parts[0])] += 1 print("类别分布:", dict(class_counter))这个脚本遍历 train 目录下所有 txt 标签文件,对每一行取出第一个数字——类别 ID,然后计数汇总。跑完你会看到类似 {0: 320, 1: 156, 2: 89} 的输出,其中 0 就对应 data.yaml 里 classes 列表的第一个名字。如果发现三个类别的数量差异悬殊,比如某个类别只有几十个框而另一个有上千个,后面训练时就得考虑加重该类别的 loss 权重,或者用 mosaic 增强来缓解。
2.3 data.yaml 的正确改法:路径和类别名一个都不能错
YOLOv9 训练时读的不是 txt 标签,而是 data.yaml 配置文件。这个文件告诉训练脚本「图片在哪、标签在哪、有哪些类别」。解压后的数据集里如果没有 data.yaml,就得按下面的模板自己写一份:
# data.yaml train: /absolute/path/to/knit_defect/train/images val: /absolute/path/to/knit_defect/valid/images test: /absolute/path/to/knit_defect/test/images nc: 3 names: ['破洞', '污渍', '跳线']train 和 val 字段建议写绝对路径,因为 YOLOv9 训练时会在当前工作目录下解析相对路径,如果你把数据集放在别处,训练脚本大概率找不到图片。nc 是类别总数,names 是类别名列表,顺序必须和标签文件里的 class_id 对应——第 0 行对应 names[0],第 1 行对应 names[1],以此类推。类别名可以改成你业务里的叫法,比如「破洞」改成 "holes",「污渍」改成 "stain",但 names 的顺序和数量绝不能乱动。
判断类别名是否匹配有个土办法:随便打开一个标签 txt 文件,看里面出现的最大的 class_id 数字是多少。如果看到 3,但 yaml 里 nc 写的 3,那第 3 个 id 就超范围了,训练必然报错。YOLOv9 训练时对标签索引越界非常敏感,轻则跳过该样本,重则直接崩训练进程。
3. 用这份数据集跑通 YOLOv9 训练:环境准备、参数选型与完整命令
3.1 环境搭建:GPU 驱动、PyTorch 和 YOLOv9 代码库的版本匹配
YOLOv9 官方代码库基于 PyTorch 实现,源码在 GitHub 上,克隆下来就能用。但环境配置有几个版本雷区,我先列出来:
| 组件 | 推荐版本 | 备注 |
|---|---|---|
| Python | 3.8 - 3.10 | 3.11 以上部分依赖编译不过 |
| CUDA | 11.8 或 12.1 | 对应不同 PyTorch 版本 |
| PyTorch | 2.0.0 或 1.13.1 | 官方 requirements 里指定了版本范围 |
| torchvision | 与 PyTorch 匹配 | 比如 2.0.0 配 0.15.1 |
有个常见做法是用 conda 建一个独立环境,避免把系统 Python 搞乱。安装 PyTorch 时注意 pip 源,国内直接 pip install torch 大概率走 CPU 版,必须用带 CUDA 的 index-url。装完验证一下 GPU 是否可用:
python -c "import torch; print(torch.__version__, torch.cuda.is_available())"输出 True 才说明 CUDA 环境正常。如果这里显示 False,后面训练时 YOLOv9 会默默跑 CPU 模式,一个 epoch 能慢十倍。遇到这种情况先检查nvidia-smi看驱动是否正常,再检查 PyTorch 是不是 CPU 版,pip list | grep torch看输出特征。
然后是克隆 YOLOv9 官方代码并安装依赖:
git clone https://github.com/WongKinYiu/yolov9.git cd yolov9 pip install -r requirements.txtrequirements.txt 里列了 torch、torchvision、opencv-python、numpy 等依赖。我习惯先装好 torch 再跑 requirements,否则 pip 会顺手把 torch 也装成 CPU 版,覆盖掉刚才配好的 GPU 版。
3.2 预训练权重与训练命令的选择逻辑
YOLOv9 提供了两种模型规模:yolov9-c(基础版)和 yolov9-e(增强版),另外还有配合 GPU 显存较小的 yolov9-t 版本。对于针织品瑕疵检测这种单类目标不算多的任务,我一般直接上 yolov9-c,精度够用,训练速度也不至于让人等得心烦。
预训练权重从官方 Release 页面下载,注意下载链接里有 ckpt 后缀的版本还是 pt 后缀的版本。训练用 pt 版本即可,ckpt 版里夹带了优化器状态和训练配置,体积大几倍,但精度没有额外收益。
# 开始训练,batch-size 根据显存调整 python train.py \ --batch-size 16 \ --epochs 100 \ --img 640 \ --data /path/to/knit_defect/data.yaml \ --weights yolov9-c.pt \ --device 0 \ --hyp hyp.scratch-high.yaml \ --project runs/kni_defect \ --name train_v1batch-size 是每轮喂给 GPU 的图片数,16 对 8GB 显存是比较稳的起步值;如果显存只有 6GB,降到 8。epochs 100 对工业瑕疵检测通常够了,我见过不少项目 50 轮就收敛。img 是训练输入尺寸,640 是 YOLO 系列默认值,如果你的瑕疵框特别小——比如几十个像素的跳线破洞——可以试试 960,但显存占用会显著上升。
hyp.scratch-high.yaml 是高数据增强的配置文件。瑕疵检测场景里目标形态变化大、样本量又有限,增强策略直接决定模型能不能泛化到产线实拍图。这里不做特殊修改,先用默认配置跑一轮,后面根据 loss 曲线再调。
3.3 训练过程中的监控指标:loss 曲线和 mAP 怎么读
训练起来之后,终端会滚动输出每一轮的指标:
Epoch gpu_mem box obj cls labels img_size 49/100 6.73G 0.04810 0.06230 0 5 640box loss 是框回归损失,obj loss 是置信度损失,cls loss 是分类损失。对单类检测任务(所有瑕疵算同一类),cls loss 始终是 0 是正常的。关键看 box 和 obj 是否持续下降。训练结束时会在 runs/kni_defect/train_v1/ 目录下生成结果汇总,包括 confusion_matrix.png、results.png、F1_curve.png 等图表。
mAP 是核心指标的通俗说法,分为 mAP@0.5 和 mAP@0.5:0.95 两种。前者只看 IoU 阈值 0.5 下的平均精度,后者是 0.5 到 0.95 每隔 0.05 取一个阈值的平均值。工业质检场景我更看重 mAP@0.5,因为实际部署时我们通常把置信度阈值调得很低、把 IoU 阈值调成 0.5,保证瑕疵一个不漏,宁可误报再多开一档人工复核。
4. 标签校验与数据增强:动手检查这份数据集的真实质量
4.1 批量可视化标签:验证坐标是否和瑕疵位置对得上
标注数据是机器学习里最不能省的一步。YOLOv9 这个项目我看过太多翻车案例——标签文件里坐标写了、格式也正确,但画出来就是框不住目标。原因多是导出时坐标系搞错或者标注者手抖。拿到这份数据集后,第一件事就是把标注画回图片上看。
import cv2 import glob image_paths = glob.glob("knit_defect/train/images/*.jpg") for img_path in image_paths[:20]: img = cv2.imread(img_path) h, w = img.shape[:2] label_path = img_path.replace("images", "labels").replace(".jpg", ".txt") with open(label_path, "r") as f: lines = f.readlines() for line in lines: cls_id, xc, yc, bw, bh = map(float, line.strip().split()) x1 = int((xc - bw / 2) * w) y1 = int((yc - bh / 2) * h) x2 = int((xc + bw / 2) * w) y2 = int((yc + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite("check_" + img_path.split("/")[-1], img)这段脚本把归一化坐标乘以图片实际宽高,还原成像素坐标,再用 OpenCV 画框。重点看三类问题:一是框是否明显偏大偏小,二是框是否偏离瑕疵位置,三是有没有重复标注的情况。前 20 张图看下来基本能判断出标注员的水平。如果发现大面积标注偏移,那训练前就得考虑重新标注或者做坐标校正,否则模型会学到错误的位置信息。
4.2 类别不平衡与数据增强策略
针织品瑕疵存在一个常见情况:破洞这类明显缺陷样本多,跳线这类细微缺陷样本少。用之前统计脚本跑完类别分布,如果最少的类别不到最大类别的 10%,就需要做样本增广,否则小类别基本学不出来。
import albumentations as A import cv2 import numpy as np transform = A.Compose([ A.HorizontalFlip(p=0.5), A.RandomBrightnessContrast(p=0.3), A.GaussNoise(p=0.2), A.ShiftScaleRotate(shift_limit=0.05, scale_limit=0.05, rotate_limit=15, p=0.5) ]) img = cv2.imread("knit_defect/train/images/IMG_14_JPG.rf.4b9f682814059eaf40b9fa484360129b.jpg") for i in range(5): transformed = transform(image=img) cv2.imwrite(f"aug_{i}.jpg", transformed["image"])albumentations 库是工业视觉里做增强最顺手的工具。注意它只管图片增强,不管标签同步——如果你做的是检测任务,增强时标注框也得跟着旋转、平移,albumentations 提供了 bbox 参数同步接口。上面这段只是图片演示,实际用在训练管线里时,YOLOv9 自带的 mosaic 策略会自动处理标签同步,所以不一定非得引入 albumentations。
4.3 标注格式快速校验脚本
训练前再做一道硬校验:统计所有标签,检查坐标是否超出图片边界、有没有空标签文件、类别索引是否越界。这几个问题在 Roboflow 导出的数据集里相对少见,但一旦出现会让训练中断或产生无效学习。
# validate_labels.py import os import cv2 ok_count = 0 error_list = [] for split in ["train", "valid", "test"]: img_dir = f"knit_defect/{split}/images" label_dir = f"knit_defect/{split}/labels" for img_name in os.listdir(img_dir): img = cv2.imread(os.path.join(img_dir, img_name)) h, w = img.shape[:2] label_path = os.path.join(label_dir, img_name.replace(".jpg", ".txt")) if not os.path.exists(label_path): error_list.append(f"{img_name}: 缺少标签文件") continue with open(label_path, "r") as f: lines = f.readlines() if len(lines) == 0: error_list.append(f"{img_name}: 空标签文件") continue for line in lines: parts = line.strip().split() if len(parts) != 5: error_list.append(f"{img_name}: 格式错误 - {line}") continue xc, yc, bw, bh = map(float, parts[1:]) if not (0 <= xc <= 1 and 0 <= yc <= 1 and 0 < bw <= 1 and 0 < bh <= 1): error_list.append(f"{img_name}: 坐标越界 - {line}") print(f"通过: {ok_count} 张, 异常: {len(error_list)} 条") for e in error_list[:20]: print(e)这段脚本把目录、坐标范围、格式全查了一遍。它不会修标签,只负责把问题列出来。看到输出里只有「通过」没有「异常」时,就可以放心进入训练环节了。
5. 避坑指南:训练 YOLOv9 检测针织品瑕疵的 5 条血泪经验
5.1 解压后找不到标签文件,图全躺在根目录
现象:解压 zip 后,同目录下只看到一堆 jpg,没看到 txt 标签文件。 原因:Roboflow 导出时如果选择「JPG + YOLOv9 .txt」,标签和图片是并排放在同一个目录的,但某些非官方打包工具会把 txt 抽离到单独文件夹,或者干脆漏打包。 解决:先ls看一眼有没有任何 txt 文件。如果有但不在图片旁边,做一个循环把 txt 挪到对应图片目录;如果完全找不到,检查 zip 里是否嵌套了一层子目录——很多打包的人会把整个数据集目录塞进 zip,解压后多出一层路径,标签其实在下一层。我一般解压后第一件事就是find . -name "*.txt" | head -5看标签在哪。
5.2 训练时报错 label class index out of range
现象:训练刚开始就报IndexError: label class 5 out of range,或者日志里大量 skip 样本。 原因:标签 txt 文件里的类别 ID 超出了 data.yaml 里 nc 指定的范围。比如 nc 配置成 3,但标签里出现了 class_id 4。Roboflow 导出的数据有时会保留原始数据集的全部类别编号,而这份针织品数据集如果做过多轮合并,类别编号可能有空洞——比如原数据集有 5 类,删掉 2 类后余下的类别 ID 还是 0、2、4,没有重排为 0、1、2。 解决:用 2.2 的统计脚本先找出标签里实际出现的最大 class_id,然后把所有 txt 里的类别 ID 重映射为连续编号。可以写个循环:先读全部 ID 排序,建立旧 ID 到新 ID 的映射字典,再逐文件替换。这个操作是数据预处理里最枯燥但最重要的一步,跳过它训练必翻车。
5.3 训练 mAP 一直很低,但 loss 下降正常
现象:训练到 50 轮,box loss 和 obj loss 都降得挺好,mAP@0.5 却卡在 0.3 上下。 原因:标签坐标系或者 letterbox 参数不匹配。YOLOv9 对训练图做了自适应缩放,如果原图本身不是正方形,代码会用灰色填充补边。问题是,如果数据集里的标签坐标在导出时是按「填充后图片」计算的,而训练时又做了一次填充,坐标就双重偏移了。另一种常见原因是图片里有 EXIF 旋转信息,OpenCV 默认不处理 EXIF,导致图片被旋转后标注没跟着转。 解决:打开几张图和标注人工比对,确认框是整体偏移还是方向错。整体偏移的话,把填充逻辑关掉改为直接 resize 到 640x640;方向错的话,预处理阶段用 PIL 先把 EXIF 旋转应用掉再喂给训练。用 cv2.imread 读图时cv2.IMREAD_IGNORE_ORIENTATION这个标志位要留心。
5.4 训练时显存溢出(CUDA out of memory)
现象:train.py 启动后没跑几步,直接报RuntimeError: CUDA out of memory。 原因:batch-size 太大,或者 img 尺寸设置太高,也可能同时跑的其它进程占了显存。检测模型训练时除了模型参数,还要缓存梯度、优化器状态、特征图,这些累积起来比推理时显存占用高 5 到 10 倍。 解决:先把 batch-size 砍到 8,如果还炸就换 yolov9-t(tiny 版本)。再不行就把 img 从 640 降到 512——对针织品瑕疵这种目标,512 输入通常也能有不错效果。注意一个细节:--workers参数如果设得太大,dataloader 会抢占 CPU 内存而不是显存,但会拖慢 GPU 喂数据速度,一般设成 4 或 8 就好。
5.5 验证集 mAP 高,但实测新图一塌糊涂
现象:valid 集 mAP@0.5 到 0.9,但拿产线新拍的照片测试,漏检一大片。 原因:这是典型的过拟合数据集,而不是过拟合模型。训练集和验证集来自同一个拍摄批次,光线、角度、颜色分布完全一致,模型学到的是「这个相机拍出来的图长什么样」,而不是「瑕疵长什么样」。 解决:训练完成后,强制要求自己用另一台设备或另一个时段拍的图片做测试。如果这份数据集里 test 目录的图片和 train 出自同一场景,那就得自己额外收集一组样张来验证。所谓泛化能力,不是看测试集分数,而是看换场景后还灵不灵。我从那以后每次训完都是先跑一遍「完全没见过」的图片再谈部署。
6. 让模型上线前更稳:置信度阈值调优与瑕疵定位验证技巧
6.1 置信度阈值和 NMS 参数该怎么试
模型训练完导出权重后,推理阶段有两个参数直接决定实际效果:conf-thres 和 iou-thres。YOLOv9 的 detect.py 或自定义推理脚本里,这两个默认值分别是 0.25 和 0.45。但对瑕疵检测场景来说,漏检的代价远高于误检——瑕疵漏过去意味着次品流入市场,多标几个框顶多多看几眼。
python detect.py \ --weights runs/kni_defect/train_v1/weights/best.pt \ --source /path/to/test_images \ --conf-thres 0.15 \ --iou-thres 0.5 \ --save-txt \ --save-confconf-thres 从 0.25 降到 0.15 通常能多召回 10% 的细小瑕疵,代价是误检增多。工业部署时的常见做法是设一个低置信度阈值做初筛,再用规则过滤掉明显不合理的框——比如面积过小、长宽比异常的检测结果。为了让这个过滤不变成玄学,逐张看推理输出、统计误检样本的特征,是唯一靠谱的路。
6.2 用热力图和错误样本定位模型短板
YOLOv9 训练完会在 runs 目录下生成混淆矩阵和 PR 曲线,这些图表对判断模型短板很有帮助。还有一个实操上更直接的办法:把所有验证集图片的推理结果保存下来,重点看 false negative 样本——那些有瑕疵但模型没框出来的图。把这些图按瑕疵类型归档,观察是否有共同特征,比如都是暗光环境、都是深色背景、或者瑕疵都偏小。
import cv2 import torch import glob model = torch.hub.load("WongKinYiu/yolov9", "custom", "runs/kni_defect/train_v1/weights/best.pt") model.conf = 0.15 model.iou = 0.5 for img_path in glob.glob("valid_images/*.jpg"): results = model(img_path) if len(results.xyxy[0]) == 0: print(f"未检出: {img_path}") else: for det in results.xyxy[0]: x1, y1, x2, y2, conf, cls = det.tolist() print(f"检出: {img_path} | 类别{int(cls)} | 置信度{conf:.2f} | 框大小{w}x{h}")这个脚本本质是把模型在验证集上的输出打出来,找漏检样本。如果发现大量漏检集中在很小尺寸的瑕疵上,可以考虑把 img 输入尺寸提到 960 重新训练,或者在数据增强里增加随机裁剪放大的概率。尺寸问题靠调参解决不掉,得从输入分辨率和样本分布下手。
另一个值得做的是把特征图可视化出来。YOLOv9 在 neck 和 head 之间有 GELAN 结构,用 hook 方式把特征图接出来,看模型在漏检样本上是否给出了低置信度的置信度图。如果特征图有明显的响应但最后被 NMS 压掉,那就调 iou-thres;如果特征图根本没响应,说明模型确实没学到这个特征,得回头补数据。
6.3 导出 ONNX 与部署前的量化检查
训练结束了,真正上线前还有一步:把 PyTorch 权重导出成 ONNX 格式,做一次精度对齐验证。PyTorch 训练时的推理逻辑和 ONNX 部署后有时会出现微小差异,主要来自算子融合和坐标解码方式。YOLOv9 官方仓库提供了 export.py:
python export.py \ --weights runs/kni_defect/train_v1/weights/best.pt \ --include onnx \ --img 640 \ --device 0导出后拿同一张图分别跑 pt 版和 onnx 版,对比检测框坐标和置信度,差异应该在 0.01 以内。我见过有人跳过了这一步,直接上生产环境,结果 onnx 版漏检率高一截,排查了半天才发现是导出时 opset 版本和推理框架不匹配导致的精度损失。从那以后我每次导出 onnx 后都强制走一遍「同一张图双版本对比」的验证流程,确认框坐标和置信度一致后再交给部署组。这份针织品数据集也一样——训练只是起点,能稳定检测才算真正完成。希望这些踩坑经验能让你少走几步弯路。
本文还有配套的精品资源,点击获取