基于YOLOv8的垃圾分类目标检测:从数据集制作到边缘部署全流程

发布时间:2026/9/28 13:14:44
基于YOLOv8的垃圾分类目标检测:从数据集制作到边缘部署全流程 1. 从一张随手拍的照片说起这个项目到底在解决什么问题小区楼下四个垃圾桶并排摆着可回收、有害、厨余、其他颜色分得清清楚楚。但真到了扔垃圾那一刻手里攥着个沾了油的塑料餐盒脑子里就开始打架——这玩意儿到底算可回收还是其他外卖盒冲一冲能回收没冲干净就是其他垃圾这种边界模糊的判断别说普通居民我自己有时候都得愣两秒。这个项目要干的事情说白了就是让机器替人做这个判断。你拿手机对着垃圾拍一张照片系统在图片上把每个垃圾物体框出来同时告诉你它属于哪一类。技术上这叫目标检测加图像分类的组合任务用到的核心算法是YOLOv8一个在工业界落地非常广的实时目标检测框架。为什么选YOLOv8而不是别的我试过Faster R-CNN精度确实不错但推理速度在普通设备上实在感人一张图动辄几百毫秒起步。垃圾分类这个场景如果是做成社区投放点的智能识别设备或者手机端的小程序响应速度直接决定用户体验。YOLOv8的nano版本在CPU上跑一张图大概几十毫秒这个差距是数量级的。而且YOLOv8的工程化做得好从训练到部署的链路很顺不像有些框架训练完导出模型还要折腾半天。这篇文章适合谁看如果你正在做深度学习相关的课程设计、毕业设计或者想找一个完整的目标检测项目练手这个垃圾分类识别的案例非常合适。它涉及数据集制作、模型训练、改进优化、部署推理的完整流程麻雀虽小五脏俱全。如果你是完全零基础我建议先补一下Python和深度学习的基本概念至少知道卷积神经网络大概是怎么回事不然看代码会比较吃力。提示这个项目的核心难点不在模型本身而在于数据集的质量和类别定义的合理性。很多人一上来就调模型参数结果发现数据标注一塌糊涂怎么调都上不去。2. 整体方案设计为什么这样搭架子2.1 任务拆解与技术选型逻辑垃圾分类识别本质上是一个多类别目标检测问题。输入是一张包含若干垃圾物品的图片输出是每个物体的边界框坐标和类别标签。类别通常按国家或地区的垃圾分类标准来定国内常见的是四分类可回收物、有害垃圾、厨余垃圾、其他垃圾。技术路线上我选择YOLOv8作为基线模型原因有三。第一YOLO系列是单阶段检测器一步到位输出检测结果速度快适合实时场景。第二YOLOv8在COCO数据集上的预训练权重可以直接拿来用迁移学习能大幅缩短训练时间。第三Ultralytics这个库的API设计得很友好训练、验证、导出模型几行代码就能搞定省去了大量工程上的麻烦。数据集方面我用了公开的垃圾分类数据集加上自己补充拍摄的图片。公开数据集大概有几千张但类别分布不均匀可回收物特别多有害垃圾特别少。这种不平衡会导致模型对少数类别识别效果差后面会讲怎么处理。2.2 改进思路在YOLOv8基础上动了哪些刀直接用YOLOv8跑垃圾分类效果其实已经能看了但有几个问题比较突出。一是小目标检测效果一般比如电池这种小体积的有害垃圾容易漏检。二是类别混淆塑料瓶和玻璃瓶外观相似模型有时候会搞混。三是背景干扰垃圾放在桌上、地上、垃圾桶里背景变化大模型容易分心。针对这些问题我做了几处改进。第一在骨干网络中引入注意力机制具体是在C2f模块后面加了CBAM卷积块注意力模块让模型更关注物体本身的特征抑制背景噪声。第二调整了特征融合网络的结构增加了一个小目标检测层把浅层特征图也纳入检测提升小物体召回率。第三在损失函数上用了Focal Loss的思想对难分类样本加大权重缓解类别不平衡问题。这些改进不是拍脑袋想的每一项都有对应的实验对比。比如加注意力机制后mAP50提升了大概2.3个百分点小目标的召回率提升更明显。当然改进是有代价的模型参数量增加了推理速度会慢一点点但在可接受范围内。2.3 数据流的整体走向整个系统的数据流是这样的用户上传图片经过预处理缩放、归一化送入训练好的YOLOv8模型模型输出检测框和类别概率再经过非极大值抑制NMS过滤掉重叠框最后把结果可视化出来画框、标类别、显示置信度。如果是部署到边缘设备比如RK3588或者树莓派还需要把PyTorch模型转成ONNX或者RKNN格式做量化加速。这部分后面会单独讲。3. 数据集制作垃圾识别项目的命根子3.1 数据采集的坑与经验数据集的质量直接决定模型的上限。我一开始图省事直接从网上下载了一个现成的垃圾分类数据集大概五千张图。训练完发现模型在测试集上表现还行但一拿到真实场景就拉胯。原因很简单网上的图片大多是白底商品图垃圾摆得整整齐齐光线均匀跟实际场景差距太大。后来我花了大概两周时间自己拍了一千多张照片。拍摄场景包括厨房台面、客厅地板、小区垃圾桶旁边、阳台角落。光线有白天自然光、晚上灯光、阴天散射光。垃圾的状态也尽量多样有干净的塑料瓶也有沾了污渍的餐盒有完整的纸箱也有揉成团的废纸。注意拍摄时尽量让垃圾物体在画面中的比例适中不要太大也不要太小。太小了模型学不到细节太大了边界框容易超出画面。一般物体占画面面积的10%到50%比较合适。3.2 标注工具选择与标注规范标注工具我用的是LabelImg这是一个老牌的图像标注工具支持Pascal VOC和YOLO格式导出。后来也试过Labelme功能更强大支持多边形标注但垃圾分类用矩形框就够了LabelImg更轻量。标注规范这块我踩过不少坑。第一边界框要贴紧物体边缘不要留太多空白也不要切掉物体的一部分。第二遮挡情况要统一处理如果物体被遮挡超过50%我选择不标注遮挡小于50%的按可见部分画框。第三类别定义要明确比如“塑料瓶”算可回收物“沾油塑料餐盒”算其他垃圾这个规则要提前定好标注时严格执行。标注完成后我写了一个脚本检查标注质量主要看几个指标每个类别的实例数量、边界框的宽高比分布、是否有超出图像边界的框。结果发现有害垃圾只有不到两百个实例严重不足。后来专门补拍了一批电池、灯管、药品的图片。3.3 数据增强与类别平衡策略数据增强是提升模型泛化能力的有效手段。YOLOv8内置了Mosaic增强、随机翻转、HSV色彩空间扰动等。Mosaic增强是把四张图拼成一张让模型在一张图里看到更多上下文对小目标检测特别有帮助。针对类别不平衡我用了两种策略。一是过采样对有害垃圾这类少数类别在训练时重复采样让每个batch里各类别比例相对均衡。二是数据增强补偿对少数类别做更多的旋转、缩放、色彩变换增加样本多样性。另外我还用了一个小技巧把一些容易混淆的类别合并。比如“塑料瓶”和“玻璃瓶”外观相似如果分开标注模型很容易搞混。我一开始分成两类结果混淆矩阵里这两类互相误判的比例很高。后来合并成“瓶类”再通过材质特征细分效果反而更好。类别原始实例数增强后实例数处理策略可回收物32003200保持原样有害垃圾180900过采样增强厨余垃圾15002200适度增强其他垃圾21002100保持原样4. 模型训练与改进从能跑到跑得好4.1 环境配置与训练参数设置环境配置这块我是在Ubuntu 20.04上做的显卡是GTX 1660 Ti6GB显存。YOLOv8的安装很简单pip install ultralytics就行。但要注意CUDA和cuDNN的版本匹配我一开始CUDA版本不对训练时一直报错折腾了半天。训练参数方面我用的配置是这样的输入图像尺寸640x640batch size设为166GB显存跑不了太大初始学习率0.01用余弦退火调度训练100个epoch。优化器选的是SGD动量0.937权重衰减0.0005。这些参数不是随便定的640的输入尺寸是YOLOv8的默认值在精度和速度之间比较平衡batch size受显存限制学习率参考了官方推荐值。训练过程中我监控了几个关键指标训练损失、验证损失、mAP50、mAP50-95。前20个epoch损失下降很快后面逐渐平缓。到第80个epoch左右验证损失不再下降甚至略有上升说明开始过拟合了。所以我最终选了第75个epoch的权重作为最终模型。4.2 改进点的代码实现细节注意力机制的加入是在YOLOv8的骨干网络里。具体来说我在每个C2f模块后面插入了一个CBAM模块。CBAM包含通道注意力和空间注意力两个部分通道注意力学习每个通道的重要性空间注意力学习每个位置的重要性。代码实现上我继承YOLOv8的C2f类写了一个C2f_CBAM类在前向传播时先过C2f再过CBAM。小目标检测层的增加是在PANet结构里多接了一个来自骨干网络浅层的特征图。原始YOLOv8有三个检测头分别对应80x80、40x40、20x20的特征图。我加了一个160x160的检测头专门负责小目标。这个改动会增加计算量但小目标的召回率提升明显。Focal Loss的引入是在分类损失部分。原始YOLOv8用的是BCE Loss我换成了Focal Loss的变体对易分类样本降权对难分类样本加权。参数上gamma设为1.5alpha设为0.25。这个参数组合是我试了几组之后选的gamma太大训练不稳定太小又起不到聚焦难样本的作用。# 简化版的C2f_CBAM实现 import torch import torch.nn as nn class CBAM(nn.Module): def __init__(self, channels, reduction16): super().__init__() self.channel_att nn.Sequential( nn.AdaptiveAvgPool2d(1), nn.Conv2d(channels, channels // reduction, 1), nn.ReLU(), nn.Conv2d(channels // reduction, channels, 1), nn.Sigmoid() ) self.spatial_att nn.Sequential( nn.Conv2d(2, 1, 7, padding3), nn.Sigmoid() ) def forward(self, x): ca self.channel_att(x) x x * ca sa torch.cat([x.mean(dim1, keepdimTrue), x.max(dim1, keepdimTrue)[0]], dim1) sa self.spatial_att(sa) return x * sa4.3 训练过程监控与调参经验训练过程中我习惯用TensorBoard或者YOLOv8自带的绘图功能看损失曲线。有一次发现训练损失正常下降但验证损失从一开始就很高排查后发现是验证集和训练集的类别分布差异太大。训练集里可回收物占60%验证集里只占30%模型在验证集上自然表现差。后来重新划分了数据集保证训练集和验证集的类别比例一致。学习率的调整也很关键。我一开始用固定学习率0.01训练到后期损失震荡得厉害。换成余弦退火后学习率从0.01逐渐降到0.0001训练稳定多了。另外warmup阶段也很重要前3个epoch用很小的学习率预热避免一开始就把预训练权重带偏。还有一个经验如果显存不够不要硬撑大batch size可以用梯度累积。比如实际batch size设为4累积4次梯度再更新一次参数等效于batch size 16。这样训练速度会慢一些但效果差不多。5. 模型评估与问题排查用数据说话5.1 评估指标解读与结果分析目标检测的评估指标主要有几个mAP50、mAP50-95、精确率、召回率、F1分数。mAP50是IoU阈值为0.5时的平均精度mAP50-95是IoU从0.5到0.95每隔0.05取一个阈值再平均后者更严格。我的基线YOLOv8n模型在测试集上的mAP50大概是0.82加了注意力机制和小目标检测层后提升到0.86Focal Loss再贡献了大概1个点最终mAP50在0.87左右。mAP50-95从0.58提升到0.63。这个提升幅度在工业界不算惊艳但对于课程设计或者入门项目来说已经够用了。分类别来看可回收物的AP最高因为样本多、特征明显。有害垃圾的AP最低主要是样本太少而且电池、灯管这些物体形态差异大。厨余垃圾和其他垃圾居中。类别基线AP50改进后AP50提升幅度可回收物0.890.920.03有害垃圾0.710.790.08厨余垃圾0.830.870.04其他垃圾0.850.880.035.2 常见问题速查与排查思路训练和部署过程中遇到的问题不少我整理了一个速查表方便快速定位。问题现象可能原因排查方法解决方案训练损失不下降学习率太小、数据标注错误检查标注文件、打印学习率调大学习率、重新检查标注验证损失远高于训练损失过拟合、数据分布不一致对比训练集和验证集分布增加数据增强、重新划分数据集某类别AP特别低样本太少、类别混淆看混淆矩阵、统计实例数过采样、合并易混淆类别推理速度慢模型太大、输入尺寸太大测推理时间、看模型参数量换nano模型、减小输入尺寸小目标漏检严重特征图分辨率不够可视化检测结果增加小目标检测层部署后精度下降量化损失、预处理不一致对比部署前后输出调整量化参数、统一预处理5.3 独家避坑技巧第一个坑标注文件格式。YOLOv8要求标注是txt格式每行是“类别id 中心x 中心y 宽 高”坐标都要归一化到0到1之间。我一开始用LabelImg导出的是VOC格式的xml转换脚本写错了一个地方导致所有框都偏了。后来写了个校验脚本随机抽几张图把框画出来看才发现问题。第二个坑图像尺寸。YOLOv8训练时会把图像缩放到指定尺寸但如果原始图像的长宽比差异太大缩放后物体会变形。我建议在数据预处理阶段就做一次letterbox缩放保持长宽比空白处填充灰色。这样训练和推理时的预处理一致避免精度损失。第三个坑类别id从0开始。YOLOv8的类别id是从0开始的如果你有4个类别id就是0、1、2、3。我见过有人从1开始编号结果训练时一直报错。这个细节很小但很容易忽略。提示训练前一定要用YOLOv8自带的验证命令跑一遍确认数据集加载没问题。命令是yolo detect train datayour_data.yaml modelyolov8n.pt epochs1跑一个epoch看看有没有报错。6. 部署落地从PyTorch到实际可用6.1 模型导出与格式转换训练完的PyTorch模型要部署到实际设备上通常需要转成ONNX格式。YOLOv8提供了导出命令一行代码搞定yolo export modelbest.pt formatonnx。导出的ONNX模型可以用ONNX Runtime推理也可以进一步转成TensorRT、RKNN等格式。转ONNX的时候要注意opset版本我一般用opset 12兼容性比较好。另外导出时最好加上simplifyTrue参数会对计算图做一些优化去掉冗余节点。如果部署到RK3588这类边缘设备还需要用RKNN Toolkit把ONNX转成RKNN格式。这个过程会做量化把FP32转成INT8模型体积缩小到原来的四分之一推理速度提升明显。但量化会带来精度损失一般掉1到2个点可以通过量化感知训练来缓解。6.2 推理代码实现与后处理推理代码的核心是加载模型、预处理图像、前向传播、后处理。预处理包括letterbox缩放、归一化、通道转换。后处理主要是NMS过滤掉重叠的检测框。import cv2 import numpy as np from ultralytics import YOLO model YOLO(best.onnx) def detect(image_path): img cv2.imread(image_path) results model(img, conf0.25, iou0.45) for r in results: boxes r.boxes for box in boxes: x1, y1, x2, y2 box.xyxy[0].cpu().numpy() cls int(box.cls[0]) conf float(box.conf[0]) label f{model.names[cls]} {conf:.2f} cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(img, label, (int(x1), int(y1)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) return img置信度阈值和NMS的IoU阈值是两个关键参数。置信度阈值设太低误检多设太高漏检多。我一般从0.25开始试根据实际效果调整。NMS的IoU阈值默认0.45如果同类物体挨得很近可以适当调高到0.5或0.6避免把相邻物体误删。6.3 边缘设备部署实战要点在RK3588上部署YOLOv8我踩过的坑主要有几个。第一RKNN Toolkit的版本要和板子上的NPU驱动版本匹配不然推理会报错。第二量化时校准数据集要选好最好从训练集里随机抽几百张覆盖各个类别和场景。第三输入图像的预处理要和训练时完全一致包括归一化参数、通道顺序差一点都会导致精度下降。推理速度方面RK3588的NPU跑YOLOv8n的INT8模型单张图大概20到30毫秒比CPU快很多。如果对帧率要求不高比如一秒处理几张图完全够用。还有一个细节边缘设备的内存有限加载模型时要注意内存占用。ONNX Runtime和RKNN Runtime的内存管理策略不同RKNN更省内存但灵活性差一些。如果模型不大两者差别不明显如果模型很大建议用RKNN。7. 这个项目还能怎么扩展垃圾分类识别这个框架其实可以迁移到很多类似场景。比如工业质检检测产品表面缺陷把缺陷分成划痕、凹坑、污渍几类技术路线几乎一样。再比如医疗影像识别X光片里的病灶只不过类别定义和数据集不同。如果想进一步提升精度可以尝试几个方向。一是换更大的模型YOLOv8m或者YOLOv8l精度会高一些但速度慢。二是用知识蒸馏用大模型教小模型让小模型学到更好的特征表示。三是引入半监督学习利用大量无标注数据减少标注成本。如果要做成实际产品还需要考虑用户交互。比如做一个微信小程序用户拍照上传后端推理返回结果。或者做成边缘设备放在垃圾桶旁边摄像头实时识别语音提示用户该怎么扔。这些工程上的事情比调模型参数复杂得多但也更有意思。我个人在实际操作中的体会是深度学习项目里数据质量的重要性怎么强调都不为过。模型结构、训练技巧这些网上教程一大堆照着做基本不会太差。但数据集这块每个项目都有自己的特殊性没有现成的答案只能自己一点点摸索。我花在数据上的时间大概占整个项目的六成以上但回头看这些时间花得值。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询