news 2026/10/2 8:36:58

VOC垃圾分类数据集详解:15000张真实场景图与YOLO训练实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
VOC垃圾分类数据集详解:15000张真实场景图与YOLO训练实战

简介:VOC垃圾分类检测数据集面向需要训练目标检测模型的开发者、研究人员及学生,提供约一万五千张真实场景高质量标注图片,覆盖纸张、塑料、果皮、玻璃杯、易拉罐、厨余垃圾等常见类别,场景丰富、角度多样。全部图片以jpg格式保存,采用LabelImg工具完成人工标注;标签同时提供VOC格式(xml文件)与YOLO格式(txt文件)两套,分别存放于独立文件夹,用户可根据训练框架灵活选用,无需额外转换即可直接用于YOLO系列模型训练。资源包共包含58921个文件,其中jpg图片19640张、xml标注文件19640个、txt标注文件19641个,整体约994.56MB,压缩包结构清晰。目前已有1334人浏览学习,适合用于垃圾分类检测相关的课程设计、毕设项目或实际工程落地,既能帮助快速搭建训练数据集,也能作为模型调参与效果验证的参考。

1. 把VOC垃圾分类检测数据集讲清楚:15000张真实场景图,双格式标签直接喂给YOLO

做垃圾分类检测时,最头疼的不是YOLO调参,而是数据。白底模拟图训出来的模型,一进真实垃圾桶场景就翻车。这份VOC垃圾分类检测数据集全部来自真实拍摄,共15000张jpg,labelImg逐张标注,VOC和YOLO两套标签分开存放,解压后就能直接开工。

覆盖纸张、塑料、果皮、玻璃杯、易拉罐、厨余垃圾这些常见类别,场景包括路边、食堂、家庭垃圾袋等,光线遮挡接近实际。适合做垃圾分类检测demo或毕设的人,也适合想用YOLO验证真实场景效果的一线工程师。作者在CSDN放了检测效果示例,文章编号124230743:https://blog.csdn.net/zhiqingAI/article/details/124230743,可以先看结果再决定下载。

下面按我处理数据的完整流程走:拆结构、做校验、跑YOLOv8、讲踩坑。

2. 数据集结构拆解:labelImg标注产物里,VOC和YOLO格式差在哪里

2.1 两个标签文件夹的目录组织与文件命名

下载包解压后,图片集中在一个文件夹里,标签按VOC和YOLO两种格式分别装在两个文件夹中。图片文件名有两种风格:P90818-212351.jpg这种是相机按拍摄时间自动命名的,IMG20190818110344.jpg这种来自手机拍摄。文件名本身无所谓,关键是每张图片都能找到同名的标签文件——VOC侧是.xml,YOLO侧是.txt。

我拿到任何标注数据集,第一件事是数文件。图片15000张,标签也要能对应上15000份。数文件时注意:labelImg标注会生成classes.txt记录标注时用到的全部类别名,这份数据集的YOLO标签文件夹里通常带着它。训练前先打开看一眼,确认里面是paper/plastic/peel/glass/can/kitchen_waste这类英文名,顺序就是class id顺序,直接决定后面data.yaml里names怎么写。

提示:如果发现classes.txt里类别数量和顺序与预期不一致,以classes.txt为准,后续所有配置跟着它改。

2.2 VOC的XML和YOLO的TXT:同一目标两种坐标表达

同一张图,在VOC和YOLO两个文件夹里看到的是同一个标注框的两种表达。VOC格式的XML长这样:

<annotation> <filename>P90818-212351.jpg</filename> <size> <width>1280</width> <height>720</height> <depth>3</depth> </size> <object> <name>paper</name> <bndbox> <xmin>142</xmin> <ymin>85</ymin> <xmax>634</xmax> <ymax>512</ymax> </bndbox> </object> </annotation>

而这个框在YOLO格式的txt里只有一行:

0 0.303 0.415 0.384 0.593

YOLO格式五个数依次是:类别id、归一化中心点x、中心点y、框宽、框高。归一化公式是:

x_center = (xmin + xmax) / 2 / width y_center = (ymin + ymax) / 2 / height w = (xmax - xmin) / width h = (ymax - ymin) / height

代入上面xml的数字:x_center = (142 + 634) / 2 / 1280 ≈ 0.303,和txt完全对得上。理解这套换算不是为了让你手动转格式——这份数据已经转好了——而是为了排查问题。训练时直接使用现成的txt;后续要加自己的标注图片,或者要在不同工具之间倒腾格式,坐标换算绕不开。

另外注意:xml里的filename字段只是参考,YOLO训练时不会用这个字段匹配图片,匹配全靠同名。如果某个工具导入后出现文件名对不上,别去改xml,直接从图片文件夹重新生成同名文件更省事。

2.3 类别映射表:六类垃圾的class id分配

这份数据集按常见场景分了六类,我的归类习惯如下表。最终名称以数据集里classes.txt的真实内容为准,作者在简介里写过“等常见类别”,下载后先核对再训练。

class idVOC name含义典型样本
0paper纸张传单、纸箱、A4纸、报纸、餐巾纸
1plastic塑料塑料袋、塑料瓶、泡沫盒、包装膜
2peel果皮香蕉皮、橘子皮、苹果皮、果核
3glass玻璃杯玻璃瓶、玻璃杯、碎玻璃
4can易拉罐铝罐、铁罐、罐头盒
5kitchen_waste厨余垃圾剩饭剩菜、骨头、菜叶

类别顺序直接决定txt里的数字和data.yaml里的names列表。如果你把names写成[glass, can, ...],而txt里0是paper,模型会把所有paper当glass,框的位置还对,类别全错,mAP看着也不低。这种错最难发现,所以拿到数据的第一件事是随机抽查三个txt,人工核对class id和类别名的对应关系。

VOC格式里同样有name字段。用可视化工具标注确认不方便时,直接对照xml看这张图里有没有易混淆类别,比如“果皮”和“厨余垃圾”——这两类的界限在后续训练中会成为最大的坑,第5章和第6章都会反复提到。

3. 训练前的数据准备:目录整理、标签校验、类别分布统计

3.1 把下载的文件夹整理成YOLO标准目录结构

YOLO系列默认读的数据结构是images/train、images/val、labels/train、labels/val。下载包往往是扁平目录或自定义结构,直接用会报dataset not found。第一步就是把图片和YOLO标签按比例切分,我通常用下面这段脚本:

import os, shutil, random root = "D:/garbage" # 数据集根目录,改成你的实际路径 img_src = "images" # 图片目录名 lab_src = "labels_yolo" # YOLO标签目录名 for sub in ["images/train", "images/val", "labels/train", "labels/val"]: os.makedirs(os.path.join(root, sub), exist_ok=True) names = [f for f in os.listdir(os.path.join(root, img_src)) if f.lower().endswith(".jpg")] random.seed(42) random.shuffle(names) val_n = int(len(names) * 0.2) for i, name in enumerate(names): split = "val" if i < val_n else "train" stem = os.path.splitext(name)[0] shutil.copy2(os.path.join(root, img_src, name), os.path.join(root, f"images/{split}", name)) # 同名txt存在才复制,避免训练时标签对不上 src_lab = os.path.join(root, lab_src, stem + ".txt") if os.path.exists(src_lab): shutil.copy2(src_lab, os.path.join(root, f"labels/{split}", stem + ".txt")) else: print("缺标签:", name)

脚本逻辑:先建好四个目录,再按8:2比例随机切分图片和标签。random.seed(42)固定了随机顺序,保证每次运行结果一致,方便复现。用copy2而不是move,是因为原始VOC备份还要留着排查问题,后面第6章挑失败样本时经常要回去看原始标注边界。

train/val按8:2切,对垃圾检测这种目标多、类别不平衡的场景够用;如果你后续要做知识蒸馏或者更细致的调参,可以改成9:1。VOC的xml不用进训练目录,但建议整个文件夹原样保留。

3.2 用脚本一次性校验图片与标签是否对得上

切分完不要急着开训。真实拍摄的图片经过压缩、改名、拷贝,常见问题有:图片本身就是坏的、txt文件名对不上、坐标越界、类别id超范围。这些问题在训练时表现为随机报错或性能莫名变差。我每次处理数据集都固定跑一遍校验脚本:

from PIL import Image import os root = "D:/garbage" bad_img, bad_label, out_of_bounds = [], [], [] seen_ids = set() for split in ["train", "val"]: img_dir = os.path.join(root, f"images/{split}") lab_dir = os.path.join(root, f"labels/{split}") for name in sorted(os.listdir(img_dir)): stem = os.path.splitext(name)[0] lab_path = os.path.join(lab_dir, stem + ".txt") if not os.path.exists(lab_path): bad_label.append(name) continue try: with Image.open(os.path.join(img_dir, name)) as im: w, h = im.size # 获取真实宽高,用于越界判断 except Exception: bad_img.append(name) continue for line in open(lab_path, encoding="utf-8"): parts = line.strip().split() if len(parts) != 5: bad_label.append(name) continue cls, xc, yc, bw, bh = map(float, parts) seen_ids.add(int(cls)) # 允许1%浮点误差,超过说明框出界 if xc <= 0 or yc <= 0 or bw <= 0 or bh <= 0: out_of_bounds.append((name, line)) if xc + bw / 2 > 1.01 or yc + bh / 2 > 1.01: out_of_bounds.append((name, line)) print("图片损坏:", len(bad_img)) print("标签缺失/格式错:", len(bad_label)) print("坐标越界:", len(out_of_bounds)) print("出现的类别id:", sorted(seen_ids))

越界阈值用1.01而不是1.0,是因为YOLO归一化时可能出现单个像素级的浮点误差,1.01能容忍边界误差,又能抓住明显出界。出现越界的文件直接删掉或人工修正,这类框训练时会被当成背景负样本,影响不可控。seen_ids如果出现比类别总数大的id,说明txt和data.yaml对不上,这是最容易埋雷的地方。

3.3 先统计类别分布,再决定要不要做样本均衡

六类垃圾在真实场景中的分布并不均匀。纸张、塑料这类常见垃圾占了大头,玻璃杯、易拉罐相对少。不均衡不一定会让模型崩,但会让小类别recall偏低。先统计再决定策略:

from collections import Counter counter = Counter() for split in ["train", "val"]: lab_dir = os.path.join(root, f"labels/{split}") for name in os.listdir(lab_dir): for line in open(os.path.join(lab_dir, name), encoding="utf-8"): cls = int(line.strip().split()[0]) counter[cls] += 1 for cls, cnt in sorted(counter.items()): print(f"class {cls}: {cnt} boxes") total = sum(counter.values()) for cls, cnt in counter.items(): print(f"class {cls} 占比: {cnt / total * 100:.1f}%")

统计的是框数量不是图片数量,因为一张图里可能多个同类目标。如果发现某一类占比低于5%,不要盲目加大epochs期望它自愈,先判断这一类的短板是漏检还是误检。漏检多,优先做增量标注补充这类样本;误检多,多半是标注边界问题——注意看框里包了多少背景,这类问题不是数量能解决的。

4. 用YOLOv8跑垃圾分类检测:data.yaml、训练参数与导出测试

4.1 一份能直接用的data.yaml

YOLOv8的数据配置核心是一个yaml文件。针对这份数据集,我的写法是:

path: D:/garbage # 数据集绝对路径 train: images/train val: images/val names: 0: paper 1: plastic 2: peel 3: glass 4: can 5: kitchen_waste

path建议用绝对路径,不要用相对路径,因为训练命令的执行目录可能和你以为的不一样。train和val是相对于path的路径,前面不要带斜杠。names顺序必须与3.2脚本里seen_ids的取值一致,0必须是paper。如果某个类别在标签里一次都没出现过,可以保留在names里,YOLO不会报错,但混淆矩阵里它会一直是零——这其实是有用信息,说明数据里该类缺失,需要重点关注。

4.2 训练参数怎么设:imgsz、batch、epochs、workers

配置好yaml后用ultralytics命令行直接开训:

yolo detect train data=D:/garbage/data.yaml model=yolov8s.pt epochs=100 imgsz=640 batch=16 device=0 workers=4

我用的参数与理由如下:

参数建议值说明
modelyolov8s.pt15000张的中型数据集,s足够;显存大或追求精度换yolov8m
imgsz640垃圾目标大小跨度大,640是速度和精度平衡点;小目标多就提到768
batch168G显存能跑;6G显存就降到8
epochs100这个数据量100轮足够,50轮时看val loss就能判断要不要停
workers2~4Windows下建议2,超过8容易在启动时卡死数据加载

epochs不需要硬凑100,如果50轮后val曲线已经平坦,可以提前停。真实场景数据噪声大,训太狠反而过拟合到当天的光线条件。device=0是GPU,没CUDA就删掉device参数,会自动用CPU,但100轮会慢很多。workers在Windows上如果报DataLoader error,直接改成2。

还有一个很多人忽略的点:ultralytics第一次训练会扫描并缓存图片路径,数据集大或磁盘慢时,第一次启动会卡很久。看到进度条没动别急,观察磁盘IO。如果实在不耐烦,训练命令可以加cache=True,首次构建后后续读取快很多。

4.3 训练完导出与快速测试

训练结束后在runs/detect/train/weights/下出现best.pt和last.pt。best.pt是val mAP最高的权重,部署优先用它;last.pt是最后一轮的权重,继续训练时用它。拿best.pt做推理测试:

yolo predict model=D:/garbage/runs/detect/train/weights/best.pt source=D:/garbage/test_images/ save=True conf=0.25

这个命令把test_images里的每张图检测一遍,画出框和置信度。conf=0.25是我做垃圾分类时的常用下限:垃圾场景里漏检比误检更影响体验,没检出等于完全没分类;如果现场误检率高,再往上调到0.35或0.4,这是个业务权衡问题。

如果要部署到边缘设备,导出onnx:

yolo export model=D:/garbage/runs/detect/train/weights/best.pt format=onnx imgsz=640

导出后可以用onnxruntime在CPU上跑,也可以继续转TensorRT加速。imgsz必须和训练时一致,否则导出模型在边缘设备上的输入尺寸和训练时的分辨率习惯不匹配,精度会明显损耗。

5. 避坑:VOC垃圾分类检测数据集训练与推理的五个翻车点

训练这套数据集时我踩的坑不算少,整理五个最典型的,基本覆盖从读数据到上线的全程。

5.1 现象:训练一开始就报 unable to load image

原因:真实拍摄数据集经过多次拷贝,部分jpg文件头损坏,或者实际上是网络传输残留的半截文件。Windows下路径含中文同样会触发读取失败。文件名里IMG2019开头的照片尤其容易出问题,因为它们可能来自手机直传,exif信息完整但压缩格式特殊。

解决:先跑3.2的校验脚本,把损坏图片筛掉;数据集和训练工程都放到纯英文路径,比如D:/garbage,不要放在“桌面/下载”这类中文目录下。

5.2 现象:验证集mAP很高,但拿到现场一测就稀烂

原因:这类真实拍摄数据集,拍摄时间和光线条件相对固定,训练集和验证集同源,mAP天然乐观。而现场环境——垃圾桶内壁反光、夜间灯光、俯视角度——和数据集分布差异巨大。

解决:不要迷信mAP。训练完马上拿手机去实际场景拍20张图做盲测。如果盲测翻车,把现场图补标注后做增量训练,而不是急着调anchor或换模型。第3章强调的校验流程,就是为了给这一步留出足够干净的底子。

5.3 现象:同一张图的VOC和YOLO标签对不上

原因:大概率是图片被压缩过,但xml里的width/height还是原始值。比如原图1280x720被压成640x360,YOLO标签如果按原尺寸归一化已经不对,VOC的bndbox像素坐标则全偏了。

解决:训练直接用YOLO文件夹里的txt。数据已经转好,不自己二次转换就不存在偏差;如果非要从VOC重新转一遍,跑3.2的越界检查,出界的框全部人工核对。

5.4 现象:果皮和厨余垃圾互相误检

原因:这两类视觉特征高度重合,香蕉皮既可以叫peel也可以叫kitchen_waste。标注时人为分类不一致,模型学到的边界就混乱。这在垃圾分类任务里几乎是必然遇到的坑。

解决:训练前自己定标注口径:水果果皮、果核一律peel;剩饭剩菜、骨头、菜叶一律kitchen_waste。然后挑选20张两类的样本人工复核一遍,有争议的单独放一个文件,后续增量训练当难例用。

5.5 现象:脚本读VOC的xml时name字段乱码

原因:labelImg在Windows下默认utf-8保存,但有的转换脚本用open(path)默认编码读取,GBK和utf-8在中文类名上直接就乱了。

解决:读xml时强制指定encoding="utf-8"。更省事的做法是只依赖YOLO格式的txt,txt里类别是英文和数字,不存在编码问题。如果你在Windows下用PyCharm调试,把项目默认编码也统一成utf-8,省得后面一堆烂事。

6. 最后一个技巧:用混淆矩阵和失败样本定位误检根因

6.1 用val命令生成混淆矩阵

训练完不要看几张测试图就收工。先跑验证:

yolo val model=D:/garbage/runs/detect/train/weights/best.pt data=D:/garbage/data.yaml split=val

跑完在runs/detect/val/下会生成confusion_matrix.png和一系列指标图。看混淆矩阵里对角线之外最高的格子,那里就是误检最严重的两类。比如peel和kitchen_waste互踩,就是第5.4节说的标注口径问题。

6.2 挑低置信度样本看标注边界

混淆矩阵告诉你哪两类在混,但没告诉你为什么。我的做法是把推理时置信度在0.25到0.45之间的样本导出来,人工看一遍。看的时候重点不是模型准不准,而是标注框本身是不是把背景包进去了、是不是有半遮挡、是不是一个框框了两个类。这些信息训练日志里看不到,只有肉眼能发现。

6.3 固定一套“先校验再训练再复盘”的流程

到这里就能回答最开始的问题了:为什么这个数据集能直接用。它本身是VOC+YOLO双格式、六类覆盖相对完整,下载后按第3章整理校验,按第4章训练,按第5章避坑,再按6.1和6.2做过一次误检复盘,基本能稳定进入迭代循环。

说实话我也翻过车。早期拿到数据集上来就跑训练,mAP漂亮就以为自己搞定了,结果现场被垃圾桶照片打回原形。从那以后我每次拿到数据集,都强制先跑一遍3.2的校验脚本,训练完必看混淆矩阵,再挑失败样本过一遍标注边界。这套流程听着慢,实际比盲目重训省太多时间。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 8:36:57

Java个人博客系统毕业设计:从环境配置到部署答辩全流程指南

简介&#xff1a;基于Java的个人博客系统毕业设计资料包&#xff0c;面向高校计算机相关专业学生及Java Web入门开发者&#xff0c;适用于课程设计、毕业设计或项目实战。压缩包约178.52MB&#xff0c;包含项目报告、答辩PPT、源代码、数据库脚本及部署教学视频等主要文件类型&…

作者头像 李华
网站建设 2026/10/2 8:36:09

Claude Code实战:重构十年遗留系统的方法论

1. 这不是又一个“AI写代码”故事&#xff0c;而是给真实世界里那堆跑着十年的老系统续命的实操笔记我接手过三套平均年龄8岁的遗留系统&#xff1a;一套用VB6写的车间排产模块&#xff0c;数据库还是Access&#xff1b;一套Java Web项目&#xff0c;Spring版本停在2.5&#xf…

作者头像 李华
网站建设 2026/10/2 8:35:53

Java直播平台源码实战:从架构拆解到高并发部署全指南

简介&#xff1a;这是一套基于Java与Spring Boot构建的在线直播平台完整源码工程包&#xff0c;面向具备Java基础、希望学习企业级直播业务落地的开发者。项目采用前后端分离架构&#xff0c;涵盖腾讯云直播流接入、直播鉴黄、礼物打赏、支付宝充值提现、弹幕聊天室等核心模块&…

作者头像 李华
网站建设 2026/10/2 8:33:30

银行数据挖掘课程作业实战:分类与聚类全流程指南

简介&#xff1a;面向计算机专业学生和需要项目实战练习的学习者&#xff0c;这份数据仓库与数据挖掘课程高分期末大作业完整实现银行数据的分类与聚类任务&#xff0c;并配套翔实的实验报告。项目由导师指导并评审认可&#xff0c;得分99分&#xff0c;代码结构清晰、依赖完整…

作者头像 李华
网站建设 2026/10/2 8:33:05

机器学习多因子选股实战:从因子处理到组合构建全流程

简介&#xff1a;这份资源面向计算机、人工智能及金融工程方向的学生与量化爱好者&#xff0c;提供一套基于机器学习方法构建多因子选股模型的完整项目源码与文档&#xff0c;适合作为毕业设计参考或量化选股入门实战。压缩包共38个文件&#xff0c;约14.71MB&#xff0c;包含1…

作者头像 李华
网站建设 2026/10/2 8:32:25

Java海康SDK二次开发:从取流到推流的全链路实战

简介&#xff1a;面向Java开发者的海康威视网络摄像机与NVR二次开发资源包&#xff0c;以实时流/历史流推流、抓图、录像下载、云台控制四大功能为主线&#xff0c;提供在Windows/Linux环境可直接运行和扩展的项目代码。压缩包共256个文件&#xff0c;约39.25MB&#xff0c;其中…

作者头像 李华