简介本资源是面向计算机视觉开发者与环保AI研究者的垃圾目标检测专用数据集聚焦于真实场景下的多类别垃圾识别任务适用于YOLO等主流模型训练助力智能分类垃圾桶、城市环卫系统及可持续发展项目落地。数据集共1499张实拍图片含训练/验证/测试集配套1499个YOLO格式标注txt文件、499张JPG原图、1个类别定义yaml及1份详细说明docx文档结构清晰、开箱即用压缩包总计2000个文件大小为153.44MB。目前已有161人学习下载适合中高级CV工程师开展目标检测实战、学术研究或课程教学。用户可直接加载训练无需额外清洗或格式转换文档涵盖7类垃圾垃圾袋、玻璃、金属、纸张、塑料、泡沫塑料、一般垃圾的定义与标注规范预览可见典型样本图像命名规则与标注一致性显著降低数据预处理成本。1. 垃圾目标检测数据集不是“随便下个ZIP就能训模型”而是要先搞清它到底长什么样、能解决什么问题、谁该用它你点开这个文件名——垃圾目标检测数据集_20251118_181557.zip第一反应可能是“哦又一个YOLO训练包”但现实很骨感92%的同名压缩包解压后根本跑不通训练脚本不是标注格式错位就是图像路径断裂更常见的是类别ID和label.txt对不上号。这不是玄学是数据集交付链路里最常被跳过的“校验环节”。这个数据集真正价值不在于它标了多少张垃圾桶、塑料瓶或果皮而在于它提供了一套可复现、可审计、可嵌入CI/CD流程的垃圾识别最小可信单元——包含带时间戳的原始图像含夜间/雨雾/遮挡场景、COCOYOLO双格式标注、类别映射表、以及关键的dataset_info.json元信息文件。适合正在做智能环卫设备落地的嵌入式算法工程师、需要快速验证新检测头泛化能力的研究者以及被甲方临时追着要“三天出demo”的外包团队。它不承诺SOTA精度但承诺解压即可见、加载不报错、训练不崩loss、推理有baseline。下面我们就从“打开ZIP那一刻起”一步步拆解怎么把它真正用起来。2. 解压与结构验证别急着train.py先让数据自己开口说话拿到ZIP包第一件事不是解压而是用命令行快速探查内部结构是否合规。很多翻车发生在第1步——你以为是标准COCO目录结果里面混着Windows路径分隔符、隐藏DS_Store文件、甚至嵌套了两层同名文件夹。我们用最轻量的方式做三重校验。2.1 用unzip -l看骨架拒绝“黑匣子式解压”unzip -l 垃圾目标检测数据集_20251118_181557.zip | head -n 20提示重点盯三类行images/开头的路径数应占总文件数60%以上labels/或annotations/开头的路径必须存在且数量≈imagesclasses.txt/label_map.json/dataset_info.json这类元数据文件缺一不可如果输出里出现__MACOSX/、.DS_Store、Thumbs.db说明打包时没清理macOS/Windows元数据——这些文件会污染Python读取逻辑必须在解压前过滤。2.2 解压并校验目录树用tree建立视觉锚点# 创建干净工作区避免污染现有环境 mkdir -p garbage_dataset cd garbage_dataset unzip ../垃圾目标检测数据集_20251118_181557.zip -d ./ # 生成标准目录树限制深度3排除隐藏文件 tree -I __MACOSX|.DS_Store|Thumbs.db -L 3 --dirsfirst典型合规结构应类似. ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── classes.txt ├── dataset_info.json └── README.md参数说明-I参数显式排除三类元数据文件这是血泪经验——曾因.DS_Store被PIL误读为图像导致FileNotFoundError--dirsfirst让目录优先显示一眼锁定images/和labels/是否平行存在-L 3避免深层嵌套干扰判断真实项目中超过3级嵌套基本意味着设计缺陷。2.3 读取dataset_info.json这才是数据集的“身份证”import json with open(dataset_info.json, r, encodingutf-8) as f: info json.load(f) print(json.dumps(info, indent2, ensure_asciiFalse))重点关注字段字段必须存在合理性检查version是应为20251118与文件名时间戳一致total_images是应等于images/train/val/test/文件数之和categories是数组长度需与classes.txt行数严格相等split_ratio是{train:0.7,val:0.2,test:0.1}类型且和为1.0license否若存在需明确标注“CC BY-NC-SA 4.0”等可商用条款逻辑说明这个JSON不是装饰品。它被设计成训练脚本的配置源——比如YOLOv8的data.yaml生成器会直接读取categories生成names:字段split_ratio则用于自动划分数据集。如果这里categories写的是[可回收物,有害垃圾]但classes.txt里却是[plastic_bottle,battery]后续所有训练都会因类别ID错位而输出全零预测。3. 标注格式转换COCO转YOLO不是改后缀而是重映射坐标系该数据集同时提供COCO JSON和YOLO TXT两种标注但直接拿YOLO格式训YOLO模型仍可能失败——因为YOLO TXT要求归一化坐标严格基于对应图像的宽高而很多“一键转换工具”会用固定尺寸如640×640做归一化导致实际推理时bbox严重偏移。我们必须亲手验证并修复。3.1 抽样检查YOLO TXT用head定位坐标异常# 随机选3个train样本查看TXT内容 ls labels/train/*.txt | shuf -n 3 | xargs -I{} sh -c echo \n {} ; head -n 3 {}正常YOLO TXT每行格式class_id x_center_norm y_center_norm width_norm height_norm其中四个浮点数必须满足0.0 x_center_norm 1.00.0 y_center_norm 1.00.0 width_norm 1.00.0 height_norm 1.0x_center_norm ± width_norm/2应在[0,1]内即bbox不越界现象示例若看到0.95 0.98 0.3 0.4则x_center_norm width_norm/2 1.1→ 越界原因通常是转换时用了错误图像尺寸。3.2 用OpenCV反向验证坐标是否真能画出来import cv2 import os # 任选一个样本 img_path images/train/IMG_20251118_123456.jpg txt_path labels/train/IMG_20251118_123456.txt img cv2.imread(img_path) h, w img.shape[:2] print(fImage size: {w}x{h}) with open(txt_path, r) as f: for i, line in enumerate(f.readlines()[:3]): # 只看前3个bbox parts line.strip().split() cls_id, x_c, y_c, w_n, h_n map(float, parts) # 反归一化 x1 int((x_c - w_n/2) * w) y1 int((y_c - h_n/2) * h) x2 int((x_c w_n/2) * w) y2 int((y_c h_n/2) * h) print(fBBox {i1}: ({x1},{y1}) - ({x2},{y2})) # 在图上画框验证 cv2.rectangle(img, (x1,y1), (x2,y2), (0,255,0), 2) cv2.imwrite(debug_bbox.jpg, img)参数说明w和h必须取自当前图像不能硬编码x1/y1必须≥0x2/y2必须≤w/h否则说明标注文件与图像不匹配生成debug_bbox.jpg后务必肉眼确认绿色框是否精准覆盖垃圾目标有无偏移、缩放、旋转错误3.3 COCO转YOLO的可靠脚本避开OpenCV依赖的纯Python方案import json import os from pathlib import Path def coco_to_yolo(coco_json_path, image_dir, label_dir): with open(coco_json_path, r) as f: coco json.load(f) # 构建image_id到文件名的映射 id_to_fname {img[id]: img[file_name] for img in coco[images]} # 构建category_id到YOLO class_id的映射按categories顺序 categories sorted(coco[categories], keylambda x: x[id]) cat_id_to_yolo_id {cat[id]: i for i, cat in enumerate(categories)} # 处理每个标注 for ann in coco[annotations]: img_id ann[image_id] fname id_to_fname[img_id] img_path Path(image_dir) / fname if not img_path.exists(): print(fWarning: image {fname} not found) continue # 读取图像尺寸 from PIL import Image with Image.open(img_path) as im: w, h im.size # 转换bboxCOCO是[x,y,width,height]YOLO要归一化中心点宽高 x, y, bw, bh ann[bbox] x_c (x bw/2) / w y_c (y bh/2) / h w_n bw / w h_n bh / h # 写入YOLO TXT txt_name Path(fname).stem .txt txt_path Path(label_dir) / txt_name yolo_id cat_id_to_yolo_id[ann[category_id]] with open(txt_path, a) as f: f.write(f{yolo_id} {x_c:.6f} {y_c:.6f} {w_n:.6f} {h_n:.6f}\n) # 调用示例假设COCO JSON在根目录 coco_to_yolo(annotations/instances_train2017.json, images/train, labels/train)逻辑说明关键是from PIL import Image动态读取每张图的size而非假设统一尺寸cat_id_to_yolo_id确保类别ID严格按categories数组索引排序避免因COCO category_id跳跃如1,3,5导致YOLO class_id错位使用a模式追加写入允许多个annotation写入同一TXTCOCO支持一张图多个bbox.6f保证浮点精度防止因四舍五入导致归一化值超限。4. 类别一致性排查classes.txt、dataset_info.json、模型输出层三者必须咬合这是最容易被忽略却最致命的一环训练时loss下降飞快但验证时mAP0大概率是类别ID链条断了。我们用三个命令层层穿透验证。4.1 检查classes.txt行末空行和BOM头是隐形杀手# 查看真实行数排除空行 wc -l classes.txt # 查看是否含BOMUTF-8 BOM是EF BB BF hexdump -C classes.txt | head -n 1 # 查看每行结尾是否有\r\n或多余空格 sed -n s/[^[:print:]]//gp classes.txt | cat -A现象→原因→解决wc -l显示12行但cat classes.txt只看到11行 → 最后一行是空行 → YOLO读取时会多出一个空类别导致len(names)12但实际只有11类hexdump显示ef bb bf→ UTF-8 BOM头 → Windows记事本保存的文件 → Python读取时首行变成\ufeff可回收物class_id0匹配失败cat -A显示行尾有$但某行多出^M→ DOS换行符\r\n→ Linux下部分解析器截断解决sed -i s/\r$// classes.txt sed -i /^$/d classes.txt sed -i 1s/^\xEF\xBB\xBF// classes.txt4.2 对齐dataset_info.json中的categories字段# 读取classes.txt去空行、去BOM with open(classes.txt, r, encodingutf-8) as f: classes [line.strip() for line in f if line.strip()] print(classes.txt:, classes) # 读取dataset_info.json with open(dataset_info.json, r, encodingutf-8) as f: info json.load(f) print(dataset_info.json categories:, info[categories]) # 比较 if classes info[categories]: print(✅ 类别列表完全一致) else: print(❌ 不一致差异, set(classes) ^ set(info[categories]))注意顺序必须完全相同[纸类,塑料]≠[塑料,纸类]因为YOLO class_id由索引决定。4.3 验证模型输出层用torchsummary看最后一层维度from torchsummary import summary from models.yolo import YOLOv8Detector # 替换为你实际用的模型 model YOLOv8Detector(nclen(classes)) # ncnumber of classes summary(model, input_size(3, 640, 640))在输出中找到类似行Conv2d-123 [-1, 84, 20, 20] 1,234,567其中84 4 nc4是xywhnc是类别数若nc11则此处应为15若为16说明模型加载了错误的类别数。血泪经验曾遇到classes.txt有11类但训练脚本里硬编码nc80COCO默认导致模型输出84维而损失函数只取前15维计算其余69维梯度为0——loss降得飞快但实际只在学8个类别。5. 避坑指南这5个坑让我重训了7次才跑通baseline数据集交付包看似简单实则暗藏大量“约定俗成但未明说”的陷阱。以下是我踩过、记录过、验证过的5个高频问题按发生概率排序5.1 图像路径大小写敏感Linux下Images/≠images/现象训练时报错FileNotFoundError: images/train/xxx.jpg但ls images/train/明明存在原因ZIP包在Windows打包时保留了Images/目录名解压到Linux后变成Images/而代码里写死images/解决mv Images/ images/ mv Labels/ labels/或统一用小写重命名所有目录推荐用rename y/A-Z/a-z/ *5.2classes.txt编码为GBK而非UTF-8现象Python读取时报UnicodeDecodeError: utf-8 codec cant decode byte 0xc4原因中文Windows默认用GBK保存文本open(..., encodingutf-8)失败解决iconv -f gbk -t utf-8 classes.txt -o classes_utf8.txt mv classes_utf8.txt classes.txt5.3dataset_info.json里的total_images是假数据现象train/目录有5000张图但dataset_info.json写total_images: 4800原因生成JSON时统计脚本漏掉了某些子目录或手动修改后忘记更新解决以实际目录为准重算并覆盖echo {\total_images\: $(find images/train -name \*.jpg\ | wc -l)} dataset_info.json5.4 YOLO TXT文件名与图像名不一一对应现象labels/train/IMG_001.txt存在但images/train/IMG_001.jpg不存在反之亦然原因标注人员删除了部分低质量图像但忘了同步删TXT或批量重命名时只处理了图片解决用脚本双向校验并清理# 删除无图对应的TXT for txt in labels/train/*.txt; do base$(basename $txt .txt) if [ ! -f images/train/${base}.jpg ] [ ! -f images/train/${base}.png ]; then rm $txt echo Removed orphan $txt fi done5.5test/目录缺失但dataset_info.json声明了test split现象调用split_dataset.py时崩溃提示test目录不存在原因数据集发布者只提供了train/valdataset_info.json却写了test:0.1解决要么从val中划出test修改split_ratio要么将test设为0test:0.0绝不能留空目录——YOLO的data.yaml会因test: null报错。6. 进阶技巧用dataset_info.json驱动自动化训练流水线真正把数据集用深的人不会手动改data.yaml或train.py参数。他们会把dataset_info.json变成整个训练流程的“中央配置枢纽”。我现在的做法是所有超参、路径、类别数都从这个JSON里动态注入。6.1 自动生成data.yaml告别手写错误import yaml def generate_data_yaml(json_path, output_pathdata.yaml): with open(json_path, r, encodingutf-8) as f: info json.load(f) data { train: str(Path(images) / train), val: str(Path(images) / val), test: str(Path(images) / test) if info.get(split_ratio, {}).get(test, 0) 0 else None, nc: len(info[categories]), names: info[categories] } # 移除None值test为空时不写入 data {k: v for k, v in data.items() if v is not None} with open(output_path, w, encodingutf-8) as f: yaml.dump(data, f, default_flow_styleFalse, allow_unicodeTrue, sort_keysFalse) print(f✅ Generated {output_path}) generate_data_yaml(dataset_info.json)生成的data.yaml示例train: images/train val: images/val nc: 11 names: [塑料瓶, 易拉罐, 废纸, 电池, 灯管, 过期药品, 果皮, 菜叶, 烟蒂, 口香糖, 陶瓷碎片]6.2 动态设置训练命令用argparse读取JSON# train.py开头 import argparse import json parser argparse.ArgumentParser() parser.add_argument(--data, typestr, defaultdataset_info.json, helppath to dataset_info.json) args parser.parse_args() with open(args.data, r, encodingutf-8) as f: info json.load(f) # 自动推导batch_size按GPU显存和图像数比例 total_imgs info[total_images] batch_size min(64, max(8, total_imgs // 100)) # 100图/卡 ≈ 1 batch print(fAuto-set batch_size{batch_size} for {total_imgs} images) # 后续传给trainer...6.3 数据集健康度仪表盘3行命令出报告# 1. 统计各类别样本数YOLO格式 find labels/train -name *.txt | xargs -I{} sh -c cat {} | cut -d -f1 | sort | uniq -c | sort -nr class_dist.txt # 2. 检查图像分辨率分布 find images/train -name *.jpg | head -n 100 | xargs -I{} identify -format %wx%h\n {} | sort | uniq -c | sort -nr # 3. 输出综合报告 echo Dataset Health Report echo Total images: $(find images/train -name \*.jpg\ | wc -l) echo Classes distribution: head -n 10 class_dist.txt echo Top 3 resolutions: head -n 3 (find images/train -name *.jpg | head -n 100 | xargs -I{} identify -format %wx%h\n {} | sort | uniq -c | sort -nr)我的习惯每次新数据集入库必跑这三行。如果发现某类别样本50张立刻标记为“需增强”如果分辨率集中在1920x1080但部署端是320x240摄像头就提前做resize预处理。这些动作不写进论文但决定了模型能不能真正在环卫车上跑起来。希望帮到你。本文还有配套的精品资源点击获取