
简介这份资源是2019年天池布匹瑕疵检测赛题相关的图像数据集面向从事工业质检、缺陷检测算法实践的开发者与学习者可用于分类、检测等视觉任务的训练与验证。压缩包共935个文件以689张jpg瑕疵图像和245个xml标注文件为主另附1个txt说明文件整体约927.26MB图像与标注基本配套便于直接构建监督学习数据管线。数据集覆盖32种布匹表面瑕疵类别各类别样本数量差异较大部分类别图片偏少作者也坦言整体质量不算高更适合作为练手或补充数据使用。目前已有2919人学习下载读者可从中获得多类别瑕疵的原始图像与对应标注用于熟悉工业缺陷数据的组织方式、验证模型在小样本与类别不均衡条件下的表现并据此设计数据清洗与增强策略。1. 布匹瑕疵数据集-2019天池一张图里藏着多少种“织错”的方式第一次拿到布匹瑕疵数据的人多半会低估它。以为就是“有瑕疵/没瑕疵”的二分类跑个 CNN 就完事。真正打开标注文件才会发现同一匹布上断经是细长竖线破洞是局部空洞油污是低对比度色斑三者的形态差异比猫和狗还大而它们又常常同时出现在一张图里。这就是布匹瑕疵数据集-2019天池这类工业质检数据集的核心难点它不是单标签分类而是多标签、小目标、类别极不均衡的检测任务。这个数据集面向的是纺织面料表面缺陷检测典型场景是验布机上的工业相机在线拍摄需要模型在高速产线上把断经、断纬、破洞、油污、污渍、三丝等缺陷框出来并分类。适合谁做工业视觉落地的算法工程师、想把检测模型从公开数据集迁移到真实产线的团队以及需要一套“脏但真实”的数据来验证小目标检测方案的人。它解决的不是“能不能识别”而是“在类别长尾、标注粒度粗、背景纹理强干扰的条件下怎么把召回率做上去”。2. 先看清数据长什么样标注格式、类别分布与图像特性动手写模型之前必须先把数据集翻一遍。工业质检数据集和 COCO 那类自然图像数据集的气质完全不同直接套通用检测流程十有八九会在验证集上看到“mAP 还行但漏检严重”的玄学现象。这一章先把数据的三个关键面拆开标注结构、类别长尾、图像纹理。2.1 标注文件的结构与字段含义这类比赛数据集常见做法是给一个 CSV 或 JSON 标注表每行对应一个缺陷框字段大致是图像名、类别、左上角坐标、宽高。不同年份、不同赛题的具体字段名会有差异但结构逻辑一致。拿到手第一件事不是训练是写脚本统计每类多少个框、每张图平均几个框、框的宽高分布。import pandas as pd # 假设标注表为 train.csv字段名按常见命名 df pd.read_csv(train.csv) # 1. 类别分布看长尾有多长 cls_count df[category].value_counts() print(cls_count) # 2. 每图框数分布判断是单目标还是密集多目标 per_img df.groupby(image_id).size() print(per_img.describe()) # 3. 框尺寸分布小目标占比决定要不要改 anchor / 特征层 df[w] df[xmax] - df[xmin] df[h] df[ymax] - df[ymin] df[area] df[w] * df[h] print(df[area].describe(percentiles[0.1, 0.5, 0.9]))这段脚本的价值在于把“感觉”变成数字。类别分布如果头尾差几十倍就不能用普通交叉熵硬训得考虑重采样或类别加权每图框数如果集中在 1 到 2 个说明大部分图是稀疏标注密集场景少评估时按图算指标会更贴近产线框面积的中位数如果很小说明小目标占主导特征金字塔的高层分辨率不够用得往上加 P2 层或者提高输入分辨率。参数上要特别注意坐标是绝对像素还是归一化值。有些标注表混用两种训练前必须统一。我一般会在统计脚本里顺手加一句断言检查xmax xmin且坐标不超过图像宽高先把脏标注筛出来。2.2 类别长尾与“标注粒度”陷阱工业瑕疵数据集的类别不均衡不是简单的 1:10常见是 1:50 甚至更极端。断经、破洞这类显眼缺陷样本多油污、三丝这类细微缺陷样本少。更麻烦的是标注粒度不统一有的图把一片连续污渍标成一个大框有的图把它拆成几个小框。模型学到的“目标尺寸”概念就被搅乱了。处理长尾常见做法有三条路。第一条是损失层面用 Focal Loss 或类别加权 CE把稀有类的梯度放大。第二条是采样层面对稀有类做 oversampling但要注意同一张图里有多个类时不能简单复制否则会重复计算常见类。第三条是评估层面别只看 mAP要按类看 AP稀有类 AP 掉到 0.1 以下就说明模型根本没学会。我一般会先跑一版不加权的 baseline拿到每类 AP 的表格再决定加权系数。加权系数不是拍脑袋通常取sqrt(N_max / N_c)这种温和形式太激进会让模型在稀有类上过拟合到几个样本。2.3 强纹理背景下的图像特性布匹图像的背景是规则织物纹理经纬线重复、对比度低缺陷往往“嵌”在纹理里。这带来两个直接后果一是通用数据增强里的随机裁剪、旋转会破坏纹理方向性可能让模型学到错误的纹理先验二是颜色归一化很关键不同批次布料的底色差异大模型容易把“底色深”误判成“油污”。实际处理时我会保留水平翻转和轻度亮度扰动慎用大角度旋转和强色彩抖动。归一化用数据集自身的均值和方差而不是 ImageNet 的因为工业图像的色彩分布和自然图像差得远。输入分辨率上如果小目标多640 起步条件允许上到 1024配合多尺度训练。提示先把标注统计和几十张可视化图看完再写模型。工业数据集里“标注错误”和“标注粒度不一致”的比例往往比想象中高早发现能省掉后面几天的调参。3. 检测方案怎么选从 YOLO 系到两阶段的取舍数据看清了接下来是选型。布匹瑕疵检测在工业界主流还是单阶段检测器为主原因是产线要速度两阶段在精度上的优势在这个场景不一定兑现因为缺陷形态太不规则RPN 的候选框质量未必比密集 anchor 好。这一章讲清楚选型逻辑再给一套能跑通的最小训练流程。3.1 单阶段与两阶段在这个场景的真实差异单阶段YOLO 系、RetinaNet 系的优势是推理快、部署简单对小目标靠特征金字塔补。两阶段Faster R-CNN 系的优势是候选框经过 RoI Align 后分类更准适合形态复杂的目标。但在布匹瑕疵上缺陷边界往往模糊标注框本身就有几个像素的抖动两阶段精细的框回归优势被抵消了一部分。我的经验是如果缺陷以细长条断经、断纬和局部斑块油污为主单阶段配合可变形卷积或注意力模块性价比更高如果缺陷类别多且形态差异极大两阶段在稀有类上的召回可能更稳。实际项目里我会先跑 YOLO 系做 baseline因为它迭代快一天能出结果再决定要不要上两阶段做对比。选型还要看部署端。产线边缘设备算力有限单阶段量化后更容易压到实时。这一点在方案初期就要确认别训完发现部署不上去。3.2 用 YOLO 格式转换标注并跑通最小训练大多数检测框架吃的是 YOLO 格式每张图一个 txt每行class cx cy w h全部归一化。从原始 CSV 转过去是最容易翻车的一步坐标归一化、类别映射、空标注图处理都要小心。import os import pandas as pd from PIL import Image df pd.read_csv(train.csv) # 类别名到 id 的映射务必固定顺序训练和推理要一致 classes sorted(df[category].unique()) cls2id {c: i for i, c in enumerate(classes)} out_dir labels os.makedirs(out_dir, exist_okTrue) for img_id, group in df.groupby(image_id): img_path os.path.join(images, img_id) W, H Image.open(img_path).size lines [] for _, r in group.iterrows(): # 归一化并裁剪到 [0,1]防止脏标注越界 cx max(0, min(1, (r[xmin] r[xmax]) / 2 / W)) cy max(0, min(1, (r[ymin] r[ymax]) / 2 / H)) w max(0, min(1, (r[xmax] - r[xmin]) / W)) h max(0, min(1, (r[ymax] - r[ymin]) / H)) if w 0 or h 0: continue # 丢弃退化框 lines.append(f{cls2id[r[category]]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) # 空标注图也要生成空文件否则训练时会被当成无标签跳过 with open(os.path.join(out_dir, img_id.replace(.jpg, .txt)), w) as f: f.write(\n.join(lines))逻辑说明按图像分组遍历保证一张图的所有框写进同一个 txt坐标先算中心点和宽高再归一化顺序不能错越界坐标做裁剪而不是直接丢因为轻微越界是标注抖动丢掉会损失样本退化框宽或高为 0必须丢否则训练时算 IoU 会出 NaN。空标注图生成空文件这一步很多人漏掉导致背景图没参与训练模型在纯纹理区域误检率偏高。转换完用框架自带的数据集检查脚本过一遍确认类别 id 连续、没有越界、没有空文件缺失。然后跑最小训练# 以常见 YOLO 系框架的命令行为例具体参数名以所用框架为准 python train.py \ --data fabric.yaml \ --img 640 \ --batch 16 \ --epochs 100 \ --weights pretrained.pt \ --hyp hyp.fabric.yamlfabric.yaml里写训练/验证路径和类别数hyp.fabric.yaml是超参文件。第一版不要改太多超参先用默认跑通看 loss 曲线和验证集每类 AP。batch 根据显存调640 输入下 16 是常见起点。epochs 先 100 看收敛趋势别一上来就 300浪费时间。3.3 输入分辨率与 anchor 的联动调整小目标多的时候光调 anchor 不够得先看特征图分辨率。640 输入下P3 层是 80×80一个 8 像素宽的断经在 P3 上只占 1 个格子几乎学不到。两个办法上到 1024 输入或者加 P2 层160×160。前者显存翻倍后者增加计算量但更划算。anchor 方面先用 k-means 在训练集框上聚类出 9 个尺寸替换默认 anchor。聚类时用 IoU 距离而不是欧氏距离因为框的匹配看的是重叠度。聚类完检查最小 anchor 是否覆盖了 10% 分位的小框覆盖不到就手动加一组更小的。注意改输入分辨率后anchor 必须重新聚类否则匹配策略失效表现为 loss 不降或召回上不去。这是血泪经验别问怎么知道的。4. 训练调优与评估让稀有类不再“隐身”baseline 跑通只是起点。布匹瑕疵数据集的真实挑战在训练中后段常见类 AP 很快到 0.8稀有类卡在 0.2 不动整体 mAP 被平均得好看但产线上漏检的全是稀有类。这一章讲三件事损失与采样怎么配、数据增强的边界在哪、评估指标怎么按类拆开看。4.1 类别加权与 Focal Loss 的实操参数Focal Loss 的两个参数 α 和 γγ 控制难易样本的聚焦程度常用 1.5 到 2.0α 控制类别平衡多类场景一般按类别频率设。但工业瑕疵里我不建议直接用标准 Focal Loss因为稀有类样本太少γ 太大会把仅有的正样本梯度也压掉。更稳的做法是类别加权 CE 加适度的 Focal。加权系数用w_c (N_total / N_c)^0.5再归一化到均值 1。这样稀有类权重是常见类的几倍但不至于几十倍导致过拟合。训练时监控每类的正样本平均 loss如果稀有类 loss 一直不降说明权重还不够或者样本本身标注有问题。另一个常被忽略的点是负样本挖掘。布匹背景纹理强容易产生大量假阳性。OHEM在线难例挖掘在这个场景有效但要注意只对背景类做挖掘别把稀有正样本当难例压掉。4.2 数据增强的边界哪些增强会帮倒忙前面提过大角度旋转和强色彩抖动会破坏纹理先验。具体边界我一般这样定水平翻转必开垂直翻转看缺陷是否有方向性断经有破洞没有旋转限制在 ±10 度以内色彩抖动只调亮度和轻微对比度饱和度不动因为布料颜色是判断油污的重要线索。Mosaic 增强对小目标有帮助因为它把多张图拼一起变相增加了小目标密度。但 Mosaic 会让框的绝对尺寸变小如果原图小目标已经很多Mosaic 后可能小到无法识别。我的做法是训练前期开 Mosaic后期关掉让模型在真实分布上收尾。还有一个容易翻车的增强是随机裁剪。裁剪可能把缺陷裁掉一半标注框却还在模型学到的是“半个缺陷也是缺陷”推理时对完整缺陷反而不敏感。如果要用裁剪后必须重新计算框的可见比例低于 0.3 的直接丢。4.3 按类 AP 与混淆矩阵定位问题整体 mAP 是给汇报看的调优要看每类 AP 和混淆矩阵。混淆矩阵能告诉你稀有类是被漏检预测为背景还是被误分类预测成别的缺陷。漏检多说明召回不足查 anchor 匹配和正样本分配误分类多说明特征区分度不够查类别间的视觉相似性。# 用 sklearn 快速看分类头的混淆情况以检测框匹配后的类别为例 from sklearn.metrics import confusion_matrix, classification_report # y_true, y_pred 为匹配后的类别 id 列表-1 表示背景 cm confusion_matrix(y_true, y_pred, labelslist(range(num_classes)) [-1]) print(classification_report(y_true, y_pred, zero_division0))看报告时重点盯稀有类的 recall 和 precision。recall 低优先补召回precision 低优先查假阳性来源。如果某两类互相混淆严重考虑在特征层加类别间的对比损失或者干脆合并成一个大类再细分产线上有时“先检出再细分”比“一步到位”更稳。5. 避坑与排查那些让 mAP 虚高、产线翻车的细节这一章是踩坑记录每条都按现象、原因、解决写。这些问题在公开数据集上不一定暴露但迁移到真实产线就会集中爆发。5.1 验证集 mAP 很高产线漏检严重现象离线评估 mAP 0.85上线后稀有类漏检率超过 40%。原因通常是验证集和训练集同分布而产线图像的光照、布料批次、相机参数都变了模型过拟合到训练集的纹理和色彩先验。解决划分验证集时按批次或按时间段切分不要随机切上线前用一批未参与训练的新批次图做一次盲测色彩归一化用在线统计的均值和方差而不是固定训练集的值。5.2 loss 正常下降但验证集 AP 不动现象训练 loss 一路降验证集每类 AP 从第 20 轮开始横盘。原因多半是标注粒度不一致导致模型学到的框回归目标自相矛盾或者数据增强过强让验证分布和训练分布偏离。解决先关掉 Mosaic 和随机裁剪跑一版看 AP 是否恢复再抽查验证集的预测可视化看框是偏大偏小还是位置漂移如果是粒度问题考虑把评估改成按缺陷面积分桶看 AP而不是整体平均。5.3 小目标召回始终上不去现象面积小于 32×32 的框 recall 低于 0.3调 anchor 无效。原因是特征图分辨率不够小目标在高层特征上已经消失。解决加 P2 检测层或者把输入分辨率从 640 提到 1024同时检查正样本分配策略小目标容易被 IoU 阈值筛掉可以降低小目标的正样本 IoU 门槛或用中心点采样代替 IoU 采样。5.4 背景纹理被大量误检为油污现象纯纹理区域出现大量低置信度油污框precision 被拉低。原因是油污和深色纹理在低分辨率下特征相似且负样本挖掘不足。解决加入纯背景图作为负样本参与训练提高分类头的背景类权重推理时对低置信度框做基于纹理特征的二次过滤比如计算框内梯度方向一致性纹理规则的区域直接压掉。5.5 多标签图里常见类“吃掉”稀有类现象一张图同时有断经和油污时模型只检出断经油污框消失。原因是 NMS 阶段不同类之间虽然不互相抑制但正样本分配时常见类占据了主要梯度稀有类学习不足。解决检查正样本分配是否按类独立进行训练时对同图多类样本做类别平衡采样推理阶段对稀有类适当放低置信度阈值再统一做后处理。6. 从数据集到产线蒸馏、量化与一套可复用的验证习惯数据集训到 mAP 满意只是走完一半。真正决定这个方向值不值得投入的是模型能不能在产线算力上跑起来、能不能在批次切换时稳住。我一般会做两件事先把大模型的知识蒸馏到小模型再做量化最后用一套固定的盲测流程验收。蒸馏的做法是拿训好的大模型当教师小模型当学生损失由检测损失加蒸馏损失组成。蒸馏损失作用在分类头的 logits 和特征图上温度 T 取 2 到 4权重从 0.5 开始试。工业场景里教师模型不必太大关键是教师在新批次上的泛化要稳否则蒸馏会把过拟合也传下去。# 蒸馏损失的核心形式分类头部分T 为温度alpha 为权重 import torch.nn.functional as F def distill_loss(student_logits, teacher_logits, labels, T3.0, alpha0.5): # 硬标签损失 hard F.cross_entropy(student_logits, labels) # 软标签蒸馏损失教师梯度不回传 soft F.kl_div( F.log_softmax(student_logits / T, dim1), F.softmax(teacher_logits / T, dim1), reductionbatchmean, ) * (T * T) return (1 - alpha) * hard alpha * soft参数说明T 越大软标签越平滑稀有类的类间关系信息传得越多但太大超过 5会让学生学不到尖锐边界alpha 控制蒸馏强度小模型容量有限时 alpha 别超过 0.7否则硬标签学不扎实。蒸馏后必须重新在验证集上按类看 AP确认稀有类没掉。量化方面训练后静态量化对小模型友好但检测头的框回归对量化误差敏感建议只量化 backbone检测头保留浮点或者用量化感知训练。量化后一定要用同一批盲测图对比浮点模型和量化模型的每类 AP掉超过 3 个点就要回退检查敏感层。验收习惯上我固定用三组数据训练同批次、跨批次、极端光照。每组至少 200 张人工复核漏检和误检。三组都过才认为可以上线。这个习惯比任何单次 mAP 都可靠因为产线不看你验证集多漂亮只看漏没漏。说到底布匹瑕疵数据集-2019天池这类数据的价值不在刷分而在逼你把小目标、长尾、纹理干扰这几个工业视觉的老问题一次性面对。我自己的教训是每次想跳过数据统计直接训模型最后都会在排查阶段加倍还回来。先把标注翻烂再谈模型。希望帮到你。本文还有配套的精品资源点击获取