
简介这是一份面向垃圾分类场景的YOLO格式标注数据集适用于目标检测模型训练、智能分类系统开发及环境工程研究。数据涵盖可回收垃圾、有害垃圾、厨余垃圾和其他垃圾四类标注信息以文本文件形式保存并配有类别定义文件可直接接入YOLO系列主流检测框架。压缩包共含2000个文件包括1999个标注文本和1个类别配置声明总大小约540.75MB目录结构清晰便于按类别筛选和批次训练。该资源目前已有2088人学习使用受到目标检测方向开发者的关注适合深度学习和计算机视觉方向的入门及进阶用户。使用此数据集可以免去人工标注的繁琐工作直接获得带目标框与类别标签的样本用于训练垃圾识别模型、评估网络性能或部署于智能垃圾桶、社区分类督导等场景促进垃圾分类自动化与准确率的提升。1. YOLO垃圾四分类数据集模型不背锅数据先过关很多人拿到一份YOLO垃圾四分类数据集第一反应是赶紧调参、换网络结构结果训练十几个版本mAP卡在0.7上不去换到真实垃圾桶旁边一测更是翻车。我的判断一直没变这种任务的分水岭不在模型而在数据集本身。所谓YOLO垃圾四分类数据集核心不是一堆图片而是把垃圾图像整理成一份能让YOLO正常训练目标检测模型的数据资产包含类目怎么定义、样本怎么采、标注怎么管、格式怎么转、类别怎么平衡。它解决的是算法团队“一训就飘、一测就废”的问题适合做智能分拣、环卫监管、社区垃圾房管理的工程师也适合拿真实任务入门目标检测的初学者。这篇就按做数据集的完整顺序把类目边界、采集清洗、格式转换、训练验收一次讲透。2. 垃圾到底分哪四类类目体系与标注边界四分类的语义是处理流向上的差异不是材料学上的差异。同一个塑料瓶干净的瓶和沾了食物残渣的瓶可能分属两类。所以做数据集的第一步不是找图而是先把类目体系和标注边界定死否则后面标注员每标一张图都在替你“做算法决策”。2.1 四分类的内核是处置流向不是材料学国内最常见的清运体系把生活垃圾分为可回收物、有害垃圾、厨余垃圾、其他垃圾也就是俗称的四分类。目标检测模型要回答的问题是“这张图里的物体属于哪个处置流向”而不是“这个瓶子是什么材料”所以类别粒度不需要精细到PET瓶、乳白玻璃瓶、铝罐那种粒度属于材料分选场景不在四分类讨论范围内。四分类是检测任务里最低可用的粒度。再少就是二分类失去场景意义再多就进入三四十类的细分类标注成本和相邻类别混淆会同时爆炸。实际工程里有一个很常见的麻烦“其他垃圾”本质上是一个杂类语义不收敛很多团队做完第一版后会考虑把“其他”拆成“烟蒂”“使用过的纸巾”“灰土”等子类训练时再合并回去这个策略后面展开讲。类别索引类别名典型实例边界容易踩的实例0可回收物塑料瓶、纸箱、易拉罐、玻璃瓶沾油污的塑料餐盒应归厨余1有害垃圾电池、灯泡、过期药品、油漆罐充电宝一般走可回收专项不等于有害2厨余垃圾菜叶、果皮、剩饭、蛋壳带残渣的外卖打包盒应归厨余3其他垃圾烟蒂、灰土、陶瓷碎片、用过的纸巾陶瓷碗碟在不同城市规则不同需与需求方确认类目清单建议用一份独立的配置文件管理训练脚本和标注平台都从这里读取。我一般写成YAML避免在代码里硬编码类别名# 类目清单顺序即YOLO类别索引发布后不要中途插队 categories: - id: 0 name: recyclable cn_name: 可回收物 deploy_name: recyclable - id: 1 name: hazardous cn_name: 有害垃圾 deploy_name: hazardous - id: 2 name: kitchen_waste cn_name: 厨余垃圾 deploy_name: kitchen_waste - id: 3 name: other_waste cn_name: 其他垃圾 deploy_name: other_waste逻辑说明YOLO的类别索引从0开始txt标签里写的数字就是这份清单的id。类别顺序一旦发布后面不要再插入新类否则旧标注文件里所有类别索引全部错位这个错位不会报错只会让模型安静地学错。deploy_name是部署时的输出名称训练名和推理名必须完全一致很多上线事故就是“训练叫recyclable推理叫recycle”。注意类目清单每次修改都要打版本号并且连同标注文件一起归档。没有版本管理的类目清单三个月后连你自己都说不清0号到底代表什么。2.2 标注边界规范比模型更重要的是“不纠结”多人标注同一个数据集时最大的消耗不在画框而在对边界对象的不同判断。同样一张“外卖盒里有剩饭”的照片有人归厨余有人归可回收这个不一致会直接变成训练噪声而且是模型自己消化不了的噪声。我建议立三条硬规则。第一维护一份难例清单凡是标注员拿不准的物体先查清单查不到就开会定定完同步给所有人。第二当目标被遮挡超过50%或距离太远看不清时宁可跳过不标也不要强行画一个猜出来的框。第三单张图的实例数上限控制在30个左右超过上限的图改成挑大目标标标注密度过高对训练收益的提升非常有限。难例清单用JSON维护每条记录包含物品特征、判定结论和理由训练完一轮后把误检图追加进来形成闭环{ hard_cases: [ {item: 带食物残渣的外卖盒, target_class: kitchen_waste, reason: 内容物污染后不再具有可回收价值}, {item: 一次性纸杯, target_class: other_waste, reason: 淋膜纸不易回收按其他垃圾处理}, {item: 玻璃碎片, target_class: hazardous, reason: 易划伤清运人员按有害垃圾处理} ] }逻辑说明这份清单不是一次性工作它是数据集的活文档。每次模型在真实场景里出现bad case先检查是不是类目定义本身的问题再决定改标注、改规则还是改模型。质检方面前500张标注全量检查之后每批抽检30%错标率超过5%就全部返工。这5%的返工线是很多团队忽略的参数但它的重要性不亚于学习率。3. 图像从哪来、怎么变多采集、清洗与增强实操类目定义好之后下一步就是把图集堆起来。很多团队找图就像拼布头先不论版权问题光是把分辨率混乱、光照差异大、带水印的图混进训练集就比任何超参数都伤模型。这一章讲采集路线的选择、清洗脚本的写法、增强参数怎么定。3.1 三条采集路线与数量目标采集路线通常有三条。第一条是自采实拍用手机或摄像头去垃圾桶旁、人行道、清运车、社区垃圾房拍覆盖白天、夜晚、阴天等光照条件。优点是场景分布可控后续做回放集测试也有地基。第二条是按四分类关键词批量抓取公开图片注意关键词语义要拆细“易拉罐 地上”比“垃圾”好用一个量级还要确认图片的使用条款。第三条是复用已有的目标检测数据集或公开数据集做二次筛选但必须逐类核对语义有些数据集里的“报纸”是人在读报的场景模型学到的是人不是报纸这种图要直接删掉。数量目标我一般按一个底线来规划每个类别至少要有1000张图像、2000个标注实例四分类总量在6000到8000张图像起步。这里有个新手容易理解错的点实例数比张数重要。YOLO在训练时吃的是框不是图300张图每张5个实例效果会好过1000张图每张只有0.3个实例。类别建议图像张数建议实例数下限建议场景数可回收物150025008个以上有害垃圾80012006个以上厨余垃圾120020006个以上其他垃圾150025008个以上有害垃圾的收集难度最大电池、灯泡这类物品在自然场景里出现频率低我的经验是先用少量场景保证实例数再通过增强补足而不是硬凑张数。3.2 清洗流程一个脚本去掉模糊、重复、损坏图抓来的图不能直接进标注流程因为重复图、模糊图、损坏图会同时污染训练和验证。我常年保留一个清洗脚本处理三类问题无法解析的损坏文件、清晰度不够的模糊图、内容几乎一致的重复图。import os import shutil import numpy as np from PIL import Image from scipy.ndimage import laplace def dhash(img, hash_size8): small img.convert(L).resize((hash_size 1, hash_size), Image.LANCZOS) arr np.array(small, dtypenp.uint8) return (arr[:, :-1] arr[:, 1:]).flatten() def hamming(a, b): return int(np.count_nonzero(a ! b)) def blur_score(path): img np.array(Image.open(path).convert(L), dtypenp.float32) return laplace(img).var() os.makedirs(bad, exist_okTrue) os.makedirs(blur, exist_okTrue) os.makedirs(dup, exist_okTrue) seen_hashes [] for name in os.listdir(raw_images): path os.path.join(raw_images, name) if not name.lower().endswith((.jpg, .jpeg, .png)): continue try: img Image.open(path) score blur_score(path) except Exception: shutil.move(path, os.path.join(bad, name)) continue if score 80: shutil.move(path, os.path.join(blur, name)) continue h dhash(img) if seen_hashes and min(hamming(h, p) for p in seen_hashes) 5: shutil.move(path, os.path.join(dup, name)) continue seen_hashes.append(h)逻辑说明dhash把图片缩放到9×8的灰度图比较相邻像素的明暗变化得到一个64位哈希两张图哈希距离小于5就判定为重复。这个阈值是关键参数改太大会把同一场景不同角度的照片也误杀改太小则漏掉压缩率不同的副本。blur_score用的是拉普拉斯算子的方差方差越低说明边缘越弱、图像越糊。参数说明拉普拉斯方差阈值80不是普适值分辨率越高通常数值越高网络抓来的大图经常超过500而手机暗光照片可能只有50到150。建议先跑一个统计分布取明显偏低的那一段作为阈值不要照着别人的参数抄。另外blur目录里的图也不是直接删偶尔会有人物主体模糊但垃圾很清晰的情况我一般会二次人工扫一眼再清空。3.3 离线增强与在线增强哪些场景真的需要增强策略分为两件事。离线增强服务于类别数量补差对有害垃圾这种少数类我会对原始图做复制、水平翻转、小幅HSV扰动生成额外的训练副本。在线增强则在训练配置里开启YOLO自带的Mosaic等策略会实时拼接图像覆盖面比离线增强更随机。需要强调的是四分类场景的增强参数要克制尤其是颜色扰动不能拉太大。可回收物里的纸箱饱和度偏低其他垃圾里的包装袋是浅棕色HSV的饱和度扰动过强会让这两个类互相渗透。我常用的起步参数是flip0.5HSV的h0.015、s0.5、v0.4mosaic1.0scale0.5全部保持中等强度。注意不要对四分类做大幅度随机旋转和透视变形。垃圾桶里的瓶子是自然摆放姿态不是艺术创作过度变形只会让模型学到扭曲的特征真实场景里反而更差。4. 把任意标注格式转成YOLO txt转换脚本与硬性检查YOLO训练要求的标签格式是每张图一个txt文件每一行写“类别索引 中心点x 中心点y 宽度 高度”坐标全部归一化到0到1之间。但标注平台导出的格式五花八门最常见的是COCO JSON和自定义JSON转换本身不难坑全在转换完没有质检。这一章给出转换脚本、检查命令和划分逻辑。4.1 YOLO txt格式的三个约定先记住三个约定。第一文件配对严格按图像主文件名走a.jpg对应a.txt两个文件要么放同一目录要么在训练配置里分别指定图像目录和标签目录。第二坐标必须归一化计算方式是矩形中心点x除以图像宽度中心点y除以图像高度宽度除以图像宽度高度除以图像高度。第三类别索引从0开始必须和类目清单保持一致。COCO JSON里的bbox字段是[x, y, w, h]且是像素坐标x、y是左上角点这个细节搞反转换出的框位置全部偏移。4.2 从COCO JSON转YOLO txt脚本与参数说明下面这个脚本是我常用的转换工具支持类别索引重映射适合从公开数据集筛选后做二次标注的场景。import json import os def coco_to_yolo(coco_json, image_dir, out_dir, label_map): os.makedirs(out_dir, exist_okTrue) with open(coco_json, r, encodingutf-8) as f: data json.load(f) images {img[id]: img for img in data[images]} anns_by_img {} for ann in data[annotations]: anns_by_img.setdefault(ann[image_id], []).append(ann) for img_id, im in images.items(): lines [] for ann in anns_by_img.get(img_id, []): x, y, w, h [float(v) for v in ann[bbox]] if w 0 or h 0: continue cls label_map.get(ann[category_id], -1) if cls 0: continue # 中心点坐标换算除以图像宽高完成归一化 cx (x w / 2) / im[width] cy (y h / 2) / im[height] bw w / im[width] bh h / im[height] # 越界值裁剪到0-1防止训练增强时出现非法anchor cx max(0.0, min(1.0, cx)) cy max(0.0, min(1.0, cy)) lines.append(f{cls} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}\n) if lines: base os.path.splitext(im[file_name])[0] txt_path os.path.join(out_dir, base .txt) with open(txt_path, w, encodingutf-8) as f: f.writelines(lines) if __name__ __main__: # 原数据集类别id映射到我们的四分类索引没有映射的一律跳过 label_map {5: 0, 3: 1, 8: 2, 6: 3} coco_to_yolo(coco.json, images, labels, label_map)逻辑说明代码先按image_id聚合标注这样每张图只打开一次txt文件。label_map是类别索引的桥梁公开数据集的类别id几乎不可能和四分类对齐必须有这张映射表。bbox的w和h已经包含宽高信息不需要再用右下角坐标减去左上角。参数说明中心点坐标做了max/min裁剪因为标注框偶尔会超出图像边界几个像素YOLO的增强模块对越界框做缩放时可能生成非法值fp16下更容易触发NaN。但宽度和高度不裁剪因为一个小目标部分超出边界是正常情况裁剪宽度会导致框的面积失真。4.3 转换后的硬性检查空标签、类别越界、实例统计转换完不能直接开训先用几条命令做硬性检查。我习惯把检查结果输出到日志文件而不是只扫一眼终端输出。# 检查空标签有多少张图片没有对应的txt文件 for img in images/*.jpg; do base$(basename $img .jpg) if [ ! -f labels/$base.txt ]; then echo MISSING $base fi done # 检查类别索引越界四分类合法索引是0-3 grep -E ^[4-9] labels/*.txt | head -50 # 统计每个类别的实例数看类不均衡程度 cat labels/*.txt | awk {print $1} | sort | uniq -c逻辑说明空标签不会让训练直接报错但会把整张图当背景如果空标签集中在某些特定场景模型会降低对那个场景的召回率。类别索引越界几乎都是label_map写错或者旧版本的标签文件混进了新目录。实例数统计是类不均衡的第一道检查如果某一类占总实例数不足10%就需要回到采集阶段补数据。注意实例统计里有一个容易漏掉的坑就是同一张图在清洗阶段被移动到blur或dup目录后图片文件还在但它的标注文件被留在了原目录这个“图没了标签还在”的问题会让训练时的图像和标签错位。建议转换前把图片目录和标签目录做一次全量配对比较。4.4 数据集划分按场景分组再随机别让评测集“透题”数据划分看起来简单实际上是最容易让验证指标虚高的环节。连续拍摄的照片同一个垃圾桶在两秒内拍了10张如果直接全局随机划分其中5张进训练集、5张进验证集验证集就“见过”训练的同一场景测出来的mAP自然漂亮部署到新场景立刻回落。我一般会先按文件名前缀提取场景标识把同一场景的照片绑在一起再按场景划分到train、val、testimport os import random from collections import defaultdict groups defaultdict(list) for f in os.listdir(images): scene f.split(_)[0] # 场景前缀例如 street_001.jpg - street groups[scene].append(f) random.seed(42) train, val, test [], [], [] for scene_files in groups.values(): random.shuffle(scene_files) n len(scene_files) train scene_files[:int(n * 0.8)] val scene_files[int(n * 0.8):int(n * 0.9)] test scene_files[int(n * 0.9):]逻辑说明按场景分组后同一个场景的全部照片要么都在训练集要么都在验证集不会两边各占一半。这种做法会让验证集mAP比“透题版”低几个点但那是真实水平。参数上train:val:test按8:1:1切test从始至终不参与调参只在最终版本上跑一次。5. 垃圾四分类数据集常见问题排查5个高频坑的现象、原因、补救数据准备好之后训练过程依然有坑而且这些坑大多不是调参能解决的是靠改数据或改评估协议解决。以下5条是我在四分类项目里反复遇到的按现象、原因、解决三部分来写方便对照排查。5.1 标注层的坑错标传染、杂类不收敛、空标签引发NaN坑1错标率超过3%时mAP开始失灵。现象是训练loss正常下降验证mAP也不差但抽查预测结果发现错误集中在同一种物品上比如模型把烟盒当其他垃圾、把纸巾当厨余垃圾。原因是那一类物品的标注本身不一致不同标注员对同一物品的判断不同YOLO在类间语义接近时会学平均特征等于被噪声拉偏。解决办法是抽检500个框错标率超过3%就返工并针对bad case物品做全量复查。前期多花一天返工后期能少调两周参数。坑2“其他垃圾”是杂类模型会把它当垃圾桶。现象是验证集里“其他垃圾”的误检测集中在所有非标注区域模型输出大量假阳框。原因是“其他垃圾”的定义是“不属于前三类”语义上是开放集合闭合分类器对开放类别天然不友好模型找不到内部一致的模式。解决办法是做数据时把“其他垃圾”按常见子类拆开标注比如烟蒂、纸巾、灰土、陶瓷碎片训练时再合并到一根让模型至少学会每个子类的视觉特征。坑3标注坐标越界导致训练中途出NaN。现象是loss前几个epoch正常某次保存后突然变成NaN或者加载预训练权重后一训练就爆。原因是标签里出现了1.0001这种越界坐标YOLO的增强模块对越界框做缩放时产生非法anchorfp16下更敏感。解决办法是转换脚本里严格用max/min裁剪所有中心点坐标到0-1并在训练前检查所有txt文件里是否存在大于1或小于0的值。5.2 数据分布层的坑不均衡的“难易度”、同场景泄漏坑4类不均衡不只在数量更在“难易度”。现象是有害垃圾AP只有0.4其他三类都在0.7以上即使加了类权重提升也有限。原因是数量少只是表面原因深层原因是“有害垃圾”出现的位置五花八门桌面、角落、垃圾袋内都有每张图的上下文差异巨大模型很难学到稳定的判别特征。解决办法是不要硬上过采样而是把一半“干净桌面上的电池”图删掉换成一米外地面杂物里露出一角电池的难例。实例数和难易度的平衡比单纯凑数量更重要。坑5训练和验证同场景泄漏本地mAP虚高。现象是本地验证mAP等于0.84去一个新小区拍了一组真实环境图测试mAP掉到0.58。原因是划分数据时没有按场景分组同一个垃圾桶的连续帧同时出现在train和val。解决办法是改用上一章的按场景分组划分法重建训练集并且在项目上线前去没见过的现场拍100张图做盲测集之后每个版本都用同一批盲测图回测。盲测集一旦用于调参就会慢慢变成第二个验证集失去盲测意义所以它必须是只跑不改的。6. 用回放集和混淆矩阵验收数据集一个耐用的迭代习惯数据集不会一次做对真正让工程质量提升的是验收习惯。我现在的做法是给每个四分类项目维护一个“回放集”核心规则有两条。第一条回放集里的图像只来源于真实现场比如小区门口、垃圾房、清运车每个季度新增一批新增的图像标注后全部并入回放集不并入训练集。因为训练集可以持续变大但验收集必须保持独立否则模型只是在考试里见过原题。第二条每次训练完不看单一mAP先看混淆矩阵里哪两个类别互相污染最严重。四分类场景的混淆矩阵有一个典型规律“可回收物”和“其他垃圾”互窜的频率远高于其他组合原因是两者的外观边界模糊纸箱、包装袋、一次性塑料制品在不同光照下很容易交叉。如果混淆矩阵显示某个类别的召回率明显低于其他类我一般直接回到数据层面查三件事实例数是否偏少、难例图是否没有覆盖、标注规则是否在那个类里有分歧。查完这三件事再去调超参数效率高很多。除了混淆矩阵我还会保存每一轮的bad case图。具体做法是训练完后挑出置信度大于0.5但预测错误的框按预测类别分组每个组看一遍。这一步虽然耗时间但能发现很多标注阶段漏掉的问题比如某个场景里所有“矿泉水瓶”都被标成了“其他垃圾”这种标注层面的大面积错误在loss曲线和mAP上几乎看不出来只有看bad case才能定位。我现在养成的习惯是每两周从现场采集100到300张图人工标注后全部追加到回放集然后重新训练一轮把新旧版本的混淆矩阵和bad case对比一遍。这个循环看起来很土但它帮我省掉了大量“不知道为什么这版变差了”的黑匣子排查时间也让每个训练版本都有明确的验收标准。如果你正被四分类数据集折磨不妨从今天开始建一个只属于你自己的回放集坚持三个版本后再回头看会感谢这个习惯的。希望帮到你。本文还有配套的精品资源点击获取