
简介目标检测数据集面向齿轮缺陷识别场景按YOLOV5目录格式整理适合需要小目标检测、密集检测或多类别缺陷标注的学习者与项目开发者直接使用。数据以单一背景下的红色齿轮图像为对象标注了表面擦伤scratch、齿轮掉牙break、齿轮不足lack三类缺陷训练集对应2382个标签、验证集对应596个标签每张图像包含多个目标框可用于模型训练与验证。zip压缩包共2000个文件包括1999个txt标注文件和1个show.py可视化脚本整体约41.27MBtxt文件为YOLO格式的边界框与类别标签脚本可随机读取图片绘制边界框并保存结果目录结构清晰无需额外处理即可接入YOLOV5训练流程。已有910人浏览学习适合作为缺陷检测入门或工业质检项目的参考数据。1. 目标检测数据集YOLOV5目录格式到底给了你什么一份能直接训练的齿轮缺陷标注而不是一堆散图拿到一个写着“目标检测数据集YOLOV5目录格式齿轮缺陷检测3类别包含训练集、验证集”的资源很多人的第一反应是打开压缩包看有多少张图。但这类数据集真正的价值是它已经把“图片 标注 数据集划分”按 YOLOv5 能直接吃进去的目录结构整理好了。你在工业现场拍完齿轮照片最耗时间的往往不是训练而是标注和格式整理这份数据集等于帮你跳过了那一步可以直接拿来跑通训练流程、验证模型选型、评估缺陷检测的可行性。适合三类人刚入门 YOLOv5 想跑通全流程的初学者、要做齿轮外观检测但还没有现场数据的工程师、以及想先做可行性验证再决定要不要投入标注成本的团队。接下来我会把它拆开从目录格式、类别定义、训练配置到踩坑点完整讲一遍。2. 拆开 YOLOV5 目录格式images 与 labels 的对位关系、train/val 划分与 data.yaml2.1 一份标准 YOLOv5 数据集目录骨架长什么样YOLOv5 对数据集的目录结构有明确约定不是把图片和标注文件随便扔在一起就能训练。一个能被train.py直接接受的目录通常长这样dataset_root/ ├── images/ │ ├── train/ │ │ ├── gear_0001.jpg │ │ ├── gear_0002.jpg │ │ └── ... │ └── val/ │ ├── gear_0101.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── gear_0001.txt │ │ ├── gear_0002.txt │ │ └── ... │ └── val/ │ ├── gear_0101.txt │ └── ... ├── classes.txt ├── data.yaml └── README.md这个结构里有几个硬性约定先说清楚后面才不会踩坑。第一images和labels是两个平行目录里面的子目录名必须完全一致。你在images/train里放图就必须在labels/train里放同名.txt标注文件验证集同理。YOLOv5 训练时是拿图片路径去推导标签路径的规则就是字符串替换把/images/换成/labels/把图片后缀.jpg/.png/.bmp换成.txt。只要对位关系错一张训练就会少一个监督信号而且不报错这是最隐蔽的问题。第二labels里每个.txt文件的内容是归一化后的目标框参数格式是class x_center y_center width height全部用小数数值范围在 0 到 1 之间。四列数据分别代表类别编号、目标框中心点的 x 坐标、中心点的 y 坐标、框宽、框高五列都以图片宽高做归一化。注意类别编号必须从 0 开始连续编号。如果你的 3 个类别编号是 0、1、2没问题但如果你标的类别编号是 1、2、3或者中间跳了号YOLOv5 会直接报错或产生静默的错误训练。第三data.yaml是训练时的数据描述文件里面至少要有三样东西类别数量nc、类别名称names、图片路径train和val。一个典型的齿轮缺陷数据集的 yaml 长这样train: dataset_root/images/train val: dataset_root/images/val nc: 3 names: [surface_crack, tooth_wear, broken_tooth]train和val路径写的是images目录YOLOv5 会自动推导labels目录。所以这里的路径必须指向images下的子目录而不是dataset_root本身也不是labels。2.2 用脚本核对目录对位五秒找出丢标注的图片拿到数据集之后第一件事不是看图片而是核对图片和标注是否一一对应。我一般用一条 bash 命令做初筛cd dataset_root # 找出 images/train 下有图片但 labels/train 下没有对应 txt 的文件名 for img in images/train/*.jpg; do name$(basename $img .jpg) if [ ! -f labels/train/$name.txt ]; then echo missing label: $img fi done这段逻辑很简单遍历images/train下的每张 jpg 图拿到不带后缀的文件名去labels/train目录下找同名.txt文件找不到就打印出来。跑完这条命令如果有输出说明目录对位有问题没有输出说明图片侧没有缺失标签。这里有一个新手容易忽略的点YOLOv5 允许图片有对应标签也允许标签文件里是空文件文件存在但没有任何行表示这张图没有目标。但空标签文件会导致训练时该图被跳过或产生空梯度所以如果目录里存在大量空的.txt文件我建议单独统计一下。# 统计空标签文件数量排除正常无目标的图 find labels -name *.txt -size 0 | wc -l如果空标签文件的占比超过 5%你就要留意这批空标签是故意标注的无缺陷样本还是遗漏标注。区别非常大。故意标注的无缺陷样本在工业缺陷检测里很有价值它能教会模型识别“合格品”减少正常齿轮的误检但如果是漏标这些图会成为负样本噪音训练出来模型会在这些区域产生无意义的预测框。判断依据很简单把空标签文件对应的图片拉出来用 ROI 方式把齿面区域放大肉眼看是不是确实没有缺陷。没有缺陷保留有明显缺陷却没标这就是数据集质量问题建议剔除或补标。2.3 为什么这个数据集只给了训练集、验证集没有测试集标题里写的是“包含训练集、验证集”没有提到测试集。这不是疏漏而是目标检测数据集最常见的划分方式。YOLOv5 的训练流程本身就是训练集喂数据、验证集做评估训练完不单独保留测试集是常态。真正的测试集通常是在模型部署到产线之前用一批现场采集但从未参与训练和验证的图片单独评测。原因也很直接验证集参与过模型选型和超参数调整会有一定程度的隐式过拟合测试集完全没见过才能反映真实工况精度。所以这份数据集的使用边界应该是用它来训练模型、对比不同 backboneyolov5svsyolov5m、调超参数这些用训练集和验证集就够了。但要评估“上产线能不能用”你还需要自己留一批新图。如果你的项目只有这批数据一个可行的做法是去掉验证集把它合并进训练集做 K 折交叉验证。比如 3 折每折拿出 1/3 做验证训练 3 次取平均精度。缺点是要训练多轮但数据量少的时候这比一次性固定的验证集更能反映模型真实水平。3. 3 类别齿轮缺陷的标注口径训练前先核对类别定义比直接跑训练更重要3.1 齿轮缺陷标注最常见的三分法表面裂纹、齿面磨损、断齿“齿轮缺陷检测3类别”听起来明确但不同数据集对“3 类别”的定义可能完全不同。工业上最常见的是按缺陷形态分三类表面裂纹、齿面磨损、断齿或崩角。这三类有明确的视觉特征和成因标注边界相对清晰也是检测模型最容易学出来的划分方式。表面裂纹的视觉特征是齿面或齿根出现线状暗纹形状细长、方向不规则有时需要分辨率足够高才能看清齿面磨损是齿面接触区域出现大面积的亮斑或暗斑边缘模糊没有清晰的边界这和裂纹的“线状”有本质区别断齿是齿体缺失缺口形状突兀这是三种缺陷里最好检测的因为它的边缘非常明确目标框大概率是窄而长的形状。如果你拿到的数据集不是按这个口径分的比如用了“划伤、点蚀、断齿”或者“齿面点蚀、齿根裂纹、齿顶磨损”不要慌。先打开classes.txt或data.yaml里的names看类别名再用下面的脚本统计每个类的样本数。关键不是类别叫什么而是每个类别在你实际部署场景里是否独立、是否容易混淆。如果“齿面磨损”和“点蚀”在图片里大量共现、边界模糊你就要考虑合类。3.2 用 Python 脚本统计类别分布识别样本失衡和标注错误在看任何训练曲线之前先用脚本把标注文件里的类别分布和框的尺寸分布摸清楚。这一步能提前暴露数据集里最致命的两个问题类别严重失衡、目标框尺寸异常。import os from collections import Counter from pathlib import Path label_dirs [labels/train, labels/val] class_counter Counter() box_sizes [] for ld in label_dirs: for txt_path in Path(ld).glob(*.txt): with open(txt_path) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(f格式异常: {txt_path}, 行内容: {line.strip()}) continue cls_id int(parts[0]) w float(parts[3]) h float(parts[4]) class_counter[cls_id] 1 box_sizes.append((w, h)) print(类别分布 (类别id: 数量):) for cls_id, cnt in sorted(class_counter.items()): print(f class {cls_id}: {cnt}) # 检查类别是否从0连续 expected set(range(len(class_counter))) actual set(class_counter.keys()) if actual ! expected: print(f警告: 类别编号不连续或缺失, 预期 {sorted(expected)}, 实际 {sorted(actual)})这个脚本做三件事遍历训练和验证的标签文件逐行解析标注统计每个类别的目标数量检查类别编号是否从 0 开始连续。另外它还顺带检查了每行是不是正好 5 列这是 YOLO 格式最容易出错的地方——比如标注工具导出时多了一个空格或少了一列训练时就会报数据集错误。在齿轮缺陷检测场景里我对类别分布有一个经验底线最小的类别目标数不要少于训练图片数的 1/10。比如训练集有 800 张图最少的类别至少要有 80 个标注实例。低于这个比例这个类在训练时能被模型有效学到的概率很低。你可能看到过很多文章说“样本不平衡用 Focal Loss 解决”但那是分类任务在检测任务里如果一个类别只有 20 个框模型很可能把它的特征当成背景噪声连候选框都提不出来。对于这个数据集如果你发现某个类严重偏少优先考虑数据增强里的copy_paste或 mosaic 增强是否打开了更强档位而不是直接改损失函数。3.3 标签与图片质量不对等时的处理策略统计完分布还要抽查图片和标签是否匹配。把标注框画到原图上最容易暴露问题不用自己写可视化脚本直接用 YOLOv5 仓库自带的detect.py就能干但不训练直接可视化更轻量的做法是写个简单的 OpenCV 脚本import cv2 img cv2.imread(images/train/gear_0001.jpg) h, w img.shape[:2] with open(labels/train/gear_0001.txt) as f: for line in f: cls_id, cx, cy, bw, bh map(float, line.strip().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) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(check_gear_0001.jpg, img)看到画出来的框重点观察两类问题一是框完全包住缺陷了吗如果裂纹延伸到框外模型学到的特征是残缺的推理时同一个缺陷可能被切成两个框二是框是不是太大把正常的齿面也框进去了这种标注会把背景信息混进前景导致模型学到的不是“裂纹”而是“裂纹周围那一圈区域”部署时误检率会直接上升。按我的经验齿轮缺陷标注里最常见的问题就是“框太大”。裂纹是长条形标注员容易下意识把整个齿面框进去。这类标签不是不能训练但建议在训练前处理一下把标注框往里收紧让缺陷占框面积的 70% 以上训练效果会有明显改善。如果数据量大、不想手工改可以用聚类方法重新统计框的宽高比分布但这个数据集只有 3 个类别我建议还是花时间跑一遍清洗因为缺陷检测对边界敏感程度远超通用物体检测。4. 用这个数据集跑通 YOLOV5 训练从 data.yaml 到验证集评估指标4.1 训练前先决定三件事backbone、输入分辨率、epoch把目录格式和标注质量确认完之后就可以开始训练了。但不要急着敲命令先做三个决定这三个决定直接决定训练效果和耗时。第一选哪个模型。YOLOv5 按深度和宽度分成n/s/m/l/x五个尺寸齿轮缺陷检测我一般推荐从yolov5s起步。理由很实际齿轮缺陷的目标都比较小但背景比较单一不需要特别大的感受野s的参数量和推理速度适合先在本地验证可行性如果精度不够再换m。不要一上来就选x齿轮产线往往有部署成本约束x的推理速度在小算力设备上很难跑实时。第二输入分辨率。这可能是齿轮缺陷检测里最重要的一步。如果数据集里的裂纹宽度只有十几个像素用默认的 640 输入训练时图片被压缩裂纹的纹理可能被直接抹掉模型根本看不到缺陷特征。我一般会先统计标注框的像素尺寸用第 3 章的脚本把box_sizes乘以图片宽高看最小的框能小到什么程度。如果最小框边长小于 30 像素建议把输入分辨率提到 1280。代价是训练明显变慢、显存占用翻倍。第三epoch 数。齿轮缺陷检测不是通用物体检测缺陷特征相对集中模型收敛不需要跑满 300 epoch。我一般先用 150 epoch 跑一轮观察第 80 epoch 附近的验证结果。如果验证精度还在明显上升就继续加如果在 80 之前就已经开始过拟合验证 loss 掉头上升就调回 100 左右。这个参数和数据量直接挂钩没有放之四海皆准的值。4.2 从克隆代码到训练命令全流程跑通假设数据集已经按第 2 章的目录结构放好接下来在终端里按顺序执行# 1. 拉取YOLOv5仓库在conda环境完成 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt # 2. 在data目录下写一个齿轮缺陷的yaml或者直接指向数据集根目录外的data.yaml # 注意yaml路径要写绝对路径或相对yolov5仓库的路径不要写~/开头的路径训练脚本不展开波浪号 # 这里以数据集自带data.yaml为例路径按实际改 vi data/gear_defect.yamldata/gear_defect.yaml的内容如下注意类别名称要和标注文件的类别编号严格对应顺序不能乱否则模型会把“表面裂纹”学到“断齿”的编号上train: /path/to/dataset_root/images/train val: /path/to/dataset_root/images/val nc: 3 names: 0: surface_crack 1: tooth_wear 2: broken_tooth然后开始训练python train.py \ --data data/gear_defect.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 150 \ --cache \ --device 0逐行解释一下--data指向刚才写的 yaml--weights yolov5s.pt表示加载 COCO 预训练权重做迁移学习第一次运行会自动下载--img 640是输入分辨率--batch 16是批次大小显存不够就降到 8--cache是把图片缓存进内存齿轮数据集通常不大缓存后训练速度能快 30% 到 50%--device 0指定第一张 GPU没有 GPU 就换成--device cpu但 150 epoch 会非常耗时建议至少在云 GPU 或本地小规模 GPU 上跑。训练开始后终端会输出每个 epoch 的训练 loss、验证 mAP、P精确率、R召回率。这几个指标一定都要看不能只看 mAP。齿轮缺陷检测是工业质检场景漏检召回率低比误检更致命——一个裂纹漏过去可能意味着一个不合格品下线了。所以我更关注 P/R 曲线的平衡点而不是 mAP 一个数字。4.3 验证集在训练过程中的角色不只是给你看数字训练过程中验证集扮演了三个角色一是 loss 监控验证 loss 不下降说明模型没在学二是模型保存依据YOLOv5 默认保存验证 mAP 最高的权重而不是最后一个 epoch 的权重三是过拟合预警训练 loss 持续下降而验证 loss 掉头上升就是过拟合信号需要立刻停止或调低学习率。训练结束后YOLOv5 会在runs/train/exp输出一堆文件其中对我最有用的三个是confusion_matrix.png、results.csv、weights/best.pt。混淆矩阵直接告诉你在哪些类别之间互相误检。齿轮缺陷场景里最典型的是“表面裂纹”和“齿面磨损”互相混淆因为二者经常出现在相同区域视觉上都是暗色纹理。看到这种混淆我一般不会急着加数据而是先检查标注如果同一张图里裂纹和磨损同时存在但标注员只标了其中一种模型就会学到错误关联。results.csv里每一行是一次 epoch 的完整评估记录我会用它画 P/R 曲线观察不同置信度阈值下误检和漏检的变化。这三样东西比跑完训练看到的最后一行终端输出有用得多它决定了你下一步是直接部署还是回头补标注。5. 齿轮缺陷数据集训练的避坑记录5 个我踩过的真问题数据格式正确不代表训练结果正确。这一类数据集我在实际项目里见过太多隐蔽问题下面 5 条每条都是“现象 → 原因 → 解决”的完整记录你如果在训练中遇到类似的可以直接对照处理。5.1 损失正常下降但检测框乱飘现象训练 loss 曲线完全正常但用验证集跑detect.py画出来的框位置和齿轮完全对不上像随机落点。原因标签文件里的坐标没有归一化或者归一化时用的分母不是真实图片宽高。标注工具如果导出的坐标是绝对像素值而 YOLOv5 按 0 到 1 解析就会把几千像素的坐标当成 0 到 1 的小数用。解决写脚本重新归一化把标签里的 x、y、宽、高全部除以对应图片的宽和高跑一遍再核对。5.2 验证 loss 先降后升模型明显过拟合现象前 80 epoch 一切正常之后训练 loss 继续降但验证 loss 开始反弹。原因数据集太小或者数据增强不够。齿轮缺陷数据集往往只有几百到一千张图模型很容易把训练图的背景纹理背下来。解决优先检查训练时的增强参数。YOLOv5 默认增强偏保守建议把--hyp换成增强更强的hyp.scratch-med.yaml或者在hyp里把mosaic概率提到 1.0、把hsv_h和hsv_s区间适当增大。注意mosaic对齿轮这类细小纹理缺陷有副作用——拼接后的图片会把齿轮切成四块裂纹被切断后标注框边缘变得不精确所以如果开大mosaic后验证精度反而下降就退回原来的设置。5.3 小裂纹目标完全漏检框永远偏大现象训练完的模型能检出断齿但表面裂纹一个都检不出来。原因输入分辨率太低导致小目标特征在图里只有几个像素骨干网络下采样后特征直接消失。YOLOv5 的下采样倍率是 32一个在 640 分辨率的输入里只有 10 像素宽的目标在特征层里还不到 1 个像素理论上就不可能被检出。解决把--img从 640 提到 1280并在 yaml 里启用小目标检测相关的锚框设置。1280 分辨率会让训练速度慢一倍显存占用翻倍但对于小裂纹缺陷这是必要成本。5.4 训练和验证时正常换到新工况就掉点现象验证集 mAP 很高但把模型部署到新的齿轮生产线误检率直线上升。原因数据集的拍摄条件和现场不一致。最常见的是光照角度不同——齿轮是金属表面光照角度一变同样的裂纹在图像上可能从暗纹变成亮纹。解决如果现场允许在部署前用现场光环境下的新图做一次小规模微调。只拿验证集里和你现场工况接近的图重新标一遍用预训练权重继续训练 50 epoch。不要直接拿原数据集从头训练那样会把旧工况的纹理学到固话换场景后反而更难适应。5.5 类别总数大于 3模型把一类缺陷拆到两个编号现象训练时nc: 3但混淆矩阵里出现了“类间互相检测”比如同一个裂纹时而被标成 0 类时而标成 2 类。原因标注文件里类别编号确实只有 0、1、2但存在大量同一目标被两个重叠框重复标注的情况而且一个框分到一类另一个框分到另一类。这通常来自标注工具的自动生成功能或者多人标注时意见不一致。解决用第 3 章的脚本计算每张图里的框交并比把 IOU 高且类别不同的框合并。合并规则是保留面积较大的那个框类别以标注置信度更高的为准。这个清洗步骤做完类间混淆通常会明显下降。6. 把验证集用到位用离线推理回灌检查数据与模型的匹配度训练完成后验证集还有一个更重要的用途经常被忽略用它来检查“模型认为的缺陷”和“数据集标注的缺陷”之间是不是同一个东西。我每次训练完必做一个叫“离线推理回灌”的动作这个动作只需要一条命令加一个脚本。python detect.py \ --weights runs/train/exp/weights/best.pt \ --source /path/to/dataset_root/images/val \ --img 640 \ --conf 0.25 \ --save-txt \ --save-conf跑完后runs/detect/exp/labels里会生成每个验证图片的预测结果格式也是class x_center y_center width height conf。然后写个脚本把预测框和真实标注框画到同一张图上对比import cv2 import numpy as np from pathlib import Path img_dir Path(/path/to/dataset_root/images/val) true_dir Path(/path/to/dataset_root/labels/val) pred_dir Path(runs/detect/exp/labels) colors [(255, 0, 0), (0, 255, 0), (0, 0, 255)] class_names [crack, wear, broken] for img_path in sorted(img_dir.iterdir())[:20]: # 抽查前20张 img cv2.imread(str(img_path)) h, w img.shape[:2] name img_path.stem # 真实标注绿色 true_txt true_dir / f{name}.txt if true_txt.exists(): for line in true_txt.read_text().strip().splitlines(): c, cx, cy, bw, bh map(float, line.split()) x1, y1 int((cx - bw/2)*w), int((cy - bh/2)*h) x2, y2 int((cx bw/2)*w), int((cy bh/2)*h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) # 模型预测红色 pred_txt pred_dir / f{name}.txt if pred_txt.exists(): for line in pred_txt.read_text().strip().splitlines(): c, cx, cy, bw, bh, conf map(float, line.split()) x1, y1 int((cx - bw/2)*w), int((cy - bh/2)*h) x2, y2 int((cx bw/2)*w), int((cy bh/2)*h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(fcompare_{name}.jpg, img)看对比图时我重点检查三类差异预测框完全覆盖但比真实框大很多说明模型定位边界不紧预测框只覆盖缺陷的一部分说明特征学习不完整真实框存在但完全没有预测框说明漏检样本集中在某种特殊形态上。这三种情况对应的处理方向完全不同第一种调 NMS 和置信度阈值第二种检查标注框质量第三种回到第 4 章检查输入分辨率和数据增强。我的习惯是抽 20 张验证集图片做这个对比发现“预测框和真实框对不上”的图片先看标注文件再翻原图基本能定位是标注问题还是模型问题。这套离线推理回灌流程比单纯看 mAP 数字更能发现数据集里的系统性偏差。过完这一步这份 YOLOv5 目录格式的齿轮缺陷数据集才算真正被用透了。希望帮到你。本文还有配套的精品资源点击获取