ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

垃圾分类检测数据集yolo+voc双格式8341张:从训练到部署实战

2026/10/5 4:55:17 拓冰建站 浏览量
垃圾分类检测数据集yolo+voc双格式8341张:从训练到部署实战 简介这份垃圾分类检测数据集面向计算机视觉学习者与目标检测开发者用于训练和验证垃圾材质识别模型可服务于智能回收、环境分拣等场景。数据覆盖纸盒、玻璃、金属、纸质和塑料五类目标标注为矩形框适合YOLO与VOC双格式直接接入。压缩包共约2000个文件以1999个xml标注文件和1个说明文件为主另含8341张jpg图片与8341个txt标签文件分别对应图像、VOC标注和YOLO标注整体约128MB目录划分清晰便于按格式快速取用。全部图片清晰且未做增强总标注框数达8815个其中塑料1911、纸盒1785、金属1770、纸质1748、玻璃630类别分布可供分析。已有224人学习适合需要真实标注数据开展检测训练、格式转换与类别均衡实验的读者。1. 垃圾分类检测数据集8341 张 yolovoc 双格式到底解决了什么手上接过一个园区垃圾投放点的智能化改造需求摄像头装在投放口上方要求识别塑料瓶、纸箱、厨余袋、有害垃圾这几类并且把结果推给现场屏幕做投放引导。真正动手时才发现卡住进度的不是模型结构而是数据。公开的垃圾分类数据要么类别定义和现场对不上要么只有分类标签没有检测框要么格式是 voc 而训练脚本吃的是 yolo txt。这个「垃圾分类检测数据集 yolovoc 格式 8341 张」正好踩在痛点上它同时给出两种标注格式意味着你拿到手不用先写转换脚本就能直接开跑8341 张的体量也够撑起一个能上线的基线模型。这篇笔记就按我实际落地的顺序把这份数据集从解压到训出可用权重、再到避坑的完整路径讲清楚适合刚入门目标检测、或者手上有类似投放点识别需求、想快速验证方案的工程师。2. 先搞懂 yolo 与 voc 双格式为什么同一批图要存两份标注2.1 两种格式的本质差异与各自适用场景目标检测的数据标注说到底就是「一张图 若干个框 每个框的类别」。voc 格式用 XML 描述一个 xml 文件对应一张图框的坐标是左上角和右下角的绝对像素值长这样annotation folderimages/folder filename000001.jpg/filename size width640/width height480/height depth3/depth /size object nameplastic/name !-- 类别名注意中英文一致性 -- bndbox xmin112/xmin !-- 左上角 x绝对像素 -- ymin88/ymin xmax305/xmax !-- 右下角 x -- ymax402/ymax /bndbox /object /annotationyolo 格式则是每张图配一个同名 txt每行一个框格式是类别索引 中心x 中心y 宽 高且这四个值全部归一化到 0~10 0.325781 0.510417 0.301563 0.654167 1 0.712500 0.388542 0.187500 0.229167两者最容易被忽略的差别是坐标系voc 是绝对像素、左上右下yolo 是归一化、中心宽高。很多人转换后框整体偏移八成是把中心点算成了左上角或者忘了除以图像宽高。数据集同时提供两份好处是你用 ultralytics 系训练直接吃 yolo txt用早期 darknet 或某些论文复现脚本时切到 voc省掉一次转换和一次校验。2.2 目录结构怎么摆才能被训练脚本直接识别拿到压缩包解压后我一般先整理成下面这种结构再动手训练。ultralytics 对目录名有约定images和labels必须同级且文件名一一对应garbage_dataset/ ├── images/ │ ├── train/ # 训练图约 80% │ └── val/ # 验证图约 20% ├── labels/ │ ├── train/ # 与 train 图同名的 txt │ └── val/ ├── annotations_voc/ # 原始 voc xml留档备用 └── data.yaml # 数据集描述文件data.yaml是训练的入口配置内容不长但每个字段都不能错path: /data/garbage_dataset # 数据集根目录绝对路径最稳 train: images/train # 相对 path 的训练图目录 val: images/val nc: 4 # 类别数必须和 names 长度一致 names: # 类别名顺序即类别索引 0: plastic 1: paper 2: kitchen 3: harmful提示names的顺序就是 yolo txt 里那个类别索引的含义。如果你把 plastic 写在第一位那 txt 里所有0都必须是塑料。改类别顺序而不改 txt模型会学出完全错误的映射这种错误在 loss 曲线上看不出来只有推理时才发现框对了类错了。2.3 用脚本校验标注别等训练炸了才回头查数据集再规整也建议先跑一遍校验把越界框、空标注、类别越界挑出来。下面这段脚本我几乎每个检测项目都会跑一次import os from pathlib import Path from PIL import Image root Path(/data/garbage_dataset) nc 4 # 类别数和 data.yaml 保持一致 bad [] for split in [train, val]: img_dir root / images / split lbl_dir root / labels / split for img_path in img_dir.glob(*.jpg): lbl_path lbl_dir / (img_path.stem .txt) if not lbl_path.exists(): bad.append((img_path.name, 缺少标注文件)) continue w, h Image.open(img_path).size for i, line in enumerate(lbl_path.read_text().strip().splitlines()): parts line.split() if len(parts) ! 5: bad.append((img_path.name, f第{i}行字段数不对)) continue cls, cx, cy, bw, bh int(parts[0]), *map(float, parts[1:]) if cls 0 or cls nc: bad.append((img_path.name, f类别索引越界 {cls})) if not all(0 v 1 for v in (cx, cy, bw, bh)): bad.append((img_path.name, f第{i}行坐标未归一化)) # 中心点加半宽半高超过 1说明框出界 if cx bw / 2 1.001 or cy bh / 2 1.001: bad.append((img_path.name, f第{i}行框越界)) print(f共发现 {len(bad)} 处问题) for name, reason in bad[:20]: print(name, reason)逻辑说明遍历 train/val 两个 split对每张图找同名 txt逐行解析五个字段。cls越界说明类别数和 names 对不上坐标不在 0~1 说明归一化漏了cx bw/2 1是框右下角出界通常是标注时框拖到了图像外。参数上nc必须和 data.yaml 的nc一致否则会把合法类别误报。跑完如果问题数在个位数手工修上百条就要怀疑是不是转换脚本本身写错了。3. 用这份数据集跑通第一个 yolo 基线从环境到权重3.1 环境准备与 ultralytics 安装的最小命令现在主流做法是用 ultralytics 这个库它把训练、验证、导出封装成几行调用。环境我一般用 conda 隔离避免和系统里的 torch 打架conda create -n garbage python3.10 -y conda activate garbage # 有 NVIDIA 卡就装 cuda 版 torch没有就用 cpu 版 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 pip install ultralytics opencv-python pillow装完先验证一下能不能识别到显卡这一步别省python -c import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0) if torch.cuda.is_available() else CPU)输出True加显卡型号就对了。如果显示False先别急着训检查驱动和 cuda 版本是否匹配否则你会用 CPU 训到天荒地老。ultralytics 的版本迭代很快接口偶有变动建议固定一个版本写进 requirements团队协作时不会因为版本差异导致结果对不上。3.2 训练命令与关键参数怎么设基线训练我一般从 yolov8n 或 yolov8s 起步n 最快s 精度略高先跑通再谈调优yolo detect train \ data/data/garbage_dataset/data.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/garbage \ namebaseline逐个说参数imgsz640是输入分辨率垃圾投放点这种目标不算特别小640 够用显存紧张可以降到 512batch16要按显存调8G 卡跑 yolov8s 640 大概能到 16爆显存就减半lr00.01是初始学习率ultralytics 默认带 warmup 和余弦退火一般不用大改patience20是早停20 轮验证指标不涨就停省时间。epochs100对 8341 张来说通常够收敛如果 loss 还在降可以加到 150。训练过程中重点看两个东西box_loss和mAP50。box_loss 平稳下降说明框在学mAP50 是 IoU 阈值 0.5 下的平均精度垃圾分类这种类间差异明显的任务基线跑到 0.85 以上不算难。如果 mAP 卡在低位不动先回去看第 2 章的校验脚本八成是标注问题而不是模型问题。3.3 推理验证把权重跑在单张图和视频流上训完权重在runs/garbage/baseline/weights/best.pt先拿单张图看效果from ultralytics import YOLO model YOLO(runs/garbage/baseline/weights/best.pt) results model.predict( sourcetest.jpg, conf0.25, # 置信度阈值低于此值的框丢弃 iou0.45, # NMS 的 IoU 阈值重叠框合并 imgsz640, saveTrue # 保存带框结果图 ) for r in results: for box in r.boxes: cls model.names[int(box.cls)] print(cls, round(float(box.conf), 3), box.xyxy.tolist())conf0.25是常用起点漏检多就降到 0.15误检多就升到 0.4iou0.45控制非极大值抑制同一目标出多个框时调低这个值能压掉重复框。投放点场景我一般把 conf 设得偏保守宁可多报也别漏报因为漏掉一个有害垃圾的提示比多提示一次代价大。视频流的话把source换成摄像头索引或视频路径即可帧率不够就降 imgsz 或换更小的模型。4. 垃圾分类检测的避坑清单5 个我真实踩过的坑4.1 类别名中英文混用导致训练直接报错现象训练启动几秒后报KeyError或类别数为 0日志里 names 是空的。原因data.yaml 里写了中文类别名而某些版本的解析对非 ASCII 支持不稳或者 xml 里的 name 和 yaml 里的 names 对不上。解决统一用英文小写类别名中文只在展示层做映射训练配置里绝不出现中文。我现在的习惯是建一个class_map.json专门管中英对照训练脚本只读英文。4.2 图片和标注文件名大小写不一致现象校验脚本报大量「缺少标注文件」但你去目录里看明明有。原因IMG_001.JPG和img_001.txt在 Linux 下是两个不同文件Windows 不区分大小写所以本地没事一上服务器就炸。解决批量把图片名和标注名统一转小写扩展名也统一成.jpg和.txt。这个坑血泪经验跨平台迁移数据必查。4.3 训练集和验证集出现同一张图的副本现象验证集 mAP 高得离谱上线后实际效果差一大截。原因划分数据集时随机切分同一场景连拍的近似图被分到了 train 和 val模型等于见过验证集。解决按拍摄批次或时间划分而不是按文件随机。同一投放点同一时段的图要么全进 train 要么全进 val。这个错误最隐蔽因为指标好看只有上线才暴露。4.4 框越界没处理训练时被静默裁剪现象某些类别的框总是偏小或位置怪。原因标注时框拖到了图像边界外yolo 训练会裁剪到 0~1导致框变形。解决用第 2 章的校验脚本把cxbw/21的挑出来要么修标注要么在转换时 clamp 到边界。别指望训练框架帮你处理它只会默默裁掉。4.5 显存不足直接 OOM 而不是降 batch现象训练刚起步就CUDA out of memory。原因batch 或 imgsz 设太大或者 dataloader 的 workers 开太多占内存。解决先把 batch 减半试还不行就降 imgsz 到 512再不行把workers设成 2。别一上来就上大模型大分辨率8341 张用 yolov8s 640 完全够验证方案可行性。5. 把基线推到可用数据增强与类别不均衡的处理技巧基线跑通只是起点真正决定上线效果的是数据层面的功夫。垃圾分类数据集最常见的两个问题是类别不均衡和小目标漏检——塑料瓶、纸箱样本多有害垃圾样本少模型会偏向多数类。我一般先统计每个类别的框数量用下面这段快速看分布from collections import Counter from pathlib import Path cnt Counter() for txt in Path(/data/garbage_dataset/labels/train).glob(*.txt): for line in txt.read_text().strip().splitlines(): cnt[int(line.split()[0])] 1 print(cnt) # 键是类别索引值是框数量如果最少的类比最多的类少一个数量级直接训会欠拟合少数类。处理手段有三档最轻的是在 data.yaml 同级开增强ultralytics 训练时加mosaic1.0、mixup0.1、copy_paste0.1让少数类在拼接图里出现更多次中等的是对少数类做离线过采样把含少数类的图复制多份进 train最重的是重标注补数据但 8341 张的体量下前两档通常够用。增强参数不是越大越好。mosaic1.0是默认四图拼接对小目标友好但会让框的上下文变怪如果发现模型对完整物体识别变差降到 0.5。mixup把两张图按透明度叠加能提升泛化但训练变慢0.1 到 0.2 比较稳。copy_paste是把实例抠出来贴到别的图上对少数类增益明显但要求标注质量高标注有噪声时反而引入错误。验证阶段别只看总 mAP要分类别看。ultralytics 验证后会输出每个类别的 P、R、mAP把少数类的召回单独拎出来看。如果少数类召回低于 0.6说明增强还不够或者样本确实太少这时候与其硬调模型不如补几十张真实场景的少数类图收益比调参大得多。我做过对比补 50 张有害垃圾实拍图带来的少数类召回提升比把 epochs 从 100 加到 300 还明显。最后说导出。投放点现场多半是边缘设备权重导出成 onnx 或 tensorrt 能显著提速yolo export modelruns/garbage/baseline/weights/best.pt formatonnx imgsz640 halfTruehalfTrue是 fp16 量化边缘卡上通常能提速三成且精度损失很小。导出后务必用同一批测试图对比 onnx 和 pt 的输出确认框位置和类别一致量化偶尔会让个别框偏移发现异常就关掉 half 重导。这套流程我从数据校验到导出跑过好几遍最深的体会是垃圾分类检测的瓶颈从来不在模型选型而在标注一致性和类别分布。把第 2 章的校验脚本和第 5 章的分布统计当成固定动作比追新模型结构实在得多。希望帮到你。本文还有配套的精品资源点击获取