垃圾分类检测数据集实战:YOLO+VOC双格式训练与调优指南
2026/9/23 10:59:43 网站建设 项目流程

简介:这是一份面向目标检测学习者的垃圾分类检测数据集,适合从事计算机视觉入门、YOLO/VOC格式训练及环保识别项目实践的开发者与高校学生使用,可解决垃圾材质分类检测任务中样本不足、标注不完整的问题。压缩包共约2000个文件,以1999个xml标注文件和1个说明txt为主,整体约128.05MB,内含JPEGImages图片、Annotations标注与labels标签三类目录,图片与标注一一对应,便于直接投入训练。数据集共8341张清晰图片,标签分为Cardboard、Glass、Metal、Paper、Plastic五类,总框数达8815个,各类别框数分布相对均衡,其中Plastic最多为1911个,Glass最少为1601个,均为矩形框标注,未做数据增强。目前已有224人学习下载,读者可借此快速搭建垃圾分类检测基线模型,验证不同算法在真实垃圾材质识别上的表现,并作为课程设计或竞赛练手的可靠数据来源。

1. 垃圾分类检测数据集:8341 张 yolo+voc 双格式到底能省多少事

你拿到一个垃圾分类检测数据集,第一反应大概率是翻目录看图片和标注,然后发现标注格式不是自己训练管线要的那一种。8341 张图,如果标注只有 VOC 的 XML,而你用的是 YOLO 系列训练脚本,就得先转格式;反过来如果只有 txt,想用 SSD 或 Faster R-CNN 又得倒回去。这个数据集标题里写的是 yolo+voc 双格式,意味着同一批图配了两套标注,省掉的正是这道转换工序。垃圾分类本身是个很典型的检测任务:可回收物、厨余、有害、其他,四大类下面还可能细分到塑料瓶、纸箱、电池、果皮。类别粒度直接决定标注框的松紧程度,也决定你后面调参时 mAP 能不能上去。适合谁用?做课程设计的学生、想跑通 YOLO 训练全流程的入门者、需要快速验证某个改进模块是否有效的研究者,以及做智能垃圾桶、分拣线视觉原型的工程师。8341 张不算大,但足够把训练管线跑通并看出模型收敛趋势。

2. 先看清标注质量再谈训练:8341 张图的类别分布与格式核对

2.1 类别粒度决定标注框松紧

垃圾分类数据集的标注方式通常有两种:一种只标四大类,框住整个物体;另一种标到细类,比如“塑料瓶”“玻璃瓶”“纸箱”“电池”。细类标注的框往往更紧,因为标注者需要区分材质,边界会贴着物体轮廓画。粗类标注则可能把一堆可回收物框成一个大框,或者只框主体。你拿到数据集后,先统计每个类别的实例数。如果某个类别实例数低于 200,训练时该类别的召回率大概率上不去,需要考虑数据增强或者类别合并。常见做法是用脚本统计 VOC XML 里的 object 标签,或者直接读 YOLO 格式的 classes.txt 和 labels 目录。

import os import xml.etree.ElementTree as ET from collections import Counter # 统计 VOC 格式标注中每个类别的实例数 voc_dir = "annotations/voc" counter = Counter() for xml_file in os.listdir(voc_dir): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(voc_dir, xml_file)) root = tree.getroot() for obj in root.findall("object"): name = obj.find("name").text counter[name] += 1 for cls, cnt in counter.most_common(): print(f"{cls}: {cnt}")

这段代码遍历 VOC 标注目录,解析每个 XML 里的 object 节点,统计类别名出现次数。参数说明:voc_dir指向 VOC 格式标注文件夹,里面每个 XML 对应一张图。输出结果直接告诉你类别是否均衡。如果发现某个类别只有几十个实例,先别急着训练,要么做过采样,要么在配置文件里给这个类别更高的损失权重。

2.2 双格式目录结构核对清单

yolo+voc 双格式的数据集,目录通常长这样:images 放原图,labels 放 YOLO 的 txt,annotations 或 VOC2007 放 XML。你需要核对三件事:图片文件名和标注文件名是否一一对应、YOLO 的 txt 里类别索引是否和 classes.txt 行号一致、VOC XML 里的 filename 字段是否和实际图片名匹配。常见翻车点是图片是IMG_001.jpg,XML 里写的是IMG_001.JPG,大小写不一致导致训练时找不到标注。另一个坑是 YOLO 的 txt 里坐标是归一化后的,如果你直接拿 VOC 的绝对坐标去训练 YOLO,框会飞到天上去。

核对项正确状态常见错误
图片与标注同名主文件名一致,扩展名可不同大小写不一致、多了空格
YOLO 类别索引从 0 开始,对应 classes.txt 行号从 1 开始,导致类别偏移
YOLO 坐标范围0~1 归一化直接写像素绝对值
VOC 坐标范围像素绝对值,xmin< xmax写反或超出图片尺寸
图片尺寸一致性标注坐标不超过宽高图片被缩放但标注没同步

提示:先跑一遍核对脚本,把不匹配的文件名打印出来,手动改比训练时报错再回头找要省时间。

3. 从 VOC 到 YOLO 的转换脚本与四个边界坑

3.1 转换脚本逐行拆解

VOC 转 YOLO 的核心逻辑:读 XML 里的 size 拿到图片宽高,读每个 object 的 bndbox 拿到 xmin、ymin、xmax、ymax,然后计算中心点和宽高并归一化。类别名映射到索引,写入 txt。下面这个脚本我一般会直接拿来用,改一下路径就能跑。

import os import xml.etree.ElementTree as ET # VOC 转 YOLO 格式 voc_dir = "annotations/voc" out_dir = "labels_yolo" classes = ["recyclable", "kitchen", "hazardous", "other"] # 按实际类别顺序改 os.makedirs(out_dir, exist_ok=True) for xml_file in os.listdir(voc_dir): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(voc_dir, xml_file)) root = tree.getroot() size = root.find("size") w = int(size.find("width").text) h = int(size.find("height").text) lines = [] for obj in root.findall("object"): name = obj.find("name").text if name not in classes: continue # 跳过不在类别表里的标注 cls_id = classes.index(name) bbox = obj.find("bndbox") xmin = float(bbox.find("xmin").text) ymin = float(bbox.find("ymin").text) xmax = float(bbox.find("xmax").text) ymax = float(bbox.find("ymax").text) # 边界裁剪,防止坐标超出图片范围 xmin = max(0, min(xmin, w)) xmax = max(0, min(xmax, w)) ymin = max(0, min(ymin, h)) ymax = max(0, min(ymax, h)) cx = (xmin + xmax) / 2.0 / w cy = (ymin + ymax) / 2.0 / h bw = (xmax - xmin) / w bh = (ymax - ymin) / h lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}") txt_name = xml_file.replace(".xml", ".txt") with open(os.path.join(out_dir, txt_name), "w") as f: f.write("\n".join(lines))

逻辑说明:先读图片宽高,再遍历 object。classes.index(name)拿到类别索引,如果标注里有不在类别表里的名字,直接跳过,避免训练时类别数对不上。边界裁剪那四行是后悔药,有些标注框会超出图片边缘,不裁剪的话归一化后坐标可能小于 0 或大于 1,YOLO 训练时虽然不会报错,但框的位置会偏。最后写入 txt,每行一个目标,格式是类别 中心x 中心y 宽 高,全部归一化到 0~1。

3.2 四个边界坑:空标注、越界框、类别名空格、图片缺失

第一个坑是空标注。有些图片里没有目标,XML 里没有 object 节点,转换后 txt 是空文件。YOLO 训练时空 txt 是合法的,表示这张图是负样本。但如果你用的是某些第三方训练脚本,空文件可能导致 dataloader 报错。解决方法是保留空文件,或者在配置里设置允许空标注。

第二个坑是越界框。标注者手抖把 xmax 写得比图片宽度还大,归一化后 bw 可能大于 1。上面脚本里的裁剪逻辑能兜住,但裁剪后框会变形。如果越界严重,建议直接丢弃这个标注,而不是裁剪。

第三个坑是类别名带空格。VOC XML 里写的是plastic bottle,而 classes.txt 里写的是plastic_bottle,转换时匹配不上,目标被跳过。解决方法是统一用下划线,或者在转换前做一次字符串替换。

第四个坑是图片缺失。XML 里有标注,但 images 目录里找不到对应图片。训练时 dataloader 会报 FileNotFoundError。写个脚本比对两个目录的文件名集合,把差集打印出来,手动补图或删标注。

4. 用 YOLOv8 在本地跑通垃圾分类训练的最小命令

4.1 环境配置与数据 YAML 写法

YOLOv8 的环境配置不算复杂,但版本对不上会出玄学问题。我一般用 conda 建一个干净环境,Python 3.9 或 3.10,然后 pip 装 ultralytics。显卡驱动和 CUDA 版本要匹配,不然训练时要么跑在 CPU 上慢得离谱,要么直接报 CUDA error。装完之后用yolo checks看一眼环境状态,确认 GPU 能被识别。

数据配置文件garbage.yaml长这样:

path: ./garbage_dataset train: images/train val: images/val nc: 4 names: 0: recyclable 1: kitchen 2: hazardous 3: other

path是数据集根目录,trainval是相对路径。nc是类别数,names是类别名和索引的映射。注意这里的索引必须和 YOLO txt 里的类别索引一致,否则训练出来的模型会把塑料瓶识别成电池。

4.2 训练命令与关键参数含义

最小训练命令:

yolo detect train data=garbage.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16

model=yolov8n.pt用的是 nano 版本,参数量小,适合快速验证。epochs=100对 8341 张图来说够跑出趋势,如果 loss 还在降可以加到 200。imgsz=640是输入分辨率,垃圾分类的物体通常占画面比例较大,640 够用;如果小目标多,比如远处的小瓶子,可以提到 800 或 1024,但显存占用会上去。batch=16根据显存调,8G 显存跑 640 分辨率大概能到 16,不够就降到 8。

训练过程中重点看三个指标:box_loss、cls_loss、mAP50。box_loss 降不下去说明框回归有问题,可能是标注质量差;cls_loss 震荡说明类别不均衡或者学习率太大;mAP50 在 50 个 epoch 后还没明显上升,检查数据里有没有大量错标。

注意:训练前把数据集按 8:2 划分 train 和 val,划分时保证每个类别在 val 里都有实例,否则验证集的 mAP 没有参考意义。

5. 训练不收敛、mAP 上不去:垃圾分类检测的排查清单

5.1 现象:loss 从第一个 epoch 就不降

原因通常是标注格式不对。YOLO 的 txt 里坐标必须是归一化的,如果你误把 VOC 的绝对坐标写进去,模型看到的框全是几百像素的数值,归一化后远超 1,loss 直接爆炸。解决方法是检查 txt 里的数值范围,正常应该在 0~1 之间,且中心点坐标在 0.5 附近波动。

另一个原因是类别索引越界。classes.txt 只有 4 行,但 txt 里出现了类别 5,训练时索引不到类别名,loss 计算会出错。用脚本扫一遍所有 txt 的类别列,把超出范围的找出来。

5.2 现象:mAP50 卡在 0.3 上不去

先看验证集里的标注有没有问题。有时候训练集标注是对的,验证集里混了几张错标图,mAP 被拉低。把验证集预测结果可视化,用yolo detect predict跑一遍,看模型到底把框画在哪。如果框的位置大致对但类别错,说明类别特征不明显,考虑增加该类别的样本或者做针对性增强。如果框的位置完全不对,检查验证集的图片和标注是否对应。

垃圾分类有个特殊难点:同一类物体外观差异大。比如“可回收物”里既有塑料瓶又有纸箱,颜色、形状、纹理都不一样。模型需要学到的是材质相关的特征,而不是固定形状。这时候数据增强里的颜色抖动、随机裁剪、马赛克增强能帮上忙。YOLOv8 默认开了马赛克增强,如果效果不好可以关掉试试,有些场景下马赛克会让小目标更难学。

5.3 现象:训练时显存溢出

batch调太大了。8341 张图,640 分辨率,8G 显存跑 batch=16 可能刚好卡在边缘,跑几个 epoch 后显存碎片多了就 OOM。解决方法是降 batch 到 8,或者开梯度累积。YOLOv8 支持nbs参数做梯度累积,batch=8 nbs=16等效于 batch=16 的梯度更新频率,但显存占用按 8 算。

另一个显存杀手是imgsz。640 提到 1280,显存占用大概翻四倍。如果非要高分辨率,先把 batch 降到 4 试试。

5.4 现象:验证集 mAP 正常但实际推理效果差

训练时的验证集和实际场景分布不一致。比如验证集里的图片都是白底产品图,实际场景是复杂背景的垃圾桶,模型在验证集上表现好,一到真实场景就翻车。解决方法是把实际场景的图片加进训练集,哪怕只标几十张,也能显著提升泛化能力。另一个原因是置信度阈值。YOLO 默认推理置信度阈值是 0.25,垃圾分类场景下如果模型对某些类别信心不足,框会被过滤掉。用conf=0.1跑一遍看看是不是漏检。

5.5 现象:某些类别完全检测不到

先确认训练集里这个类别的实例数。如果少于 100,模型很难学到。解决方法是过采样,把包含这个类别的图片复制多份,或者在 dataloader 里给这个类别更高的采样权重。另一个原因是这个类别的标注框太小。YOLO 对小于 16x16 像素的目标检测能力有限,如果标注框确实很小,考虑提高输入分辨率或者用专门的小目标检测策略。

6. 把 8341 张图用出复利:数据增强、类别合并与增量训练

6.1 针对垃圾分类的增强参数怎么调

YOLOv8 的增强参数在训练命令里可以直接改。默认的hsv_h=0.015hsv_s=0.7hsv_v=0.4对垃圾分类来说偏保守。垃圾物体在不同光照下颜色变化大,可以把hsv_v提到 0.5,让模型对亮度变化更鲁棒。degrees=0默认不旋转,但垃圾物体在垃圾桶里可能是任意角度,把degrees=10打开,让模型学旋转不变性。flipud=0默认不上下翻转,垃圾场景里上下翻转是合理的,可以设flipud=0.5mosaic=1.0默认开,如果发现小目标检测效果差,降到 0.5 试试。

yolo detect train data=garbage.yaml model=yolov8n.pt epochs=150 imgsz=640 batch=16 hsv_v=0.5 degrees=10 flipud=0.5 mosaic=0.5

这些参数不是拍脑袋定的,是我在类似数据集上试出来的。hsv_v太高会让颜色失真,模型学不到材质特征;degrees太大会引入大量黑边,反而干扰训练。建议每次只改一个参数,跑 30 个 epoch 看 mAP 变化。

6.2 类别合并的决策依据

如果某个细类实例数太少,比如“电池”只有 80 个框,单独作为一类训练效果很差。这时候可以考虑合并到“有害垃圾”大类里。合并的依据是:实际应用场景是否真的需要区分这个细类。如果只是做四分类垃圾桶的满溢检测,不需要知道具体是什么有害垃圾,合并完全合理。如果做分拣线,需要区分电池和灯管,那就不能合并,得补数据。

合并的操作很简单:改 classes.txt,把两个类别名改成同一个,然后重新生成 YOLO txt 里的类别索引。注意 VOC XML 里的类别名也要同步改,否则下次转换又对不上。

6.3 增量训练:在已有模型上继续学新数据

你不可能一次收集完所有场景的垃圾图片。常见做法是先用 8341 张图训一个基线模型,然后在实际部署中收集误检和漏检的图片,标好后做增量训练。YOLOv8 支持从已有权重继续训练:

yolo detect train data=garbage_v2.yaml model=runs/detect/train/weights/best.pt epochs=50 imgsz=640 batch=16 lr0=0.001

关键是lr0要调小,默认 0.01 是从头训练的学习率,增量训练用 0.001 或更低,避免把之前学到的特征冲掉。新数据里如果包含新类别,nc要改,模型头会重新初始化,这时候学习率可以稍大一点。

6.4 一个验证模型是否学到东西的小技巧

训完之后,别只看 mAP 数字。把验证集里预测错误的图片挑出来,按错误类型分类:框位置偏、类别错、漏检、误检。如果框位置偏的多,说明回归分支没学好,检查标注框是否一致;如果类别错的多,说明分类分支特征不够,考虑加数据或换更大的模型。我一般会随机抽 20 张错图,一张一张看,看完基本就知道下一步该调什么了。

这个数据集最大的价值不是 8341 这个数字,而是它给了你一个完整的、双格式的起点。你可以用它跑通从数据核对、格式转换、训练调参到错误分析的完整闭环。跑完一遍之后,再拿到其他检测数据集,流程是一样的。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询