ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

垃圾目标检测数据集构建实战:从类别体系到YOLOv8训练

垃圾目标检测数据集构建实战:从类别体系到YOLOv8训练 简介这是一套面向计算机视觉与人工智能领域的目标检测数据集聚焦电池、纸团、一次性杯子、塑料瓶和积木五类常见垃圾目标采用COCO格式进行标注每张图像均包含边界框信息可直接服务于YOLO、SSD、Faster R-CNN等主流检测模型的训练与效果评估。全套资源共1753个文件包括1743张jpg图片、8张png图片和2个json标注文件压缩包约20.19MB图片素材来自多样场景json文件则记录每个目标的类别与坐标可方便地拆分训练集、验证集和测试集。该数据集聚类了实际环保应用中的典型对象为垃圾分类、智能监控等场景提供标准化训练数据。目前已有2199人学习/下载无论是正在学习目标检测算法的高校学生还是需要基础数据开展实验的算法工程师都能从中获得直接可用的数据支撑。1. 垃圾目标检测数据集难点不在“找图”而在“标得动”如果我接手一个智慧环卫项目第一周的结论会有些反直觉垃圾目标检测的技术瓶颈不在模型而在数据集。通用检测器对易拉罐、塑料瓶这类“物体”已经足够稳可切到真实巡检画面烟蒂、泡沫块、破渔网、半埋在土里的砖头跑一遍通用模型会漏掉近八成。“垃圾”在物体目标检测里不是单一类别而是几十类目标的并集这使它同时踩中细颗粒度、小目标、长尾分布三个坑。从零做一套自己的垃圾目标检测数据集我一般会走这样一条链路先定类别树和标注规范再混入公开数据集和自采视频抽帧然后用半自动预标注压减人工成本最后用 YOLOv8 跑闭环训练拿指标反推哪些样本标错了。下面每一步都落到命令和参数上。2. 先拆清楚垃圾目标检测数据集的类别体系与标注规范2.1 垃圾检测不是“乱标一通”先定类别树越早定类别数据加工越便宜。我基本不会直接用“垃圾”作为类别名而是把垃圾降解成“可感知的弃置物”塑料瓶、易拉罐、塑料袋、泡沫、玻璃瓶、烟蒂、纸箱、布料、砖块、轮胎。它们形态差异大在画面里的颜色、纹理、边缘和光照表现各不相同如果按垃圾的化学成分归类同一类在图像上完全不可分标注员会崩溃模型也学不到稳定特征。建议做两级类别树。第一级记录场景属性岸线陆地、水面漂浮、道路市政、工地废料第二级才是具体类别数量控制在 8 到 15 类。类别数太多会让每个类别样本量不足太少则模型无法区分“塑料袋”和“白色泡沫”。下面是一个可参考的初始清单一级场景二级类别常见形态典型尺寸占比标注难度岸线/陆地塑料瓶、易拉罐、玻璃瓶多为完整或轻度压瘪容器中低滩涂/水面泡沫、塑料片、渔网碎片多半埋或浸水边界不清小高道路/市政烟蒂、口罩、纸屑目标极小遮挡严重小高工地/废料砖块、混凝土块、钢筋形状不规则常堆叠中中定完表不能急着标。先把每个类别的定义写成一份标注文档附 3 到 5 张典型图和 1 到 2 张边界图说明“什么算什么不算”。例如“沾满泥土的塑料袋”算“垃圾桶内已投放的瓶子”不算因为开放场景只关心暴露在环境里的弃置物。没有这份规则第二个人接手时标注一致性会立刻崩塌。2.2 标注粒度与小目标垃圾是“小”出来的垃圾目标检测数据集与通用物体检测的本质区别是小目标占比极高。按 MS COCO 的面积口径小于 32×32 像素的框算小目标垃圾场景里烟蒂、泡沫碎块常常连 16×16 像素都没有。标注时如果不在原图上放大 300% 再操作很容易把一个烟蒂略过。我建议直接标注边界框不要走“先分割再转框”的弯路。垃圾边界模糊逐像素分割争议大标注成本高而且多数公开数据集只提供 bbox先做检测任务用 bbox 足够。COCO 格式里一个标注记录长这样{ images: [ { id: 1, file_name: frame_0001.jpg, width: 1920, height: 1080 } ], annotations: [ { id: 1, image_id: 1, category_id: 2, bbox: [1240.5, 308.2, 18.3, 21.7], area: 396.51, iscrowd: 0 } ] }bbox依次是左上角 x、左上角 y、宽、高area必须与 bbox 一致iscrowd对垃圾检测建议全部置 0。垃圾目标经常堆叠如果把一堆瓶罐标成iscrowd1模型永远学不到单目标边界。还需要注意保留浮点坐标不要四舍五入成整数小目标框宽可能只有十几像素每个像素的偏移都会显著降低 IoU。2.3 难例标注规则遮挡、半埋与目标过小垃圾数据集中最难的不是正常暴露目标而是三种情况被植物或泥沙遮挡、目标只有局部露在外面、光线很差。没有规则的标注员会把“露出的一条塑料袋角”也框出来另一人却选择跳过这两者在训练里互相打架。一般做法是定三条硬规则第一可见面积小于目标的 30% 不标第二目标完全被泥土或水覆盖只能凭颜色判断的不标第三目标在画面中短边小于 8 像素不标。这三条规则的目的不是减少信息而是保证标注框的“语义确定性”。垃圾检测的难例学习应交给模型用更多样本来补足而不是靠标注员猜测。3. 从源头构建数据集公开集勾兑、视频抽帧与预标注3.1 公开垃圾目标检测数据集怎么取舍公开数据集中可以用于垃圾检测的有 TACO、TrashCan 这类专门集也有 COCO、VOC 中与瓶罐纸箱相关的类别。专门集的价值是类别命名贴近真实垃圾COCO 的价值是数量大、迁移容易。但这些数据集之间有两个冲突一是标签口径不一致同是“瓶子”有的集要求标饮料瓶有的把所有容器都算二是形态偏移COCO 里的瓶子大多是完整立在桌上的而垃圾场景里的瓶子是压扁、破损、半埋的。我的做法是把公开集放进“预训练池”而不是直接混入训练集。先用公开集让模型见足够多的“物体形态”再用自采数据微调。如果图省事直接合并训练需要统一改标签并重新抽检否则某个类别在训练时同时看到两种对立标注loss 会出现奇怪抖动。3.2 自采视频抽帧一个 ffmpeg 命令稳住源头自采视频仍然是最可控的数据来源。我一般用手机或监控摄像头固定机位在不同时段、天气和光照下绕场地巡检单场景拍 5 到 10 分钟。抽帧用 ffmpeg 按时间间隔抽而不是逐帧抽ffmpeg -i site_A.mp4 -vf fps1/3 -q:v 1 -start_number 0 frames_site_A_%04d.jpg参数说明fps1/3表示每 3 秒输出一帧适合目标基本静止的巡检画面-q:v 1是图像质量取值 2 到 31值越小质量越高-start_number 0让输出帧号从 0 开始连续方便后续脚本对齐。逐帧抽帧会产生大量几乎相同的冗余帧这些高相似度画面进到训练集后会让模型过拟合到固定背景验证集指标虚高。抽帧后可以做一次感知哈希去重。对每帧计算 pHash去除汉明距离小于 5 的相邻帧这一步用 OpenCV 几十行就能完成能显著降低标注成本。3.3 用 YOLOv8 半自动预标注把标注工作量压到 30%完全人工框垃圾目标不现实。常见做法是先用预训练模型给整批图生成伪标签再让人工在伪标签基础上修正。以下代码用 Ultralytics YOLOv8 对 frames 目录做批量推理from ultralytics import YOLO model YOLO(yolov8m.pt) model.predict( sourceframes/, imgsz640, conf0.30, max_det100, save_txtTrue, save_confTrue, classes[39, 41, 44, 62] )这段代码的输出是每张图片同名的 txt格式为class x_center y_center width height conf。conf0.30控制伪标签的召回率调低到 0.2 能多检一些小目标代价是垃圾框增多classes是 COCO 类别索引过滤只保留瓶子、杯子、碗、椅子等可能与垃圾相关的类。预标注的价值不是一次到位而是让标注员在已有框的基础上去增补漏检、调整错框这个流程能把纯人工时间压缩到原来的三分之一左右。生成的伪标签可以直接导入 Label Studio 或 CVAT。转换时注意把 YOLO 格式的中心点脚标换算成 COCO 的左上角坐标导入后人工逐张修正。不要直接把伪标签当训练标签用垃圾场景下烟蒂和泡沫的漏检率通常超过 60%。3.4 人工修正后的抽检一致性检查标注完成后要做一次双人一致性检查。抽 100 张已修正图片让另一个人完全重新标计算两组框之间的 IoU。合格线大致是简单场景 IoU 大于等于 0.7 一致复杂场景大于等于 0.5 一致完全漏标率小于 2%。如果“完全漏标”超过 5%说明标注规范没有落地要在第 2 章的文档里补充典型图而不是继续标下去。分类一致性同样要查。垃圾场景中塑料袋与塑料膜、布料与渔网很容易互相串类建议把验证集上互相误标比例高的类直接合并。串类问题靠模型再训练是压不掉的根源在训练标签就已经错了。4. 用 YOLOv8 把垃圾目标检测数据集训练成可用模型4.1 train/val 划分必须在视频层级做划分数据集时我见过最多的错误是在帧层面随机切分。同一个视频前半段进 train、后半段进 val两批画面背景高度重叠最后验证 mAP 虚高到 0.85 以上换新场景立刻掉回 0.5。正确做法是按视频文件分桶每个视频的所有帧只能进单侧集合公开集则按拍摄场景分组。此时准备一份数据配置path: ./garbage_det train: images/train val: images/val names: 0: plastic_bottle 1: can 2: glass_bottle 3: foam 4: plastic_bag 5: cigarette_butt 6: fabric 7: brick 8: tirenames的值必须从 0 开始连续编号。如果抽帧脚本生成了类别的概率不要把它当最终监督信号有噪声的伪标签可以在预训练阶段用进入正式训练前必须经过人工确认。4.2 训练命令与必调参数我用 YOLOv8 训练垃圾检测模型时通常从 s 而不是 n 起步。n 对小目标漏检严重m 对小目标更好但需要更大 batch 和更长训练时间。基础命令如下yolo train \ datagarbage_data.yaml \ modelyolov8s.pt \ imgsz640 \ batch16 \ epochs100 \ close_mosaic10 \ patience20 \ projectgarbage_exp \ namerun1参数按垃圾场景的实际情况说明modelyolov8s.pt加载 COCO 预训练权重迁移效率远高于从零训练。如果你的垃圾类别与 COCO 重合度不高仍然推荐用它初始化因为低层特征可以迁移。imgsz640对烟蒂这种 16×16 像素的目标640 输入下它只占图宽的 2.5%。显存足够时调到 960小目标 AP 提升非常明显代价是训练时间翻倍。close_mosaic10最后 10 个 epoch 关闭 mosaic。YOLOv8 的 mosaic 把 4 张图拼在一起大量小目标在裁剪时被切碎训练后期恢复真实分布有助于收敛。patience20连续 20 个 epoch 验证集无提升则早停避免过拟合到重复帧。显存不够时用batch-1让 Ultralytics 自动探测最大 batch。我一般不推荐开rectTrue虽然它能省显存但会让 batch 内做矩形 padding导致尺度分布不稳定与垃圾检测的小目标需求相冲突。4.3 评估小目标和大目标必须分开看训练完成后第一件事不是看总 mAP而是逐个类别看 APyolo val modelgarbage_exp/run1/weights/best.pt datagarbage_data.yaml imgsz640输出结果中重点关注每类的mAP50和mAP50-95。垃圾检测最常见的失败模式是某个小目标类别 AP50 低于 0.5而瓶子、砖块这类大目标 AP50 超过 0.85。出现这种两极分化先不要调模型回去看标注框的面积分布如果烟蒂类超过 90% 的框面积小于 32×32且样本量不足 100补数据比调参更有效。混淆矩阵也要打开。垃圾类别中最常互相串的是塑料袋和泡沫、布料和渔网。如果 val 集显示这两个类互相误判率超过 20%优先怀疑标注边界不一致而不是模型能力不够。此时重新抽看原始图往往会发现当初类别树就没定清楚。5. 部署前最后一步给垃圾检测数据集做定向增强5.1 Copy-Paste 增强长尾类垃圾检测与其他场景不同垃圾目标常孤立出现遮挡少适合把同一目标复制到多个背景中。这比从零采集更多“同目标不同环境”的照片便宜得多。常见做法是用 Python 读取已有标注框把目标裁剪并旋转后粘贴到另一张无该目标的前景图上同时把新框写入标签。贴小目标时注意做轻微的缩放和亮度扰动否则模型会学习到“复制品”的固定纹理。5.2 用光照和天气扰动提升泛化垃圾素材大多来自晴天白天雨天、逆光、黄昏场景严重量不足。可以在训练流程里加随机亮度和对比度扰动也可以直接用 albumentations 的随机伽马变换模拟不同光照。水面漂浮垃圾还要加模糊和细小雨纹噪声这类增强对岸线巡检视频尤其有效。我的经验是增强幅度要克制过强的 hue 扰动会让模型把“绿色树叶”和“绿色瓶子”混在一起。5.3 验证增强是否有效不看总 mAP 看三类指标每次增学改动后做一次差分验证同一套 train/val 划分只开或关某项增强分别训练到收敛对比三类指标——每类 AP、漏检率、误检框数。漏检率可以用模型在难例集上的召回替代误检框数则直接数验证集里置信度大于 0.5 的错框。如果 Copy-Paste 只提升了长尾类的 AP却没有拉低其他类说明增强方向正确如果总 mAP 没变但烟蒂类 AP50 从 0.35 升到 0.42这比总 mAP 上升 0.02 更有价值因为你真正要服务的是真实巡检里那些小到几乎看不见的目标。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进