简介:本资源是一份面向计算机视觉初学者与实战开发者的城市道路垃圾检测专用数据集,采用标准Pascal VOC格式,适用于YOLO系列模型训练及目标检测算法验证。数据集聚焦真实城市场景,涵盖道路、人行道及草丛等典型区域,共892张高质量JPG图像与严格对齐的XML标注文件,全部由labelImg工具人工标注,仅含单类别“trash”,总计1155个精确矩形框;其中81张为常见塑料瓶样本,增强模型对高频垃圾类型的识别鲁棒性。压缩包共1785个文件(892 jpg + 892 xml + 1 readme.txt),总大小983.57MB,结构简洁无冗余,开箱即用。目前已有1089人学习下载,读者可直接用于模型训练、mAP评估、数据增强实验或VOC转YOLO格式的流程实践,是开展环保AI项目、课程设计与竞赛基线实验的可靠基础数据支撑。
1. 项目背景与数据集价值解析
最近在做一个关于城市环境智能巡检的项目,核心需求是让模型能自动识别出散落在城市道路上的各类垃圾,比如塑料袋、饮料瓶、纸箱、烟头这些。找了一圈公开数据集,要么是场景太单一(比如只针对海滩或公园),要么是类别不符合国内城市道路的实际情况。最后,我决定自己动手,整理并标注了一个专门针对城市道路垃圾的数据集。这个数据集总共包含了892张高质量图片,并且已经转换成了标准的VOC格式,可以直接用于YOLO系列模型的训练。今天这篇文章,我就把这个数据集的制作过程、核心难点,以及如何用它高效训练一个YOLOv8模型的经验,毫无保留地分享出来。
为什么城市道路垃圾检测值得专门做一个数据集?这里面的门道其实不少。首先,城市道路场景复杂多变,光照条件从清晨到黄昏差异巨大,背景中混杂着车辆、行人、绿化带、交通标志等干扰物。其次,垃圾本身的形态极其不规则,一个被压扁的纸箱和一个鼓胀的塑料袋,在视觉特征上可能天差地别。再者,垃圾常常是“小目标”,一个远处的烟头在图像中可能只有十几个像素点,这对检测器的感受野和特征提取能力提出了很高要求。最后,数据分布的均衡性也很关键,你不能让模型只认识矿泉水瓶,却对快餐盒视而不见。因此,一个针对性强、标注质量高、类别平衡的数据集,是后续模型能否真正“落地”的关键基石。
这个892张的数据集,虽然规模不算海量,但贵在“精”和“准”。我们覆盖了城市主干道、辅路、人行道、十字路口等多种典型场景,时间上也涵盖了白天、傍晚、阴天等不同光照。标注的类别主要聚焦于几类最常见的道路垃圾:plastic_bag(塑料袋)、bottle(瓶子)、carton(纸箱)、cigarette_end(烟头)以及一个other(其他垃圾)作为兜底类别。所有标注均采用VOC格式,包含了每个目标的精确边界框(Bounding Box)和类别标签,为训练提供了坚实的基础。
2. VOC格式数据集详解与YOLO适配原理
拿到一个数据集,第一步永远是先理解它的格式。我们用的是PASCAL VOC格式,这是一种在目标检测领域历史悠久的经典格式。它的目录结构非常清晰,通常包含以下几个关键文件夹:
JPEGImages/: 存放所有的原始图片文件(.jpg)。Annotations/: 存放与图片一一对应的XML标注文件。每个XML文件详细描述了对应图片中所有目标的位置(<xmin>,<ymin>,<xmax>,<ymax>)和类别(<name>)。ImageSets/Main/: 这里通常有train.txt,val.txt,test.txt等文本文件,里面每一行就是一个图片的文件名(不含后缀),用来划分训练集、验证集和测试集。
VOC格式的XML标注文件是核心。它采用树状结构,根节点是<annotation>,下面包含了图片尺寸、目标列表等详细信息。这种格式的优点是人类可读性强,结构规范,很多早期的视觉库都原生支持。但是,YOLO系列模型(从v5到v8)通常要求的是另一种更简洁的格式:TXT格式。
YOLO所需的TXT格式,每个图片对应一个同名的TXT文件。文件里每一行代表一个目标,格式为:<class_id> <x_center> <y_center> <width> <height>。这里的坐标是归一化后的值,即目标中心点的x、y坐标以及宽度、高度,都除以了图片的宽度和高度,因此取值范围在0到1之间。class_id是类别的索引号,从0开始。
所以,训练前的关键一步就是格式转换。我们需要将VOC的XML格式(绝对像素坐标)转换为YOLO的TXT格式(归一化相对坐标)。这个转换过程并不复杂,但有几个坑点必须注意:
- 坐标归一化计算:
x_center = (xmin + xmax) / 2.0 / image_width;width = (xmax - xmin) / image_width。y轴同理。务必使用浮点数进行计算,确保精度。 - 类别ID映射:需要建立一个从VOC类别名(如
plastic_bag)到数字ID(如0)的映射字典。这个映射关系必须在整个数据预处理和模型训练过程中保持一致。 - 处理空标注:有些图片可能没有垃圾目标(这是好事,代表干净的街道)。对于这类图片,其对应的YOLO格式TXT文件应该是一个空文件(0字节)。很多转换脚本会忽略这一点,导致后续加载数据时报错。
- 验证转换结果:转换后,一定要随机抽样检查。可以写个简单的可视化脚本,把TXT文件中的归一化坐标还原到原图上画框,看看是否与原始VOC标注严丝合缝。我经常在这里发现因为图片读取方式(OpenCV的
cv2.imread返回的shape是(H, W, C))导致的宽高弄反的问题。
对于这个892张的数据集,我按照大约7:2:1的比例进行了划分,即训练集624张,验证集178张,测试集90张。划分时要注意分层采样,确保每个子集中各类别的比例与整体数据集大致相当,避免某个子集缺少某一类样本。
3. 基于YOLOv8的模型训练全流程实操
环境准备好了,数据也转换好了,接下来就是激动人心的训练环节。我选择的是Ultralytics的YOLOv8,因为它生态完善、文档清晰,而且性能确实强悍。下面我以YOLOv8为例,拆解整个训练流程。
3.1 环境配置与项目结构
首先,创建一个干净的项目目录。我的结构通常如下:
road_garbage_detection/ ├── data/ │ ├── images/ │ │ ├── train/ # 存放训练集图片 │ │ └── val/ # 存放验证集图片 │ └── labels/ │ ├── train/ # 存放训练集标签TXT文件 │ └── val/ # 存放验证集标签TXT文件 ├── dataset.yaml # 数据集配置文件 ├── train.py # 训练脚本 └── runs/ # 训练结果输出目录(由YOLO自动生成)关键就在于这个dataset.yaml文件,它是YOLO读取数据的入口。内容如下:
# dataset.yaml path: /path/to/your/road_garbage_detection/data # 数据集根目录 train: images/train # 训练集图片相对路径 val: images/val # 验证集图片相对路径 # 类别数量和名称 nc: 5 # number of classes names: ['plastic_bag', 'bottle', 'carton', 'cigarette_end', 'other']注意:
path最好使用绝对路径,避免相对路径引起的歧义。train和val的路径是相对于path的。
3.2 模型选择与超参数理解
YOLOv8提供了不同尺寸的预训练模型(n, s, m, l, x),在精度和速度上做了权衡。对于我们的垃圾检测任务,目标通常较小,需要模型有较强的特征提取能力。我一般从YOLOv8m(中等尺寸)开始尝试。它比s模型容量大,比l和x训练推理更快,是兼顾精度和效率的甜点。
启动训练的命令非常简单:
yolo task=detect mode=train model=yolov8m.pt data=dataset.yaml epochs=100 imgsz=640 batch=16 workers=4这条命令背后有几个关键超参数,直接影响训练结果:
epochs=100: 迭代轮数。对于892张图的小数据集,100轮通常足够,可以观察损失曲线是否已平稳。imgsz=640: 输入图片尺寸。YOLOv8训练时会自动将图片缩放到此尺寸。更大的尺寸(如1280)可能对小目标检测更友好,但会显著增加显存消耗和训练时间。640是一个通用的起点。batch=16: 批次大小。这取决于你的GPU显存。在显存允许的情况下,较大的batch size有助于训练稳定。如果出现CUDA out of memory错误,就需要降低batch或imgsz。workers=4: 数据加载的进程数。用于加速数据从磁盘到GPU的流水线。通常设置为CPU核心数左右。
3.3 训练过程监控与调优
训练开始后,不要干等着。Ultralytics提供了非常好的可视化工具——TensorBoard。在另一个终端启动:
tensorboard --logdir runs/detect/train然后浏览器打开localhost:6006。你需要重点关注这几个面板:
- 损失曲线(
train/box_loss,train/cls_loss等):观察训练损失是否平稳下降,验证损失是否同步下降且没有严重过拟合(即验证损失后期上升)。 - 性能指标(
metrics/mAP50-95,metrics/precision,metrics/recall):mAP50-95是核心指标,它计算了IoU阈值从0.5到0.95(步长0.05)的平均精度均值,非常综合。我们的目标就是让它稳步提升。 - 验证集预测样本(
Images或Validation标签页):这里会随机展示验证集图片的预测结果。直观地看模型在哪里漏检(False Negative)、在哪里误检(False Positive),是调优的最直接依据。
如果发现验证集精度上不去或过拟合,可以尝试以下策略:
- 数据增强(Augmentation):YOLOv8内置了强大的增强功能。可以在
dataset.yaml中配置或直接在训练命令中添加参数,如augment=True(默认已开启)。对于小数据集,增强是防止过拟合的利器。Mosaic、MixUp、随机仿射变换等都能显著提升模型鲁棒性。 - 调整学习率:使用
lr0参数。如果损失震荡,可以调低;如果下降太慢,可以适当调高。YOLOv8默认的调度器通常表现良好,初期不必大动。 - 早停(Early Stopping):设置
patience=20参数,如果验证集性能在连续20个epoch内没有提升,则自动停止训练,并保存最佳模型。
3.4 模型评估与测试
训练完成后,模型会保存在runs/detect/train/weights/best.pt。使用以下命令在测试集上评估其最终性能:
yolo task=detect mode=val model=runs/detect/train/weights/best.pt data=dataset.yaml评估报告会详细列出每个类别的精确率(Precision)、召回率(Recall)、mAP等。仔细分析这个报告:
- 哪个类别的
AP最低?可能是该类样本数量不足或特征难以学习。 - 召回率低?说明很多目标没被检测出来,可能需要增加正样本(通过数据增强),或者检查标注是否漏标。
- 精确率低?说明误检多,模型把很多背景当成了目标,可能需要增加困难负样本,或者调整分类损失的权重。
最后,用几张全新的、不在数据集中的城市道路图片进行测试,看看模型的真实泛化能力:
yolo task=detect mode=predict model=runs/detect/train/weights/best.pt source=path/to/your/test_image.jpg4. 小数据集训练的核心技巧与避坑指南
用不到一千张图片训练一个可用的检测模型,是有挑战的。下面分享我趟过的坑和总结出的有效技巧。
4.1 针对小目标的专项优化
城市道路垃圾很多都是小目标。YOLO的默认锚框(Anchor)是针对COCO等通用数据集设计的,可能不完全适合我们密集的小目标。YOLOv8是Anchor-Free的,但特征金字塔的设计依然关键。
- 使用更高分辨率训练:如果显存允许,尝试将
imgsz从640提升到1280。这能保留更多细节,对小目标检测有立竿见影的效果。可以先用640训练一个基础模型,再用1280进行微调(Fine-tune)。 - 修改模型结构(谨慎):YOLOv8的
model.yaml配置文件可以修改。例如,可以尝试在Neck部分增加更浅层特征的融合(如将P2层也纳入检测头),让模型“看”得更细。但这需要对网络结构有较深理解,且容易引入噪声。 - 聚焦小目标的数据增强:除了通用的增强,可以特意增加一些针对小目标的增强,比如随机复制粘贴小目标到图像的不同位置(但要注意合理性,垃圾不会在天上飞)。
4.2 数据增强的“艺术”
数据增强是扩展小数据集的法宝,但要用得巧。
- 几何变换:旋转、缩放、裁剪、剪切。对于道路垃圾,水平翻转是安全的,大角度的旋转可能不现实(垃圾通常躺在地上)。
- 色彩变换:亮度、对比度、饱和度、色调的随机调整。这能模拟不同天气和光照条件,非常有效。
- Mosaic和MixUp:YOLOv8默认开启。它们能将多张图拼成一张进行训练,极大地增加了背景的复杂性和目标的上下文多样性,对于防止过拟合、提升泛化能力效果显著。但对于极端小目标,Mosaic有时会将其缩得更小,需要观察效果。
- 一个关键经验:增强后一定要可视化!我写过一个小脚本,在增强流水线后随机采样图片并画出框,确保增强没有破坏标注的正确性(比如把目标裁没了,或者变换后框没跟上)。
4.3 迁移学习与微调策略
强烈建议使用预训练模型(yolov8m.pt)而不是从头训练。这些模型在百万级数据上学到的通用特征(边缘、纹理、形状)对我们任务有巨大帮助。这就是迁移学习。
- 冻结骨干网络(Backbone)微调:这是一种常用策略。先冻结特征提取网络的前面几十层,只训练检测头(Head)。训练几个epoch让检测头适应我们的新类别后,再解冻全部网络进行联合微调。这能加速训练并稳定初期收敛。在YOLOv8中,可以通过设置
freeze=10(冻结前10层)之类的参数实现,但更精细的控制可能需要修改代码。 - 我更常用的方法是:直接用预训练模型进行全参数训练,但使用更小的初始学习率。例如,将默认的
lr0从0.01降到0.001或0.0005。因为预训练权重已经很好,我们需要的是温和地调整它以适应新任务,太大的学习率会破坏已有的好特征。
4.4 类别不平衡问题处理
我们的数据集中,plastic_bag可能最多,cigarette_end可能最少。类别不平衡会导致模型偏向于多数类。
- 在损失函数层面:YOLOv8默认使用带标签平滑的交叉熵损失和CIoU损失。对于不平衡数据,可以尝试使用
Focal Loss,它通过降低易分类样本的权重,让模型更关注难分的、稀有的样本。YOLOv8可能需要修改源码来集成Focal Loss。 - 在数据采样层面:可以尝试“过采样”少数类。即,在加载数据时,让包含少数类的图片有更高的概率被抽到。这需要在构建数据加载器时下功夫。
- 一个更实用的简单方法:人工补充少数类样本。如果
cigarette_end很少,我就拿着手机去街上特意拍一些烟头的特写和不同场景,补充进数据集。虽然费事,但效果最直接。
4.5 训练中的常见“陷阱”与排查
- 损失为NaN或突然爆炸:这通常是学习率过高、数据有损坏(如图片无法解码)或标注坐标异常(如归一化后坐标大于1)导致的。检查数据清洗步骤,并大幅降低学习率。
- mAP始终为0或极低:首先检查
dataset.yaml中的nc(类别数)和names是否与你的标签文件匹配。其次,检查标签文件路径是否正确,验证集是否能正常加载。最笨但最有效的方法:用训练好的模型去预测训练集图片,如果连训练集都测不准,那肯定是数据或配置出了问题。 - 验证集损失远高于训练集损失:这是典型的过拟合。需要加强数据增强、减少模型复杂度(换用更小的模型如
yolov8s)、或者增加正则化(如权重衰减)。 - GPU显存不足(OOM):降低
batch_size,降低imgsz,使用梯度累积(gradient accumulation)来模拟大batch。在YOLOv8命令中,可以添加batch=-1来让库自动估算最大batch size。
5. 从训练到部署:模型优化与性能考量
训练出一个指标不错的模型只是第一步,要让它在实际场景中跑起来,还需要考虑优化和部署。
5.1 模型导出与格式转换
YOLOv8训练出的.pt文件是PyTorch格式,包含了模型架构和权重。为了在不同平台部署,我们需要导出。
- 导出为ONNX:ONNX是一种开放的模型交换格式,被众多推理引擎支持。
导出时注意yolo export model=runs/detect/train/weights/best.pt format=onnximgsz要和训练时一致或兼容。ONNX模型可以方便地用OpenCV DNN、TensorRT、ONNX Runtime等库进行推理。 - 导出为TensorRT:如果你在NVIDIA GPU上追求极致速度,可以导出为TensorRT引擎。这通常需要先导出ONNX,再用TensorRT的
trtexec工具或Python API进行转换和优化。这个过程涉及精度校准(FP16, INT8),能大幅提升推理速度,但有一定复杂度。 - 导出为OpenVINO IR:针对Intel CPU或神经计算棒的优化格式。
- 一个提醒:导出后,务必用导出的模型(如ONNX)和原始
.pt模型对同一批图片进行推理,对比结果是否一致,以确保导出过程没有出错。
5.2 模型剪枝与量化(可选)
如果部署在资源受限的边缘设备(如Jetson Nano、树莓派、手机)上,模型大小和速度至关重要。
- 剪枝(Pruning):移除网络中不重要的连接或通道,得到一个更稀疏、更小的模型。YOLOv8本身没有内置剪枝工具,需要借助第三方库(如Torch Pruning)进行,属于进阶操作。
- 量化(Quantization):将模型权重和激活从32位浮点数(FP32)转换为8位整数(INT8)。这能显著减少模型体积和加速推理,但可能会带来轻微的精度损失。TensorRT和OpenVINO都提供了方便的量化工具。对于我们的垃圾检测任务,在精度损失可控的情况下(例如mAP下降小于1%),INT8量化带来的速度提升是非常值得的。
5.3 构建实时推理Pipeline
一个完整的应用不仅仅是模型。你需要构建一个处理流水线:
- 图像输入:从摄像头(USB/IP)、视频文件或图片流读取帧。
- 预处理:将图像缩放到模型输入尺寸(如640x640),进行归一化(像素值/255.0),并转换为模型需要的张量格式(通常是CHW,即通道、高、宽)。
- 模型推理:调用导出的模型(如ONNX Runtime)进行前向传播,得到预测框。
- 后处理:
- 非极大值抑制(NMS):过滤掉重叠的、冗余的预测框。YOLOv8的输出通常已经包含了经过NMS处理的结果,但有些导出格式可能需要自己实现。
- 阈值过滤:根据置信度分数(如
conf_threshold=0.25)和类别概率过滤掉不可信的预测。 - 坐标还原:将模型输出的归一化坐标,根据原始图像的尺寸还原为像素坐标。
- 结果可视化与输出:将检测框和类别标签画在图像上,显示或保存。
5.4 持续迭代与数据闭环
模型上线不是终点。在实际应用中,你会收集到大量新的、模型可能处理不好的场景数据(例如,雨雪天气下的垃圾、极端光照下的反光瓶子)。建立一个数据闭环至关重要:
- 主动收集困难样本:记录下模型漏检、误检的案例。
- 人工复核与标注:对这些困难样本进行精标。
- 增量训练:将新标注的数据加入原有训练集,用之前的模型权重进行微调,让模型持续进化。
这个过程可以逐步提升模型在特定场景下的鲁棒性。对于这个892张的数据集,它就是一个强大的起点。你可以基于它训练一个基础模型,然后在后续的迭代中,用新数据不断微调,让模型越来越“聪明”。
本文还有配套的精品资源,点击获取