简介:面向目标检测实战与智慧环卫应用的YOLOV5垃圾桶满溢检测数据集包,适用于需要快速搭建垃圾分类识别模型并部署上线的开发者、高校学生以及算法工程师。资源共包含2000个文件,压缩包整体大小约450MB,以1921个txt格式的标注文件构成基础标签库,40个py脚本负责模型训练、验证与推理,23个yaml文件提供网络结构与超参数配置,同时附带sh脚本、md说明文档和json配置文件,目录组织清晰,便于按模块调用。数据集训练集包含2680张标注图像,验证集669张,项目已迭代训练100个epoch,最优map0.5达到0.91,map0.5:0.95为0.73,同时保存有验证集混淆矩阵、PR曲线、F1曲线等训练过程可视化结果;runs/detect目录还保留了对训练集图片的完整推理结果,可直接观察检测框与置信度表现。目前已有363人学习,适合希望快速体验YOLOV5完整训练与推理流程,或实际落地垃圾桶满溢识别场景的研究与工程人员。
1. 垃圾桶满溢检测:一份能直接跑的YOLOV5数据集项目
凌晨的垃圾中转站,满溢的垃圾桶往往要等清运车到场才被发现。这类垃圾桶满溢检测需求,落到技术上就是让YOLOV5学会区分三个状态:满溢的垃圾桶、未满溢的垃圾桶、散落的垃圾。这套实战项目把标注好的数据集、完整训练代码、训练好的权重一次打包,训练集2680张图、验证集669张图,迭代100个epoch后mAP0.5跑到0.91、mAP0.5:0.95跑到0.73,runs目录里连混淆矩阵、PR曲线、F1曲线和全部推理结果都保留着。对想快速上手YOLOV5目标检测的从业者来说,它最大的价值是省掉标注和调参的时间,直接拿现成权重改场景;新手想学完整训练流程,这套产物也是很好的对照样本。
2. 数据集的三个类别与标签格式:训练前先做一次标签体检
拿到资源第一步不是急着训练,而是把数据集结构摸清楚。YOLOV5对数据的组织方式有固定要求,目录对不上、标签格式不规范,训练时轻则警告重则报错。这套项目的目录结构是标准YOLO布局,但我建议动手前先用自己的脚本做一次体检,确认图片和标签一一对应、类别索引没写错、坐标没有越界。这一步能避开后面大量玄学问题。
2.1 目录结构与类别定义
解压后核心数据在datasets目录下,images和labels分开存放,train和val各自配对。图片统一是jpg,标签是同名txt文件。我一般会先跑一遍统计命令确认数量:
# 统计训练集图片和标签数量 find datasets/images/train -name "*.jpg" | wc -l find datasets/labels/train -name "*.txt" | wc -l # 统计验证集图片和标签数量 find datasets/images/val -name "*.jpg" | wc -l find datasets/labels/val -name "*.txt" | wc -l逻辑说明:find命令按文件名后缀枚举文件,wc -l统计行数。每行代表一个文件路径,行数就是文件个数。图片和标签数量应当完全一致,如果差几个,说明存在漏标或多余文件。
参数说明:这里假设图片扩展名都是jpg,如果数据里有png记得加一行find ... -name "*.png"补上,两行结果相加才是总数。训练集2680张、验证集669张,和项目描述对得上。这套数据不只能喂给YOLOv5,目录结构整理一下同样能用于YOLOv8训练,标签txt格式是通用的。
类别定义方面,项目里共3类,我习惯用小写英文做类别名,配置时按索引对齐。分类顺序是:0对应满溢的垃圾桶,1对应未满溢的垃圾桶,2对应垃圾。这个顺序在你改data.yaml时不能乱,训练和推理用的是同一套索引。
2.2 标签txt逐行拆解与归一化坐标
YOLO格式的标签每一行代表一个目标框,格式是class x_center y_center width height,五个值用空格分隔。四个坐标全部是归一化到0到1之间的小数,不是像素值。这点新手最容易理解错,以为坐标就是像素坐标,结果训练出来检测框全乱。
import os from collections import Counter label_dir = "datasets/labels/train" stats = Counter() empty_files = 0 sample_lines = [] for fname in os.listdir(label_dir): if not fname.endswith(".txt"): continue path = os.path.join(label_dir, fname) with open(path) as f: lines = [line.strip() for line in f if line.strip()] if not lines: empty_files += 1 continue for line in lines: parts = line.split() stats[parts[0]] += 1 if len(sample_lines) < 5: sample_lines.append((fname, parts)) print("空标签文件数:", empty_files) print("类别分布:", dict(stats)) print("样例:") for fname, parts in sample_lines: print(" ", fname, parts)逻辑说明:遍历所有txt标签,按行切分后第一个字段是类别id,统计每个id出现的次数。如果空标签文件数不为0,说明有图片没有任何目标,YOLOV5训练时对这张图会跳过loss计算,数量太多会拉低召回。
参数说明:parts列表长度固定为5,如果某行长度不是5,说明标注工具导出的格式有问题。四个坐标值的范围应当都在0到1之间,超出这个范围说明归一化没做好,训练时会出现loss异常或边框偏移。W的值越界往往是把x_center和width填反了。
2.3 用可视化确认标注框质量
数值体检只能发现格式问题,框到底画得准不准得看图。我一般会在训练前随机抽三到五张图,把标注框画出来人工确认一眼,这一步花十分钟,能避免训练完才发现标注本身是错的。
import random import cv2 image_dir = "datasets/images/train" label_dir = "datasets/labels/train" files = os.listdir(image_dir) for fname in random.sample(files, 3): img = cv2.imread(os.path.join(image_dir, fname)) h, w = img.shape[:2] txt_path = os.path.join(label_dir, fname.replace(".jpg", ".txt")) with open(txt_path) as f: for line in f: cid, cx, cy, bw, bh = map(float, line.split()) x1 = int((cx - bw / 2) * w) y1 = int((cy - bh / 2) * h) x2 = int((cx + bw / 2) * w) y2 = int((cy + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, str(int(cid)), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 1) cv2.imwrite(f"check_{fname}", img)逻辑说明:读取图片后拿到实际像素尺寸,把归一化坐标还原成像素坐标,用cv2画框和类别id。这样做一次能看到标注框与真实物体轮廓的重合程度。
参数说明:class id这里直接取整数画在框上方。如果发现满溢垃圾桶的框把旁边的建筑也框进去了,说明标注偏大;如果只框住桶盖,说明偏小。这类问题趁没训练前修掉成本最低。
3. 训练配置与100个epoch:超参数怎么设才不翻车
数据集没问题之后,接下来就是环境配置和训练参数。YOLOV5这个版本是2020年开源的经典分支,社区资料最多,遇到问题搜一下基本都能找到答案。环境配置别用最新版Python,常见做法是装Python 3.9,坑最少。这章把从零到跑通训练的命令和参数讲清楚。
3.1 环境准备与依赖安装
YOLOV5官方仓库依赖PyTorch和一堆图像处理库,老手一般用conda建独立环境,避免和别的项目互相污染依赖版本。我这边按常见做法给一套能稳定跑通的环境组合:
conda create -n yolo python=3.9 -y conda activate yolo cd yolov5 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple逻辑说明:conda创建独立Python环境,requirements.txt里锁定了torch、opencv-python、numpy、pandas等核心依赖版本。加清华镜像源是为了在国内网络环境下下载快一点,如果已经全局配置过镜像可以不加。
参数说明:Python版本选3.9而不是3.11,是因为YOLOV5官方测试环境主要针对3.8到3.10,3.11上偶尔会遇到依赖编译失败。如果机器有NVIDIA显卡,建议先确认nvidia-smi驱动版本再装对应CUDA版PyTorch,纯CPU机器也能训练,只是速度会慢十倍以上。
3.2 data.yaml的核心字段与常见填错
YOLOV5训练不读json,所有数据集信息都写在data.yaml里。项目里的数据配置文件要自己建一个,指向刚才确认过的目录。这一步是最容易出错的地方,路径写法、类别数量、类别名字顺序,任何一个和实际不一致,训练过程都会出问题。
# data.yaml 训练配置文件 train: datasets/images/train val: datasets/images/val nc: 3 names: 0: overflowing 1: normal 2: garbage逻辑说明:train和val字段指向的是图片目录,YOLOV5会自动把路径中的images替换成labels去找同名txt,所以标签目录不需要写在这里。nc是类别总数3,names按索引顺序定义类名。
参数说明:train路径支持相对路径和绝对路径,相对路径是相对于你执行train.py的位置。如果写成datasets/images/train/带末尾斜杠也可以,但不要写成datasets/labels/train,否则YOLOV5会去labels里找labels,直接报找不到。项目自带的README里有对每个文件的说明,训练前翻一遍能省不少排查时间。
3.3 训练命令、断点续训与显存控制
环境配好、yaml写好,就可以启动训练。项目迭代了100个epoch且mAP0.5到0.91,说明这套超参数对这个数据集是有效的。我按这个配置给你可复现的训练命令:
python train.py \ --data data.yaml \ --weights yolov5s.pt \ --epochs 100 \ --batch-size 16 \ --imgsz 640 \ --workers 4 \ --cache \ --name trash_run逻辑说明:train.py读取data.yaml中的数据集配置,加载yolov5s.pt预训练权重做迁移学习,按设定epoch数迭代训练,每轮结束后在验证集上算mAP并保存权重。--cache参数把图片缓存到内存,减少磁盘IO等待,能明显提速。
参数说明:--weights选择模型大小,yolov5s是small版本,速度和精度平衡,适合边缘部署;显存充足可以换yolov5l,精度会略高但训练时间翻倍。--batch-size 16在8G显存上比较稳,显存小就降到8,大显存可以开到32。--name指定本次训练的文件夹名,runs/train/trash_run里会存放权重和曲线图。如果中途断了想继续,加--resume runs/train/trash_run/weights/last.pt即可,不用重新从头跑。
训练过程中如果看到loss曲线震荡不下降,常见做法是调低学习率。默认lr0是0.01,我一般遇到震荡先改成0.001试跑30个epoch观察,稳定后再加大。
4. 训练产物与指标解读:mAP0.5=0.91背后的四个文件
训练跑完,runs/train/trash_run目录下会生成一堆文件。很多人只知道best.pt能用来推理,其实混淆矩阵、PR曲线、results.csv这几个文件才是判断模型好坏的关键依据。项目里保存了全部100个epoch的结果,进阶玩家可以直接通过这些文件复盘整个训练过程。
4.1 runs目录里到底存了些什么
训练结束后最重要的产物是weights下的两个权重文件:best.pt是验证集上mAP最高的那一轮权重,last.pt是最后一轮权重。两者用途不同,推理用best.pt,想继续训练用last.pt。
| 文件/目录 | 内容 | 什么时候看它 | | weights/best.pt | 验证集最优权重 | 推理、导出、部署 | | weights/last.pt | 最后一次epoch权重 | 断点续训 | | results.csv | 每个epoch的loss和mAP指标 | 判断收敛情况 | | confusion_matrix.png | 验证集混淆矩阵 | 看哪两类容易混 | | PR_curve.png | 各类别PR曲线 | 选置信度阈值 | | F1_curve.png | F1分数与阈值关系 | 选置信度阈值 | | detect/ | 推理结果图 | 直观确认效果 |
这个项目的runs/detect目录下保存了全部验证图片的推理结果,框画得很干净,直接翻一遍就能对模型能力有个整体印象,比自己跑一次推理还省事。
4.2 results.csv怎么看收敛
results.csv记录了每个epoch的box loss、obj loss、cls loss以及精度指标,是判断训练是否收敛最直接的数值来源。我习惯用Python读最后几行看看尾部指标:
import csv with open("runs/train/trash_run/results.csv") as f: rows = list(csv.reader(f)) header = rows[0] for row in rows[-3:]: record = dict(zip(header, row)) print(f"epoch {record['epoch']}: " f"mAP@0.5={record['mAP@0.5']}, " f"mAP@0.5:0.95={record['mAP@0.5:0.95']}, " f"box_loss={record['box_loss']}")逻辑说明:results.csv第一行是表头,每一行对应一个epoch的指标。用字典把表头和数值对齐,取最后三行看尾部值。如果尾部mAP还在上升,说明100个epoch不够,可以追加训练。
参数说明:这里的mAP@0.5表示IoU阈值为0.5时的平均精度,mAP@0.5:0.95是0.5到0.95每间隔0.05算一个IoU阈值再取平均。项目结果mAP0.5=0.91说明检测框位置够准,mAP0.5:0.95=0.73说明高IoU要求下也有不错的定位精度,日常监控场景足够用。
4.3 混淆矩阵与PR曲线的读法
confusion_matrix.png是一张N+1行N+1列的图,行是真实类别,列是预测类别,对角线上的值越高越好。对垃圾检测这类场景,最需要注意的就是满溢垃圾桶和未满溢垃圾桶是否互相混淆,因为这两类外形相似,只有桶内垃圾高度有区别。如果混淆矩阵里这两类交叉值超过0.2,就得考虑加训练数据或者调整损失权重。
PR_curve.png横轴是召回率、纵轴是精确率,曲线越靠近右上角越好。箱线图边上会标出每个类别的AP值。这张图还帮你决定推理时的置信度阈值——曲线拐点对应的conf值就是甜点区,太低会引入大量误检,太高会漏掉真正的满溢垃圾桶。F1_curve.png直接画出F1随阈值变化的曲线,最高点对应的阈值就是这个模型在当前数据集上最优的置信度设定。
5. 排查与避坑:目标检测训练最常见的五个翻车点
YOLOV5虽然成熟,但训练过程中的坑一点不少。这一章把这套项目实际训练中可能遇到的五个典型问题列出来,每条按现象、原因、解决三步拆开。全是血泪经验,照着排查能省下大半天时间。
5.1 loss变成nan
现象:训练跑到几十个epoch时终端打印的loss突然变成nan,精度指标也跟着消失,之后所有数值都是nan。
原因:最常见是学习率过大导致梯度爆炸,其次是因为标签坐标出现越界值,归一化坐标大于1或小于0,计算损失时梯度异常。还有一种情况是数据里有损坏的图片文件,解码出来的数组是空的。
解决:先把学习率从默认0.01降到0.001,重启训练观察前20个epoch的loss曲线。如果还出现nan,回头跑前面那段标签检查脚本,把所有txt里超过范围的值打印出来人工修正。最后用file命令扫一遍图片目录,把损坏的图片移出去。
5.2 百度网盘解压后代码识别txt文件失败
现象:从网盘下载压缩包解压后,训练时报错提示找不到标签文件,或者标签文件被识别为空。
原因:部分网盘工具在Windows上会把txt文件名做处理,或者解压时把扩展名改了。YOLOV5通过图片同名匹配txt,文件名对不上就直接跳过。
解决:把图片名和文件名做一次交集比对,找到缺失的对应用脚本批量改回一致。更省事的办法是重新解压到纯英文路径,避免中文路径和编码干扰。
5.3 mAP高但推理时漏检
现象:验证集mAP0.5有0.9以上,但用detect.py推理视频或摄像头画面时,某些明显满溢的垃圾桶没被框出来。
原因:验证集评估时用的是多尺度测试和集成,推理时默认单尺度且置信度阈值偏高。另外训练图片里的垃圾桶都是近距离大目标,实际场景摄像头离得远,目标变小后小目标检出率下降。
解决:推理时把--conf降到0.15试一遍,漏检会明显减少,代价是误检变多。把--imgsz从640提到1280也能提升小目标检出,但推理速度会下降。根本办法是收集更多远距离样本补充训练。
5.4 类别数量对不上
现象:训练正常结束,但推理时只识别出两类,第三类完全不出现。
原因:data.yaml里nc写的值和标签里实际出现的类别id不匹配。最常见是把nc写成了2,或者names里类别名字顺序和标注文件里的id对应错位,比如把garbage写到了索引1的位置。
解决:重新跑类别分布统计脚本,看txt里实际出现几个类别id,把data.yaml的nc改成实际数量,再核对names顺序。这里没有一个参数能自动修复,必须人工对齐。
5.5 显存溢出
现象:训练刚开始就报CUDA out of memory,进程直接退出。
原因:batch-size设得太大,输入分辨率640加上默认开启的多次缩放和增强,一次性占满显存。8G显存开batch-size 16比较临界,如果图片尺寸大就会爆。
解决:batch-size降到8,workers降到4,关闭--cache让图片按需读取。如果还要跑大模型,可以加--rect参数按长宽比分组训练,降低显存峰值。我一般先以8跑通,确认资源够用再往上调。
6. 推理与模型导出:把best.pt用到实际场景的验证方法
训练完的best.pt不能只在训练集上自嗨,最终要落到实际场景跑推理。第一步用detect.py在验证集上再跑一遍,和runs/detect里保存的结果对比;第二步导出ONNX,为边缘部署做准备。
python detect.py \ --weights runs/train/trash_run/weights/best.pt \ --source datasets/images/val \ --conf 0.25 \ --iou 0.45逻辑说明:detect.py加载best.pt,对source指定的图片或视频逐帧推理,画框后保存到runs/detect目录。--conf是置信度阈值、--iou是NMS的IoU阈值,这两个参数就是YOLOV5后处理阶段的核心控制点。
参数说明:--source支持图片目录、视频文件、摄像头编号,输出默认存到runs/detect/exp。如果发现满溢垃圾桶没被检出,把conf降到0.15看效果;如果发现同一目标出现两个框,提高iou到0.5压制重复框。
确认PyTorch推理没问题后,下一步是导出ONNX。用Python做服务端推理时ONNX比PyTorch原生模型更通用,换成树莓派5这类ARM设备也能跑:
python export.py \ --weights runs/train/trash_run/weights/best.pt \ --include onnx \ --imgsz 640 \ --batch-size 1逻辑说明:export.py把best.pt转成ONNX格式,ONNX本身不支持NMS后处理,导出时默认会把后处理以额外输出节点保留下来,部署时用onnxruntime配合nms即可。
参数说明:--batch-size 1固定单batch,动态batch导出会在部分部署框架上报错,固定1最稳。--imgsz要和推理时一致,否则输出尺寸对不上。部署到树莓派5这类设备时,ONNX需要配合onnxruntime或rknn-toolkit使用,直接跑PyTorch模型很吃力,内存和CPU都扛不住。
从那以后我每次拿到新数据集都强制走一遍标签体检流程:先统计空标签和类别分布,再检查坐标范围,最后随机抽三张图把框画出来确认,然后才启动训练。这个流程救过我太多次了,希望帮到你。
本文还有配套的精品资源,点击获取