
简介面向YOLO算法训练的垃圾分类检测数据集完整数据规模达13707张带标签图像覆盖纸箱、纸张、塑料、铝、玻璃、硬纸板、瓶子、塑料瓶等常见可回收物类别可有效解决垃圾分类场景中样本分散、标注成本高的问题适合计算机视觉入门者、目标检测研究者以及智能分拣、环保监控类项目开发者使用。本次压缩包内含2000个XML标注文件整体约348.31MB每个XML记录目标类别名称与边界框坐标信息结构清晰可直接接入YOLOv5、YOLOv8等训练流程省去手动标注环节。已有346人学习下载说明具备一定参考价值。利用这些标注文件使用者能快速搭建自己的垃圾检测训练集完成模型训练、参数调优与效果评估并用于课程设计、毕业设计或算法竞赛由于类别贴近常见生活垃圾训练成果可迁移至环卫清扫、回收分拣等实际场景显著降低重复数据准备的时间成本。1. 13707张图的垃圾检测数据集YOLO算法入手的真实起点做智能回收箱、环卫巡检车或者产线分拣的项目时最卡人的往往不是模型选型而是标注数据。自己拍图、清洗、打标签一个类别跑下来一两周就没了。这个垃圾检测数据集把纸箱、纸张、塑料、铝、玻璃、硬纸板、瓶子、塑料瓶这8类常见可回收物打包成13707张带标签图像格式直接面向YOLO算法训练解压之后就能开始跑。适合正在做垃圾分类视觉方案的算法工程师、准备毕业设计的大学生以及想快速验证业务可行性的产品原型团队。不过拿到手别急着开训压缩包里数据结构、标注质量和类别分布都有隐藏信息先花半小时把家底盘清楚比直接跑一轮训练划算得多。2. 数据画像与标注格式先看清这13707张图能干什么不能干什么2.1 检测对象与场景构成这8个类别覆盖了社区回收箱和分拣线上最常见的可回收物。纸箱和硬纸板在外观上高度相似瓶子与塑料瓶在拍摄角度不理想时也容易混淆而铝罐反光会让YOLO在特征提取时产生较大波动。标注质量决定模型上限场景多样性决定泛化能力。拿到压缩包后我一般先把样本量按类别走一遍确认每个类别大致分布。# 统计每个类别的标注框数量了解数据分布 cd dataset/labels for f in *.txt; do cat $f; done | awk {print $1} | sort | uniq -c | sort -nr逻辑说明这个脚本把所有txt标签文件的内容拼接取每行第一个字段类别ID再按类别聚合统计。输出的数字就是每个类别出现的总次数。如果某一类只有几百框而另一类有几千框说明数据严重不平衡后面要调整损失权重或者做针对性增强。注意这里的类别ID不是类别名称映射关系要看zip里自带的yaml配置文件。别在没核对映射表之前就开训否则会出现模型把纸箱学成玻璃的笑话。2.2 YOLO标签格式五个数字一行缺一不可这个数据集压缩包里的标签文件基本都是TXT文本每行五个数字类别ID、归一化中心点x、归一化中心点y、归一化宽度、归一化高度。坐标归一化的基准是图片宽高所有数值都在0到1之间。训练时YOLO算法会直接读取这些坐标并映射回原图尺寸。这里有个很容易踩的坑如果数据集中混入了VOC或COCO格式的XML标注未经转换直接训练模型会以几乎为零的召回率收场。# 快速预览一张图的标注内容验证坐标是否在合法范围 import cv2 img cv2.imread(images/000001.jpg) h, w img.shape[:2] with open(labels/000001.txt, r) as f: lines f.readlines() for line in lines: cls, x_center, y_center, bw, bh map(float, line.split()) x1 int((x_center - bw / 2) * w) y1 int((y_center - bh / 2) * h) x2 int((x_center bw / 2) * w) y2 int((y_center bh / 2) * h) print(fclass{int(cls)}, box({x1},{y1})-({x2},{y2}))逻辑说明这段代码读取图片尺寸再把归一化的中心点和宽高换算成像素坐标并打印出边界框的绝对位置。跑出来后重点看坐标是否越界比如x2超出图像宽度以及框是否明显偏小。如果发现大目标框出界说明数据集里混入了另一种坐标体系——常见做法是用YOLO官方仓库自带的格式检查脚本统一修正。参数说明x_center和y_center是归一化值乘以宽高w、h后才是真实像素坐标。有些开发者图省事直接用整数坐标存成txtYOLO算法读取后会按归一化处理导致标注框全部偏移模型输出一堆错位的预测框这种事我在实践中见过不止一次。2.3 光照、拍摄角度与共现场景垃圾检测和行人检测最大的区别在于目标形态极其不固定纸箱被压扁后是一个平面立起来是一个立体塑料瓶被踩扁后轮廓扭曲铝罐在强光下出现高光斑块。这批数据如果多数是室内桌椅上的摆拍图模型在户外垃圾桶边上的表现会大幅下降。因此拿到数据集后先抽出几张图看看背景构成确认有没有露天垃圾堆、传送带、社区垃圾桶等真实场景。完全没有的话训练后的模型在户外场景中会出现漏检率偏高的问题这时需要在项目中补充实地采集数据做二次微调。2.4 类别映射类名顺序决定一切压缩包里通常会附带一份data.yaml或者classes.txt文件内容类似“0: carton, 1: paper, 2: plastic, 3: aluminum, 4: glass, 5: cardboard, 6: bottle, 7: plastic_bottle”。如果这份文件缺失可以拿任意一个txt标签文件的类别ID去对照图片内容反推。这个顺序必须和训练脚本保持一致。我的习惯是把yaml单独复制到训练目录用绝对路径引用避免因为工作目录变动导致找不到数据集。# 数据集配置文件示例 path: /your/absolute/path/garbage_dataset train: images/train val: images/val names: 0: carton 1: paper 2: plastic 3: aluminum 4: glass 5: cardboard 6: bottle 7: plastic_bottle参数说明path建议写绝对路径。train和val指向的是存放图片的目录不是txt标签目录YOLO算法会按同名规则自动匹配images和labels下的文件。names列表的索引必须和标注txt里的第一个字段严格对应。如果压缩包自带的yaml里已经有这个映射不要手动重排顺序否则训练出来的类别全错位。3. 数据清洗与训练集划分别让脏标注拖垮YOLO算法3.1 标注框可视化检查最笨但最有效的抽检方式数据集的标注质量直接影响训练收益。跑模型前我会先抽样200张图把标注框直接画上去人工过一遍。这一步不要省它能发现三类问题标签与物体不匹配、目标太小无法学习、边界框偏移导致IoU计算异常。画框脚本非常简单几分钟就能跑完。import cv2 import glob files glob.glob(images/train/*.jpg)[:200] for f in files: img cv2.imread(f) h, w img.shape[:2] label_path f.replace(images, labels).replace(.jpg, .txt) with open(label_path, r) as fp: for line in fp: cls, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(fdraw/{f.split(/)[-1]}, img)逻辑说明逐张读取图片和同名txt标签在图上画出绿色边界框并保存到draw目录。检查时记录三个现象标签框内看不到对应物体、两个类别共享一个框、框内物体只占框面积的10%不到。第一类直接删掉样本第二类看情况拆框或删除第三类在训练时把img_size放大到640以上小目标召回率能明显提升。3.2 按场景划分而非随机划分防止指标虚高的关键操作直接随机划分训练集和验证集在垃圾检测上会翻车。原因在于同一批垃圾堆经常连续拍摄几十张随机划分会让相似图片同时进入训练集和验证集模型在验证集上的表现被高估。常见做法是按图片的拍摄批次或者连续编号分组把同一个来源的图片放进同一集合验证集只用来评估没见过的场景。import os import shutil from sklearn.model_selection import GroupShuffleSplit image_files sorted(os.listdir(images)) groups [f[:-4].split(_)[0] for f in image_files] split GroupShuffleSplit(n_splits1, test_size0.2, random_state42) train_idx, val_idx next(split.split(image_files, groupsgroups)) for i in train_idx: src_img fimages/{image_files[i]} src_lbl flabels/{image_files[i][:-4]}.txt shutil.copy(src_img, images/train/) shutil.copy(src_lbl, labels/train/) for i in val_idx: shutil.copy(fimages/{image_files[i]}, images/val/) shutil.copy(flabels/{image_files[i][:-4]}.txt, labels/val/)参数说明GroupShuffleSplit按groups的值分组保证同一组内的图片不会被拆散。test_size0.2意思是验证集占20%对13707张图来说验证集约2700张足够了。random_state固定为42保证重复执行结果一致。文件名前面的前缀怎么提取取决于压缩包原始命名规则如果命名本身没有批次信息只能靠拍摄时间戳或者目录结构来分组。3.3 类别权重不平衡数据集的后悔药垃圾检测天然存在类别不平衡纸箱和瓶子数量多铝罐和玻璃数量少。训练时不处理模型对多数类过拟合少数类几乎全漏。两种常见做法一是计算每个类别的权重传给损失函数二是对少数类做过采样。经验之谈权重法在多数场景下够用。from collections import Counter all_labels [] for f in os.listdir(labels/train): with open(flabels/train/{f}) as fp: for line in fp: all_labels.append(int(line.split()[0])) counter Counter(all_labels) total sum(counter.values()) weights {k: total / (len(counter) * v) for k, v in counter.items()} print(weights)逻辑说明统计训练集中每个类别出现的次数然后按总数除以类别数与频次乘积的公式计算权重。频次低的类别拿到更大的权重反向传播时梯度更新幅度更大模型被迫多关注这些类别的特征。打印出来的权重字典可以直接转成YOLO训练脚本里的class_weights参数也可以进配置文件。4. YOLO算法训练参数第一次跑通垃圾检测的配置模板4.1 训练命令与基础参数以当前主流的YOLOv8为参照第一次跑这个数据集建议用默认配置起步不要上来就魔改。先把环境跑通看Loss曲线是否收敛再根据结果调整。命令行如下yolo train datagarbage.yaml modelyolov8s.pt epochs100 imgsz640 batch16 device0逻辑说明data指向写好的garbage.yamlmodel指定预训练权重yolov8s.pt。用s版本是因为它在精度和速度之间比较平衡。epochs设100配合早停机制防止过拟合。imgsz640是YOLO系列最通用的输入尺寸垃圾目标大小不一640能保留更多细节。batch16在大多数16GB显存显卡上可以跑。device0表示用第一张GPU。4.2 训练参数速查表参数推荐值说明imgsz640目标较小时可提升到768batch16显存不够则降为8epochs100配合早停避免无效训练optimizerAdamW收敛平稳lr00.01SGD的话建议用0.01AdamW可降到0.002patience20连续20个epoch没提升就停cos_lrTrue余弦退火后期收敛更细上面的表对训练YOLO算法参数体系的参考价值比较大但要清楚垃圾检测所在的边界如果你的部署设备是Jetson Nano这类低算力板子建议把imgsz降到416推理速度提升明显精度损失可以接受。如果现场光照变化剧烈闭着眼睛调brightness、contrast增强数据往往没有直接引入图像自适应增强效果来得实在。4.3 数据增强参数垃圾检测场景怎么调YOLO算法默认开启Mosaic和MixUp增强对垃圾检测有利有弊。Mosaic把四张图拼成一张增加了小目标密度铝罐这种小目标反而受益但Mosaic生成的拼接图会有明显的边界线模型学到的可能是不自然的拼接纹理。如果训练过程中发现val loss在后期反复震荡可以考虑关闭Mosaic增强只用RandAugment。augment: mosaic: 1.0 mixup: 0.2 fliplr: 0.5 scale: 0.5 translate: 0.1 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4参数说明fliplr是水平翻转概率垃圾目标没有方向性设0.5没问题。scale设0.5表示缩放范围较大模拟远近视角。hsv_h、hsv_s、hsv_v是色相、饱和度、明度的扰动幅度现场光线变化大的场景可以适当加大hsv_s但幅度太大容易让颜色特征失真。玻璃和塑料瓶很多靠颜色和反光区分过度调色反而让类别更难分。4.4 迁移学习预训练权重怎么选用yolov8s.pt初始化比从零训练省一半时间而且收敛效果更好。前几轮训练会冻结Backbone的参数只更新检测头。这里有个常见的疑问垃圾检测和COCO数据集的目标差别很大迁移学习还有用吗答案是仍然有用。COCO预训练学到的是边缘、纹理、形状等底层视觉特征垃圾检测只是在这些特征上重新组合。# 部分冻结Backbone训练先训练检测头再解冻全部 model YOLO(yolov8s.pt) model.train( datagarbage.yaml, epochs50, freeze10, lr00.005 )参数说明freeze10表示冻结模型前10层通常是Backbone部分只更新检测头权重。这种方式在数据集风格和预训练数据差异大时尤其有效。50轮之后再用完整模型继续训练20轮让Backbone重新适应垃圾目标的纹理和反光特征。这种两阶段训练在垃圾检测上是性价比最高的做法。5. 垃圾检测数据集避坑五个给我上过课的问题5.1 现象Loss下降但mAP始终为零训练过程中训练损失在下降验证集mAP却一直是0。原因是标签类别ID与yaml里的names顺序错位。比如yaml里0是纸箱、1是纸张但压缩包里0其实是纸张、1是纸箱。模型学的语义和标注语义完全对不上输出当然判错。解决训练前先人工比对10张图的标注内容和标签ID。具体的操作是把图片和txt标签对照看用可视化脚本画框后手动确认类别名称。别相信压缩包里的yaml自带的顺序自己核对一次再开训。5.2 现象验证集上铝罐漏检率极高大多数情况下是类别样本量太少模型没学到足够的铝罐特征。铝罐反光强表面纹理又和纸张、塑料差异大样本少时很容易被当成背景。解决在训练配置里提升aluminum类的损失权重另外对铝罐样本做复制粘贴增强。压缩包里如果铝罐只有几百框建议单独采集一些铝罐在不同背景下的图像补进数据集比任何训练技巧都有效。如果不想扩充数据把img_size从640升到768通常能带来小幅提升代价是训练时间和显存消耗增加。5.3 现象解压后文件路径包含中文导致训练报错Windows下解压zip时常常生成带中文的文件夹名或者图片文件名里包含中文空格。YOLO算法对路径敏感读取失败时抛出“Unable to read image”之类的异常。这种情况偶发跑了十几个epoch才崩很浪费时间。解决解压后马上重命名目录和所有文件统一用英文小写加数字用下面这段脚本清洗find . -depth -name * * -exec rename s/ /_/g {} find . -depth -name *.JPG -exec mv {} {}.jpg \;逻辑说明第一条命令把所有包含空格的路径替换成下划线第二条把大写的JPG后缀统一改成小写jpg。在Linux下执行前先备份Windows下可以用批量重命名工具操作。这类文件系统问题越早处理越好训练跑到一半再排查耗时且影响心态。5.4 现象验证集指标很好部署到现场却大面积漏检模型在验证集上mAP很高但拉到实际场景就翻车。多半是验证集划分方式的问题随机划分导致同场景图片同时出现在训练集和验证集评估结果虚高。实际场景中光线变化、遮挡、垃圾堆叠等未见过的条件让模型难以招架。解决严格按照3.2节的方式按场景分组划分数据集。如果部署现场与训练集差异太大唯一可靠的路径是采集现场数据做增量训练前期的验证集划分只是确保模型在类似场景上可用无法避免场景迁移带来的性能下降。5.5 现象纸箱和硬纸板混淆严重混淆矩阵上这两类互相串这两个类别从视觉上看太接近标注人员自己都容易判错标签错误又进一步加剧模型混淆。如果分不清这两个类别的边界模型训练时等于在学习标签噪声。解决把纸箱和硬纸板合并成同一类。对实际业务来说回收箱并不关心纸箱和硬纸板分开计费合并后模型精度立刻提升业务上也更合理。如果业务上必须区分需要重新整理数据把标注人员叫回来统一标注标准删除模棱两可的样本。6. 评估与导出用mAP和混淆矩阵判断模型能不能上产线训练完成后先跑验证集拿到mAP50、mAP50-95和混淆矩阵。mAP50反映的是宽松IoU下的检测能力mAP50-95更严格。垃圾检测场景中mAP50达到0.85以上、mAP50-95达到0.6以上基本满足试点要求。但这只是第一步还要把验证集按类别拆开看确认铝罐和玻璃不拖后腿。yolo val modelruns/train/exp/weights/best.pt datagarbage.yaml splitval输出会包含每个类别的mAP。如果铝罐的mAP50低于0.5模型不适合直接上产线。混淆矩阵图片保存在runs目录下重点关注对角线之外的值尤其是纸箱和硬纸板、瓶子和塑料瓶之间的错误条带。确认模型可用之后下一步是导出部署格式。边缘设备大多只跑ONNX或TensorRTYOLO官方仓库直接支持导出yolo export modelruns/train/exp/weights/best.pt formatonnx imgsz640 opset12参数说明format指定导出格式onnx是通用性最好的中间格式可以再转TensorRT或者OpenVINO。opset12是兼容性较好的算子版本太新可能导致旧设备不支持。导出后用ONNXRuntime做一次推理测试确保输出张量的维度、置信度阈值、NMS后处理逻辑和训练时一致。很多部署翻车都发生在后处理环节模型输出没问题代码里把box坐标还原错了位置。部署时给置信度阈值留一点余量。训练时验证集上0.5阈值效果不错现场可以降到0.35试试观察误检率再逐步调回去。这个数值没有绝对标准跟现场干预的频率、误检的成本有关。我用过的项目里投入产线运行的垃圾分类盒子通常设0.45到0.55之间偏低会造成误检偏高则漏检需要根据实际试运行数据确定。最后说一个我自己的习惯每个数据集版本都建一张评估卡记录训练参数、每类mAP、失败样本截图。有新的数据进来时先跑一遍老模型做回归测试再决定要不要重新训练。做垃圾检测这类长尾分布明显的数据最怕的不是模型学不会而是你忘了当初在什么条件下调出来的结果。评估卡把各类在光照变化、遮挡、夜间场景下的表现记下来后续迭代时对照着看思路会清晰很多。这个方向值得投入但前提是把数据当成产品一样认真对待。希望帮到你。本文还有配套的精品资源点击获取