基于YOLOv8的路面垃圾识别:数据集构建与训练实战

📅 发布时间:2026/9/8 22:16:23
基于YOLOv8的路面垃圾识别:数据集构建与训练实战
简介面向目标检测学习与实践的路面垃圾识别数据集包含7537张真实场景图片的标注信息覆盖塑料瓶、口罩、纸袋、易拉罐、玻璃瓶等17个常见垃圾类别可支持YOLO系列、Faster RCNN、SSD等主流模型训练。资源包共2000个文件以1999个YOLO格式txt标注文件为核心另含1个yaml类别配置文件txt标签已划分训练集、验证集和测试集解压后即可直接用于YOLO算法训练。数据集来源于真实路面场景适用于市政环卫、自动驾驶辅助等方向的模型验证也便于学习者对比不同目标检测框架的精度与速度。压缩包整体约527MB文件组织清晰省去自行整理数据的环节。目前已有824人学习对高校学生、科研人员及AI开发者而言是一套兼具实用性与学习价值的练手资源。 路面垃圾识别这个需求最早是朋友找我帮忙做城市道路巡检的试点。他们丢过来一句话想要一套能自动识别塑料瓶、易拉罐、纸杯、烟盒这类路面杂物的检测模型并且只给了一批没整理过的现场照片。我当时的反应是模型不是最大的问题真正的难点在于把这些照片整理成一套能训练的路面垃圾识别数据集。那种只有原始图片、没有任何标注文件的目标检测项目做完一次你就会记住一个规律——数据集的质量决定了检测效果的上限模型只是在不断逼近这个上限。我把这批照片整理成数据、做增强、用 YOLOv8 跑完整流程踩了不少坑这篇文章就把这些经验完整整理一遍。需要补充的是这套经验不仅对道路场景有效。换成工厂地面异物、超市货架摆货、工地遗留杂物这些场景思路几乎一致。整篇内容分为数据设计、标注清洗、增强策略、训练配置、评估分析、常见问题几个部分适合正在准备目标检测数据集、或者打算从零自定义一个 YOLOv8 训练项目的读者。如果你手头已经有一部分实拍素材只是不知道下一步怎么处理这篇应该能直接帮你省下三四天调试时间。1. 项目背景与数据集整体设计1.1 为什么路面垃圾识别要单独做一套数据很多人觉得垃圾检测直接用公开数据集就行真上手后会发现自己掉进了三个坑公开集大多是室内或园区场景道路上的光照、阴影、拍摄视角完全对不上路面垃圾形态普遍很小瓶子倒着、纸团半压着、易拉罐带反光这些细节在通用数据集里非常稀缺最后是类别定义对不上业务要区分“可回收瓶罐”和“纸屑杂物”公开集给出的却是家居垃圾或行人车辆。我坚持从现场实拍照片整理而不是直接下载现成数据集核心逻辑是检测场景越具体数据集越要贴近真实部署环境。路边垃圾识别的拍摄距离大多在 5 到 15 米单张图里目标可能只有几十到一两百像素这种小目标特性会影响后续所有环节——从标注精度要求、数据增强力度到模型输入尺寸的选择。如果只做通用数据集迁移看着 mAP 不低一到实际路况立刻露馅。1.2 类别体系与目录结构怎么定数据阶段最值得花心思的就是类别定义。我按业务需求把路面垃圾定成了五类避免类别过细导致标注混乱类别名中文含义典型外观特点plastic_bottle塑料瓶半透明、易反光、常有高光干扰can金属易拉罐金属光泽、圆形截面、阴影明显paper_cup纸杯/纸盒白色或带印刷图案、表面不平整plastic_bag塑料袋透明或彩色、形状不规则、容易变形cigarette_pack烟盒/烟头体积小、色彩鲜艳但容易被遮挡标注格式方面我直接选了 YOLO 的 txt 格式每条记录是类别id 中心点x 中心点y 宽度 高度全部按图像宽高归一化。这样做的好处是省了一层格式转换YOLOv8 开箱即用。后续如果有人需要 COCO 或 Pascal VOC 格式再写个小脚本转就行反向转换反而更麻烦。目录结构我是这样规划的garbage_det/ ├── data.yaml ├── images/ │ ├── train/ # 856张 │ ├── val/ # 112张 │ └── test/ # 63张 └── labels/ ├── train/ ├── val/ └── test/图片和标签文件名保持一致这是 YOLO 系列最常见也最不容易出错的约定。注意测试集在训练阶段绝对不能碰否则最后评估结果会虚高误导你对模型真实水平的判断。2. 数据清洗、标注检查与增强策略2.1 先清一遍标注文件再进训练标注文件是数据流程里事故率最高的环节。我第一次跑训练时就在 5 分钟之内收到了源文件大小不匹配的错误。排查发现两个典型问题一是某些标注文件里出现了负数坐标这多半是标注工具框选时越界造成的二是归一化坐标写成了整数比如把 0.5 写成了 0导致锚框直接落在图像边缘。后来我写了一个小脚本先在训练前统一检查所有 txt 标注任何一行坐标超出 0 到 1 范围、或者类别 id 超出配置的类别数直接打印文件名并跳过。这类问题在几百张图时还能人工翻数据量上千之后必须靠脚本兜底。更隐蔽的一个坑是图像和标签文件名对不上。有些相机自动改名、图片压缩后编号错位训练时模型看到图 A 却读到图 B 的标签损失函数照样能算只是最终 mAP 一塌糊涂。排查方法是写脚本统计 images 和 labels 两个目录下同名文件的数量差数量不一致就说明有文件丢失或重命名。2.2 增强参数不是越多越好路面垃圾这个小目标场景数据增强不能无脑堆。YOLOv8 默认开启的马赛克增强在通用目标上效果很好但对小垃圾目标有时反而是干扰四张图拼在一起后很多瓶子、烟盒被截断或缩小到只有 20 像素模型学习到的特征严重失真。我采用的增强方案是前 90 个 epoch 正常使用马赛克增强最后 10 个 epoch 关闭马赛克术语叫close_mosaic让模型在这段时间里拟合真实尺寸的目标翻转向量设成 0.5垂直翻转保持 0因为路面垃圾没有上下颠倒的合理性颜色扰动开小一些hsv_h0.01hsv_s0.5避免把道路色调学歪缩放增强控制在 0.5 以内过大的缩放会让垃圾目标直接消失训练集只有 856 张图的情况下增强力度太大会让每个 epoch 内同一张图以完全不同的形态出现模型容易被“带偏”验证集上指标迟迟不涨。这不是增强越多越好而是要让网络在“见过更多变体”和“保持目标真实分布”之间找平衡。2.3 训练集、验证集怎么切分才科学很多人拿到图片后直接random_split这是目标检测项目里最坑的做法。道路巡检照片通常是一段路上连着拍的同一条街、同一个时段的光照高度相似如果这些相似图片被同时分进训练集和验证集验证集就会失去代表性模型在训练集上“记住”场景验证精度虚高。我这次按照片的拍摄时间戳地点前缀做分组保证同一个路段的所有图片要么全在训练集要么全在验证集。实际操作就是先把图片文件名解析出地点字段按地点分组后再随机挑选 80% 的地点作为训练场景其余 20% 的地点作为验证场景。测试集则单独保留一段没有参与训练的新路段专门模拟真实部署时面对的陌生环境。3. 基于 YOLOv8 的训练流程与关键参数3.1 环境准备与 YOLO 格式转换环境部分不复杂直接装 ultralytics 库就行。pip install ultralytics如果你的标注文件原本是 COCO JSON 格式或者想从其他工具导出可以先用下面的脚本转成 YOLO 格式。这里的关键点是坐标转换COCO 的 bbox 是左上角 x、y 和宽高YOLO 需要的是中心点坐标和宽高并且全部要除以图像宽高做归一化。import os import json def coco_to_yolo(coco_json_path, img_dir_path, label_out_path): with open(coco_json_path, r, encodingutf-8) as f: data json.load(f) image_map {img[id]: img for img in data[images]} category_map {cat[id]: idx for idx, cat in enumerate(data[categories])} os.makedirs(label_out_path, exist_okTrue) for ann in data[annotations]: img image_map[ann[image_id]] img_w, img_h img[width], img[height] bbox ann[bbox] # origin: 左上角x, 左上角y, w, h cx (bbox[0] bbox[2] / 2) / img_w cy (bbox[1] bbox[3] / 2) / img_h x bbox[2] / img_w y bbox[3] / img_h line f{category_map[ann[category_id]]} {cx:.6f} {cy:.6f} {x:.6f} {y:.6f}\n label_name os.path.splitext(img[file_name])[0] .txt with open(os.path.join(label_out_path, label_name), a, encodingutf-8) as out: out.write(line) print(转换完成)转换后随机抽查 10 张图把标注框画回原图确认位置没有偏移这一步别省。坐标转换看似简单一旦某处除错符号模型不会报错只会闷头学习错误位置最后检测框全部偏左上或偏右下。3.2 编写数据配置并启动训练数据配置文件data.yaml内容如下# data.yaml train: /home/user/garbage_det/images/train val: /home/user/garbage_det/images/val test: /home/user/garbage_det/images/test nc: 5 names: [plastic_bottle, can, paper_cup, plastic_bag, cigarette_pack]然后直接启动训练我用的命令是yolo detect train \ modelyolov8m.pt \ data/home/user/garbage_det/data.yaml \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectrun/garbage \ nameexp1注意modelyolov8m.pt这里我选择了中杯模型没有一上来就上 x 版本。路面垃圾类别少、语义边界相对清晰m 模型的参数量足够训练速度更快部署也更友好。如果网络容量过大在只有几百张图的小数据集上反而更容易过拟合。3.3 训练参数怎么设才不容易翻车这几个参数我建议按下面的逻辑来调imgsz默认 640 在大多数路况下没问题。如果觉得小瓶子、小烟盒识别不准可以试 1280但显存占用会直接翻好几倍推理速度也会明显下降。我的建议是先用 640 跑通全流程再单独做一组 1280 的对比实验。batch在 8G 显存、imgsz640的情况下batch16基本是安全值16G 显存可以尝试 32。拿不准就直接写batch-1YOLOv8 会自动根据显存算一个最合适的批次。workersCPU 核数多就设 8核数少设 4。这个参数太小会造成 GPU 空转太大则可能把内存占满。cacheram数据量在几百到两三千张时可以开启把所有图片缓存进内存能明显加速训练。但要注意看内存占用同时开增强和缓存内存小的机器可能直接卡死。训练过程中我习惯盯着两个关键曲线训练损失和验证损失。如果训练损失一直降验证损失反而上升这就是过拟合信号通常做法是调低权重衰减系数、减少训练轮数或者把增强力度降下来。如果两个损失都不降那多半是学习率太大或者数据本身存在系统性标注错误。4. 评估结果与部署效果分析4.1 主要看哪些评价指标目标检测训练过程中评价标准很多我实际使用中只盯这几个precision、recall、mAP50、mAP50-95。precision 反映模型预测出的方框里有多少真的是垃圾recall 反映真实垃圾里有多少被找回来了mAP 是对不同置信度阈值下精确率和召回率综合打分的结果。当时训练结束后我的指标大概长这样类别precisionrecallmAP50plastic_bottle0.870.830.89can0.910.880.93paper_cup0.780.740.82plastic_bag0.700.660.74cigarette_pack0.720.700.77整体 mAP50 大概在 0.86mAP50-95 在 0.63 左右。可以看到塑料袋和烟盒的精度偏低这符合预期塑料袋形状太随意烟盒太小太容易遮挡。如果你跑出来的结果里某个类别的指标特别差优先怀疑那一类样本数量不足或者标注框框得不够准而不是急着换大模型。4.2 用混淆矩阵定位失败样本模型训练完YOLOv8 会在结果目录下生成混淆矩阵图。我第一次看混淆矩阵时发现一个特别明显的规律易拉罐和塑料瓶之间存在大量互相误判。原因也好理解两者都是圆柱形反射高光后轮廓很接近唯一可靠区分点是材质和表面的纹理。针对这个混淆我做的调整是补了一批“远处易拉罐”和“强光下塑料瓶”的特写图进训练集专门让网络学习二者的材质差异。补数据之后混淆量明显下降。这类靠肉眼看不出来、只能在混淆矩阵里暴露的问题是最值得花时间优化的方向。4.3 在视频流上做推理验证离线的图片测试只能说明模型上限落地时我更关心视频流能不能跑得稳。推理命令非常简单yolo predict modelrun/garbage/exp1/weights/best.pt \ sourcetest_video.mp4 \ conf0.35 \ iou0.45 \ saveTrueconf0.35的意思是置信度低于 0.35 的框全部丢掉。实际路测时我发现这个阈值不能设太高特别是画面里有运动模糊的帧很有价值的检测结果置信度可能只有 0.3 左右。我通常先把conf调到 0.25先保证不丢目标再根据误报情况逐步往上调。视频流推理如果嫌慢可以打开halfTrue使用半精度 FP16 推理大多数支持 AMP 的 GPU 上速度能提升不少精度损失在可接受范围内。5. 常见问题与排查技巧实录5.1 问题排查速查表问题现象可能原因排查方向训练时报 shape mismatch最后一批样本数量和 batch 不匹配或缓存数据损坏降低 batch 或用batch-1自动计算清空缓存某类 mAP 特别低该类样本量少、标注遗漏多统计每类框的数量分布缺哪类补哪类视频推理漏检严重目标太小、置信度阈值过高、运动模糊提高imgsz把conf降到 0.25加目标跟踪做跨帧补偿训练损失不降学习率太大或标注质量差先确认标注再调低lr0验证损失远高于训练损失过拟合或数据集划分泄漏降低训练轮数关闭马赛克按场景重新切分数据模型把易拉罐识别成塑料瓶两类特征太接近训练数据不足针对性补拍两类极端光照/材质的图片5.2 两个容易被忽略的坑第一个坑是类别极度不平衡。我这批数据里塑料瓶占了一半以上烟盒只占百分之五。直接训练出来的模型会偏向瓶类烟盒召回率非常难看。解决方式不是删瓶子图片而是在训练时对少数类做 oversample也就是把烟盒图片复制三到五次混进训练集用最简单的重采样就能改善类别平衡。注意复制图片时要同步复制同名标签文件很多人会漏掉后面这一步。第二个坑是部署环境里相机高度和角度变了模型效果断崖式下跌。路面垃圾识别一旦换了一个安装角度目标在图像里的尺度和透视关系全变再好的模型也会打折扣。建议在采集数据阶段就按部署时真实的相机高度和视角来拍不要贪图省事从网上下载俯拍图。最后分享一个本地经验我在落地时给检测模型前串了一个简单跟踪器依靠帧间关联补回零零散散的漏检实测下来比单纯把模型调大更省钱、更有效有类似需求的朋友可以先往这个方向试。本文还有配套的精品资源点击获取