
简介这份资源是面向计算机视觉开发者与工业质检方向学习者的轮胎缺陷检测数据集采用Pascal VOC与YOLO双格式标注可直接用于目标检测模型的训练、验证与算法对比实验适合具备一定深度学习基础、正在做缺陷检测项目或课程设计的人员使用。压缩包内共约2000个文件以1999个xml标注文件和1个说明用txt为主整体大小约105.65MB另配套2154张jpg图片及对应的yolo格式txt标注图片与标注一一对应无需额外转换即可接入主流检测框架。数据集共标注debris、ground、side、side_cut四类缺陷框数分别为1599、564、188、493总框数2844标注由labelImg完成类别分布清晰便于分析长尾问题与调整采样策略。目前已有666人学习下载可作为轮胎表面缺陷识别、工业异常检测等任务的练手与基线复现素材帮助读者快速搭建数据管线、验证模型效果并积累调参经验。1. 轮胎缺陷检测数据集2154 张 VOCYOLO 双格式到底能跑出什么结果拿到一个标注好的轮胎缺陷检测数据集第一反应通常不是「太好了」而是「这 2154 张到底够不够、四个类别分得开吗、VOC 和 YOLO 两套格式该用哪个」。轮胎缺陷检测在工业质检里属于典型的小目标、低对比度、类间差异细微的场景缺陷区域往往只占整张图很小一块背景纹理又高度重复。这个数据集提供 VOC 和 YOLO 两种标注格式、共 2154 张图、4 个缺陷类别本质上解决的是「从零搭建轮胎表面缺陷检测模型时标注数据从哪来」的问题。它适合两类人一是想快速验证 YOLO 系列在自己产线图像上能不能用的算法工程师二是需要一份带边界框标注的工业缺陷数据来做课程设计或方案预研的开发者。下面按「先看清数据长什么样、再决定怎么训、最后避开标注和训练里的坑」这条线走一遍。2. 拆开压缩包之前VOC 与 YOLO 双格式的差异与选型2.1 两种格式的目录结构和标注逻辑VOC 格式的核心是每张图对应一个同名 XML 文件标注信息写在object节点里包含类别名和边界框的xmin/ymin/xmax/ymax四个像素坐标。YOLO 格式则是每张图对应一个同名 txt 文件每行一个目标格式是类别索引 中心x 中心y 宽 高四个值全部归一化到 0 到 1 之间。这两种格式描述的是同一批标注只是坐标系和存储方式不同。VOC 保留绝对像素坐标方便回溯原图尺寸YOLO 归一化后与图像分辨率解耦训练时不用再做缩放换算。一个 2154 张、4 类别的数据集如果按 VOC 组织目录大致是Annotations/放 XML、JPEGImages/放原图、ImageSets/Main/放训练验证划分。如果按 YOLO 组织通常是images/和labels/两个平行目录再加一个classes.txt或data.yaml记录类别名。压缩包里同时给两套意味着你可以直接用 YOLO 格式开训也可以用 VOC 格式接那些只吃 XML 的老框架。2.2 选 VOC 还是 YOLO看你的训练框架和后续需求选型其实不复杂。用 Ultralytics 系的 YOLOv5/v8/v11 训练直接上 YOLO 格式省掉转换步骤。用 PaddleDetection、MMDetection 或者一些传统机器视觉流程VOC 格式兼容性更好。如果你后面要做数据增强后重新生成标注VOC 的绝对坐标更容易做几何变换的校验YOLO 的归一化坐标在旋转、裁剪后需要重新归一化容易出错。提示两套格式的类别顺序必须一致。VOC 里类别靠名字匹配YOLO 里靠索引匹配一旦classes.txt的顺序和 XML 里类别名的字母序对不上训练出来的模型会把类别搞混而且这种错误在 loss 曲线上看不出来。我一般会先做一次交叉校验随机抽 20 张图把 YOLO 的归一化坐标还原成像素坐标和对应 XML 的xmin/ymin/xmax/ymax对比误差超过 2 个像素就说明转换环节有问题。这个检查花不了几分钟但能挡掉后面几小时的无效训练。2.3 用脚本做一次格式交叉校验import os import xml.etree.ElementTree as ET from PIL import Image # 校验 VOC XML 与 YOLO txt 是否描述同一批标注 def voc_to_xyxy(xml_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w, h int(size.find(width).text), int(size.find(height).text) boxes [] for obj in root.findall(object): name obj.find(name).text bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) boxes.append((name, xmin, ymin, xmax, ymax)) return w, h, boxes def yolo_to_xyxy(txt_path, img_w, img_h): boxes [] with open(txt_path) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls_id, cx, cy, bw, bh map(float, parts) xmin (cx - bw / 2) * img_w ymin (cy - bh / 2) * img_h xmax (cx bw / 2) * img_w ymax (cy bh / 2) * img_h boxes.append((int(cls_id), xmin, ymin, xmax, ymax)) return boxes # 抽样校验 sample_ids [000001, 000002, 000003] # 替换为实际文件名 for sid in sample_ids: xml_path fAnnotations/{sid}.xml txt_path flabels/{sid}.txt img_path fJPEGImages/{sid}.jpg if not all(os.path.exists(p) for p in [xml_path, txt_path, img_path]): continue img Image.open(img_path) w, h, voc_boxes voc_to_xyxy(xml_path) yolo_boxes yolo_to_xyxy(txt_path, w, h) print(f{sid}: VOC {len(voc_boxes)} boxes, YOLO {len(yolo_boxes)} boxes) for vb, yb in zip(voc_boxes, yolo_boxes): diff max(abs(vb[1]-yb[1]), abs(vb[2]-yb[2]), abs(vb[3]-yb[3]), abs(vb[4]-yb[4])) if diff 2: print(f 坐标偏差过大: {diff:.1f}px, VOC{vb}, YOLO{yb})这段脚本做的是逐框对比。voc_to_xyxy从 XML 里读出图像宽高和绝对坐标yolo_to_xyxy把归一化坐标乘回图像宽高还原成像素坐标。两个列表按顺序配对后算最大偏差超过 2 像素就报警。参数上唯一需要注意的是图像宽高必须从原图读取不能硬编码因为不同批次采集的轮胎图像分辨率可能不一致。如果校验通过说明两套格式描述一致可以放心选一套用。3. 用 YOLOv8 在 2154 张轮胎缺陷图上跑通训练3.1 数据集划分与 data.yaml 配置2154 张图按 8:1:1 划分训练集约 1723 张验证集 215 张测试集 216 张。划分时要注意同一轮胎、同一拍摄批次的图像不能同时出现在训练集和验证集里否则验证指标会虚高。如果数据里有连续帧或同一位置的多角度拍摄按轮胎编号分组划分更稳妥。YOLO 格式的data.yaml是训练的入口配置path: /data/tire_defect train: images/train val: images/val test: images/test nc: 4 names: 0: bubble 1: crack 2: foreign_object 3: wearpath是数据集根目录train/val/test是相对路径。nc是类别数必须和实际标注的类别数一致。names的索引顺序必须和 YOLO txt 里的类别索引严格对应这个顺序一旦写错模型学到的就是错位的类别映射。我一般会在生成data.yaml之前先统计一遍所有 txt 里出现过的类别索引确认最大值等于nc-1且每个索引都有对应样本。3.2 训练命令与关键参数设置yolo detect train \ data/data/tire_defect/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience30 \ device0 \ projectruns/tire \ nameexp01modelyolov8s.pt用的是预训练权重2154 张图从零训容易过拟合预训练能显著加快收敛。imgsz640是输入分辨率轮胎缺陷区域小如果显存允许可以提到 960 或 1280小目标召回会明显改善。batch16在单张 8G 显存卡上比较稳显存不够就降到 8 并配合accumulate做梯度累积。lr00.01是初始学习率lrf0.01是最终学习率系数余弦退火到初始值的百分之一。patience30表示验证指标 30 轮不提升就早停避免无效训练。注意imgsz必须是 32 的整数倍否则 YOLO 内部会报维度不匹配。640、960、1280 都是安全值。训练启动后重点看三个信号box_loss是否稳定下降、mAP50是否在 50 轮内超过 0.5、验证集的cls_loss是否和训练集差距过大。如果box_loss震荡不降先检查标注框有没有越界或宽高为负的情况。如果mAP50卡在低位多半是类别不平衡或小目标太多需要调imgsz或做针对性增强。3.3 训练结果解读与混淆矩阵排查训练结束后runs/tire/exp01/下会生成confusion_matrix.png、results.png和weights/best.pt。混淆矩阵是排查类别混淆的第一手材料。4 个类别如果出现某一类大量被预测成背景说明该类样本太少或标注质量差如果两类之间互相混淆严重说明它们在视觉上区分度不够需要补充难例或调整类别定义。from ultralytics import YOLO model YOLO(runs/tire/exp01/weights/best.pt) metrics model.val(data/data/tire_defect/data.yaml, splittest) print(fmAP50: {metrics.box.map50:.4f}) print(fmAP50-95: {metrics.box.map:.4f}) for i, name in enumerate(metrics.names.values()): print(f{name}: AP50{metrics.box.ap50[i]:.4f})这段代码加载最优权重在测试集上跑一次验证输出整体和各类别的 AP。metrics.box.ap50是按类别索引排列的数组顺序和data.yaml里的names一致。如果某一类 AP 明显低于其他类优先检查该类别的标注框数量是否过少以及标注框是否普遍偏小。轮胎缺陷里裂纹和磨损这两类在灰度图上对比度接近混淆概率高可以考虑在数据增强里加对比度扰动。4. 轮胎缺陷检测训练避坑5 个真实踩过的坑4.1 坑一YOLO 类别索引与 names 顺序错位现象训练 loss 正常下降但推理时所有预测框的类别都是错的比如裂纹被标成气泡。原因生成 YOLO txt 时用的类别索引顺序和data.yaml里names的顺序不一致。常见于从 VOC 转换时按文件夹遍历顺序分配索引而data.yaml手写时按字母序排列。解决写一个统计脚本遍历所有 txt 收集出现过的类别索引再和data.yaml的names长度对比。更稳妥的做法是从classes.txt统一生成data.yaml保证两边同源。4.2 坑二小目标缺陷在 640 分辨率下大量漏检现象mAP50能到 0.7 左右但实际推理时小面积缺陷几乎检不出来可视化后发现小目标框全部丢失。原因轮胎缺陷里细小裂纹和点状异物在原图上可能只有十几个像素缩放到 640 后特征几乎消失。YOLO 的 P3 特征图 stride 是 8对应最小检测尺度约 8 像素再小就无能为力。解决把imgsz提到 960 或 1280同时开启mosaic和copy_paste增强。如果显存不够改用 YOLOv8 的s以下模型或者切图推理。另一个办法是在标注阶段就把过小的目标合并或剔除避免模型被无法学习的样本干扰。4.3 坑三验证集指标虚高实际产线翻车现象验证集mAP500.85部署到产线后误检率极高大量正常轮胎被判为缺陷。原因数据集划分时同一轮胎的多张图被分到了训练集和验证集模型记住了这个轮胎的背景特征验证集相当于在「见过的轮胎」上测试。产线上遇到新轮胎背景分布变了模型就崩了。解决按轮胎编号或拍摄批次做分组划分确保同一轮胎只出现在一个子集里。如果数据里没有编号信息按图像采集时间排序后做间隔划分避免连续帧泄漏。4.4 坑四标注框越界导致训练中途报错现象训练跑到几十轮突然报RuntimeError: box coordinate out of range或 loss 变成 NaN。原因VOC 转 YOLO 时某些标注框的xmax超过了图像宽度归一化后中心坐标加半宽大于 1YOLO 内部计算 IoU 时出现非法值。解决转换脚本里加一道裁剪逻辑把xmin/xmax限制在[0, w]ymin/ymax限制在[0, h]再重新归一化。转换完成后统计一遍所有框的宽高出现 0 或负值直接定位到对应文件人工复核。4.5 坑五类别不平衡导致少数类几乎学不到现象4 个类别里某一类样本只有几十张训练后该类 AP 接近 0混淆矩阵里全部被预测成其他类或背景。原因YOLO 默认的分类损失对所有类别等权少数类梯度被多数类淹没。解决在data.yaml同级目录建一个hyps.yaml调低cls损失权重的同时对少数类做过采样。更直接的办法是用copy_paste增强把少数类样本复制粘贴到其他图上扩充到和其他类同一量级。如果少数类确实难以扩充考虑合并到语义相近的类别里减少类别数。5. 把 2154 张用到极致小样本下的增强策略与验证习惯2154 张 4 类别平均每类五百多张在工业缺陷检测里算中等偏少。想让模型真正可用光靠默认增强不够。我一般会在 YOLO 自带增强之外再加两层一是针对轮胎表面纹理的blur和brightness扰动模拟不同光照和镜头状态二是针对缺陷形态的elastic_transform让裂纹和磨损的边界产生形变提升模型对形状变化的鲁棒性。import albumentations as A import cv2 transform A.Compose([ A.HorizontalFlip(p0.5), A.VerticalFlip(p0.3), A.RandomBrightnessContrast(brightness_limit0.2, contrast_limit0.2, p0.5), A.GaussNoise(var_limit(10.0, 50.0), p0.3), A.ElasticTransform(alpha1, sigma50, p0.2), A.Rotate(limit15, p0.3), ], bbox_paramsA.BboxParams(formatyolo, label_fields[class_labels])) img cv2.imread(JPEGImages/000001.jpg) with open(labels/000001.txt) as f: lines [l.strip().split() for l in f if l.strip()] bboxes [[float(x) for x in l[1:]] for l in lines] labels [int(l[0]) for l in lines] aug transform(imageimg, bboxesbboxes, class_labelslabels) print(f增强后框数: {len(aug[bboxes])})这段增强用 albumentations 做BboxParams指定formatyolo后边界框会随图像变换自动调整。ElasticTransform的alpha控制形变强度sigma控制平滑度轮胎缺陷建议alpha1, sigma50太强会让缺陷形态失真。Rotate限制在 15 度以内因为轮胎图像通常有固定拍摄角度大角度旋转会产生不真实的样本。验证习惯上我坚持做两件事。第一每次训练完在测试集上跑一遍逐类 AP记录到表格里对比不同实验的类别短板。第二从测试集里抽 30 张做人工复核把漏检和误检的图单独存一个badcase/目录下一轮训练前优先对这些场景做增强或补标。这个习惯坚持几轮后模型在产线上的误检率通常能降一半以上。增强手段推荐参数适用缺陷类型注意事项亮度对比度扰动brightness 0.2, contrast 0.2全部过强会掩盖低对比度缺陷高斯噪声var 10-50裂纹、异物噪声过大会被误学成缺陷弹性形变alpha1, sigma50裂纹、磨损强度过大会产生非真实形态旋转limit15全部超过 15 度与拍摄角度不符水平翻转p0.5全部轮胎纹理通常对称安全最后说一个我自己的教训早期做轮胎缺陷检测时我花了两周调模型结构结果提升还不如把 200 张漏标和错标的图重新标一遍。数据质量的上限决定了模型的上限2154 张图里如果有百分之五的标注有问题再好的增强和调参都是在噪声上拟合。每次开训前花半天做标注抽检比训练中途反复调参划算得多。希望帮到你。本文还有配套的精品资源点击获取