☰
垃圾目标检测数据集实战:YOLOv8训练、避坑与ONNX部署全流程
2026/10/11 9:44:45 网站建设 项目流程

简介:这是一份面向计算机视觉开发者、环保科技团队及高校师生的垃圾目标检测数据集,聚焦单类别Trash识别,可服务于智能垃圾分类、清洁机器人视觉、违规倾倒监测及目标检测教学等场景。资源包共492个文件,以245张jpg真实场景图片与245个同名txt标注文件为主,另含1个yaml数据配置和1份docx说明文档,压缩包约33.05MB,训练集231张、验证集14张,均采用标准化YOLO边界框格式,可直接接入YOLO系列、Faster R-CNN等主流框架。图片采集自实际环境,覆盖多样光照、角度与背景,标注经过校验,有助于提升模型泛化能力。目前已有198人学习下载,适合需要快速验证算法或搭建环保识别原型的读者参考使用。

1. 垃圾目标检测数据集:从“能跑”到“能落地”的第一道坎

如果你做过环卫巡检机器人、智能垃圾分类箱或者城市固废监管平台,大概率会遇到同一个尴尬:模型在 COCO 上 mAP 挺好看,一换到真实垃圾场景就崩。原因不复杂——通用数据集里“垃圾”这个类别的样本又少又杂,塑料袋、纸盒、饮料瓶、烟头、建筑渣土混在一起,类间差异大、类内差异更大,而且遮挡、堆叠、光照变化几乎是常态。这份垃圾目标检测数据集就是冲着这个缺口来的:它把生活垃圾、可回收物、有害垃圾等常见目标做了标注,格式对齐 YOLO 训练习惯,能直接喂给 YOLOv5/v8 这类框架。适合谁?做环保类视觉项目的算法工程师、带学生做课设的高校老师,以及想拿行业数据集练手目标检测的入门者。它解决的不是“有没有数据”,而是“数据能不能直接用、标注能不能信、类别能不能对上你的业务”。

2. 数据集结构与 YOLO 格式对齐:先看清标签再谈训练

2.1 目录组织与标注格式

拿到一个目标检测数据集,我第一件事不是写训练脚本,而是把目录结构和标签文件翻一遍。行业数据集最常见的坑就是“图片和标签对不上号”,训练时 loss 不降,排查半天发现是文件名后缀不一致。这份数据集按 YOLO 惯例组织,典型结构如下:

dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml

YOLO 格式的标签是每张图对应一个.txt,每行一个目标,格式为class_id x_center y_center width height,坐标全部归一化到 0~1。这里有个容易被忽略的点:归一化用的是图片原始宽高,不是网络输入尺寸。如果你在预处理阶段先 resize 再算坐标,标签就全错了。常见做法是保持原图不动,让 YOLO 的 dataloader 自己处理 letterbox 缩放。

data.yaml是训练入口,内容大致长这样:

path: ./dataset train: images/train val: images/val nc: 6 names: ['plastic', 'paper', 'glass', 'metal', 'organic', 'hazardous']

nc是类别数,names的顺序必须和标签里的class_id严格对应。我见过有人改了names顺序却没改标签,结果模型把塑料瓶识别成有害垃圾,这种错误在验证集上表现为“类别混淆严重但 mAP 还行”,特别隐蔽。

2.2 类别分布与长尾问题

行业数据集绕不开长尾分布。垃圾场景里,塑料瓶、纸盒这类样本多,有害垃圾(电池、灯管)样本少,直接训练会导致模型对少数类几乎不响应。先统计一下每类实例数:

import os from collections import Counter label_dir = 'dataset/labels/train' counter = Counter() for f in os.listdir(label_dir): if f.endswith('.txt'): with open(os.path.join(label_dir, f)) as fp: for line in fp: cls = int(line.split()[0]) counter[cls] += 1 for cls_id, cnt in sorted(counter.items()): print(f'class {cls_id}: {cnt} instances')

跑完你会看到类似class 0: 3200、class 5: 180的分布。差距超过 10 倍就要考虑处理策略:过采样少数类、在 loss 里加类别权重,或者用 copy-paste 增强合成少数类样本。我一般先用cls_pw参数给 YOLOv8 加类别权重,改动最小,效果也够用。

提示:统计实例数时注意区分“图片数”和“实例数”,一张图可能有多个目标,按图片数统计会低估长尾程度。

2.3 标签可视化验证

训练前必须做一次可视化抽检,确认标注框位置正确、类别无误。用 OpenCV 画框最直接:

import cv2 import os img_path = 'dataset/images/train/0001.jpg' label_path = 'dataset/labels/train/0001.txt' img = cv2.imread(img_path) h, w = img.shape[:2] with open(label_path) as f: for line in f: 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.putText(img, str(int(cls)), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imwrite('check.jpg', img)

这段代码把归一化坐标还原成像素坐标再画框。重点看三件事:框是否贴合目标、类别 ID 是否和data.yaml对得上、有没有漏标的目标。漏标比错标更麻烦,因为模型会把漏标区域当背景学,导致召回率上不去。抽检比例建议不低于 5%,如果发现系统性偏移(比如框整体偏左上),大概率是标注工具导出时坐标系搞反了。

3. 用 YOLOv8 跑通训练:参数怎么设、日志怎么看

3.1 环境准备与数据配置

YOLOv8 通过 ultralytics 包安装,一条命令搞定:

pip install ultralytics

训练前把data.yaml里的路径改成绝对路径或相对于训练脚本的路径,避免“找不到图片”的报错。我习惯在项目根目录建一个configs/放 yaml,训练脚本里用--data configs/garbage.yaml指定。如果你的数据集类别名和业务系统不一致,改names就行,但记住标签里的class_id是数字,改名字不影响训练,只影响推理时的输出标签。

3.2 训练命令与关键参数

一条典型的训练命令:

yolo detect train \ data=configs/garbage.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=20 \ project=runs/garbage \ name=exp1

逐个说参数:model=yolov8n.pt是 nano 版预训练权重,垃圾检测这种类别不多、场景相对固定的任务,n 或 s 版通常够用,上大模型容易过拟合。imgsz=640是输入分辨率,如果你的图片里小目标多(比如烟头、瓶盖),可以提到 960,但显存占用会翻倍。lr0=0.01是初始学习率,YOLOv8 默认用 SGD 时这个值比较稳,用 AdamW 的话降到 0.001。patience=20是早停耐心值,验证集 mAP 连续 20 轮不涨就停,省时间。

注意:batch要根据显存调,8G 显存跑 640 分辨率,n 版模型 batch=16 基本是上限,报 OOM 就往下调,别硬撑。

3.3 训练日志解读与中断恢复

训练开始后终端会打印每轮的 box_loss、cls_loss、mAP50、mAP50-95。重点盯两个信号:cls_loss 不降说明类别学习有问题,可能是标签类别错乱或长尾太严重;mAP50 涨到某个值后震荡不升,说明模型容量或数据量到瓶颈了。如果训练中途断了,用resume接着跑:

yolo detect train resume model=runs/garbage/exp1/weights/last.pt

last.pt是最后一轮权重,best.pt是验证集最优权重。推理和部署用best.pt,继续训练用last.pt。我踩过的坑是拿best.pt去 resume,结果优化器状态对不上,loss 直接起飞。记住这个区别能省你半天排查时间。

3.4 验证集评估与混淆矩阵

训练完跑一次验证:

yolo detect val model=runs/garbage/exp1/weights/best.pt data=configs/garbage.yaml

输出里除了 mAP,还会生成混淆矩阵图。垃圾检测最容易出的问题是“可回收物”和“其他垃圾”互相混淆,因为塑料袋、纸巾这类目标在不同标注标准下归类不一致。如果混淆矩阵显示某两类互相误判严重,先回去查标注规范,别急着调模型。数据问题模型救不了,这是血泪经验。

4. 避坑与排查:标注、路径、显存的三类翻车现场

4.1 图片与标签文件名不匹配

现象:训练启动后报No labels found或 loss 恒为 0。原因:图片是.jpg,标签是.JPG.txt,或者图片名带空格、中文,标签名做了清洗。解决:写个脚本统一文件名,图片和标签只保留主名一致,扩展名各自保留。批量重命名用 Python 的os.rename最稳,别手动改。

4.2 类别 ID 从 1 开始导致越界

现象:训练报IndexError: index out of range或类别全错。原因:有些标注工具默认类别从 1 开始编号,而 YOLO 要求从 0 开始。解决:全局扫描标签文件,把class_id减 1,同时确认data.yaml的names列表长度等于最大 ID 加 1。这个坑在跨工具导出的数据集里特别常见。

4.3 显存溢出与 batch 设置

现象:训练几轮后突然 OOM,或者一开始就报 CUDA out of memory。原因:图片分辨率不一致,dataloader 按最大尺寸分配显存;或者batch设太大。解决:先把imgsz固定,训练前用脚本统计图片尺寸分布,把超大的图筛出来单独处理;batch从 8 开始试,稳了再往上加。别迷信“batch 越大越好”,小数据集小 batch 反而泛化更好。

4.4 验证集 mAP 虚高

现象:验证集 mAP 0.9,一上真实场景就废。原因:训练集和验证集来自同一段视频的相邻帧,几乎一模一样,等于变相泄漏。解决:按视频或采集批次划分 train/val,别随机按帧分。如果数据集已经分好了,检查一下 val 里的图片是不是在 train 里出现过相似帧。这个坑最隐蔽,也最致命。

4.5 标签坐标超出 0~1 范围

现象:训练不报错但框位置诡异,或者某些目标永远学不会。原因:标注时框拖到了图片边界外,归一化后坐标小于 0 或大于 1。解决:训练前跑一遍校验脚本,把越界坐标裁剪到 [0,1],同时记录哪些文件被修正过,回头检查标注质量。

5. 从训练到部署:ONNX 导出与推理加速的实操细节

5.1 导出 ONNX 并验证一致性

训练完的.pt权重适合研究和验证,真正部署到边缘设备或服务端,通常要转 ONNX。导出命令:

yolo export model=runs/garbage/exp1/weights/best.pt format=onnx imgsz=640 opset=12

opset=12兼容性最好,别盲目追新版本。导出后必须做一致性验证:用同一张图分别跑 PyTorch 和 ONNX,比较输出框的坐标和置信度。差异超过 1e-3 就要查,常见原因是预处理(letterbox 的 padding 值)没对齐。我一般写个脚本把两边结果画在同一张图上,肉眼比对最直观。

5.2 推理脚本与后处理参数

ONNX 推理的核心是预处理和后处理要对齐训练配置。预处理做 letterbox 缩放,后处理做 NMS。关键参数是conf_thres和iou_thres:垃圾检测场景下,目标密集堆叠时iou_thres设 0.5 容易把相邻目标合并,可以降到 0.4;conf_thres从 0.25 起步,漏检多就降到 0.15,误检多就提到 0.4。这两个值没有万能解,拿验证集跑一轮 PR 曲线,按业务对漏检和误检的容忍度选。

5.3 边缘设备部署的量化取舍

如果部署到 Jetson 或瑞芯微这类边缘设备,ONNX 还可以进一步转 TensorRT 或 RKNN,做 FP16 甚至 INT8 量化。量化能提速 2~3 倍,但小目标召回率通常会掉几个点。我的习惯是:先跑 FP16,看精度损失是否可接受;如果必须上 INT8,一定用真实场景的校准集,别拿训练集凑合。校准集分布不对,量化后的模型在特定光照下会集体失效,这种问题在实验室里根本复现不出来。

5.4 一个验证部署效果的小技巧

部署上线前,我会做一件事:把验证集里模型表现最差的 20 张图挑出来,单独跑一遍部署管线,和 PyTorch 结果逐张对比。这 20 张图往往包含遮挡、逆光、密集堆叠等边界情况,能提前暴露 80% 的部署问题。从那以后我每次导出模型都强制走一遍这个“最差样本回归”,比看整体 mAP 有用得多。希望这套流程能帮你在垃圾检测项目上少走几个弯路。

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

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

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

立即咨询