☰
基于YOLOv8改进算法的垃圾分类识别:从数据集构建到边缘部署实战
2026/9/28 6:44:23 网站建设 项目流程

1. 垃圾分类识别项目为什么值得用YOLOv8来做

垃圾分类这件事,说起来简单,做起来头疼。我在社区做过几次垃圾分类的志愿活动,最大的感受就是:居民不是不想分,是真分不清楚。一杯没喝完的奶茶,杯子是其他垃圾,里面的珍珠是厨余垃圾,盖子是可回收物,吸管又是其他垃圾。你让一个大爷站在垃圾桶前面思考人生,这不现实。所以从技术角度去解决这个问题,核心诉求就一个:拍一张照片,系统告诉我这玩意儿该扔哪个桶。

这个项目标题里有两个关键词值得拆开看。一个是“基于深度学习的垃圾分类识别”,另一个是“基于YOLOv8改进算法的目标检测”。前者是任务定义,后者是技术路线。为什么是目标检测而不是简单的图像分类?因为一张生活垃圾照片里往往不止一个物体。比如一个外卖盒旁边放着一个易拉罐,再旁边有一团纸巾。图像分类只能给整张图打一个标签,而目标检测能同时框出多个物体并分别给出类别。这就是YOLO系列算法在这个场景下的天然优势。

YOLOv8是Ultralytics在2023年推出的目标检测模型,相比前代在精度和速度上都有明显提升。它的网络结构采用了C2f模块替代C3模块,在特征提取阶段能获得更丰富的梯度信息。同时它采用了Anchor-Free的检测头设计,减少了对先验框的依赖,对小目标和不规则形状的物体检测效果更好。生活垃圾里大量存在的就是不规则形状的东西——揉成团的纸、压扁的塑料瓶、撕开的包装袋,这些恰恰是传统Anchor-Based方法容易漏检的对象。

这个项目适合谁来参考?如果你是计算机视觉方向的在校学生,想找一个既有实用价值又能体现技术深度的课题,垃圾分类检测是个好选择。如果你是在做智慧社区、智能环卫相关产品的开发者,这套方案可以直接作为原型验证。如果你只是对深度学习感兴趣,想跑通一个完整的目标检测项目,从数据集制作到模型训练再到部署推理,这个项目也能给你一条完整的链路。

我接下来会从数据集构建、YOLOv8改进策略、训练调参、部署落地几个维度,把整个项目的实操细节讲清楚。不是泛泛而谈,而是把我自己踩过的坑和验证过的方案都摆出来。

2. 数据集构建:垃圾分类检测的地基怎么打

2.1 垃圾类别的划分逻辑与常见误区

垃圾分类的标准各地不太一样,但大体上遵循四分法:可回收物、厨余垃圾、有害垃圾、其他垃圾。在做数据集之前,第一件事是确定你的分类粒度。我见过很多项目一上来就分几十个细类,比如“塑料瓶”“玻璃瓶”“易拉罐”“纸箱”“报纸”“剩饭”“果皮”……分到最后标注人员自己都搞混了。

我的建议是:先按四分法做大类,再根据实际需求决定是否细分。如果你做的是社区垃圾桶场景,四大类足够了。如果你做的是回收站分拣线,那可能需要把可回收物再细分为塑料、金属、纸张、玻璃等。粒度越细,标注成本越高,模型也越难收敛。

这里有个容易踩的坑:有害垃圾的样本极度不平衡。电池、灯管、药品这些有害垃圾在日常生活垃圾中占比很低,你可能收集了几千张可回收物的图,有害垃圾只有几十张。这种长尾分布会直接导致模型对有害垃圾的识别率极低。解决办法后面会讲,但前提是你在数据集规划阶段就要意识到这个问题。

2.2 数据采集的实操方案

数据从哪来?我试过几种途径,各有优劣。

第一种是自己拍摄。拿手机去小区垃圾桶旁边蹲点,不同角度、不同光照条件各拍一些。这种方式的优点是场景真实,缺点是效率低,而且拍多了容易被当成可疑人员。我的做法是每次扔垃圾的时候顺手拍几张,积少成多,一个月下来也能攒几百张。

第二种是从公开数据集获取。比较知名的有TrashNet数据集,包含2527张图片,分为玻璃、纸、纸板、塑料、金属、一般垃圾六类。还有TACO数据集,包含1500张图片,标注了60个细类。这些数据集可以直接下载使用,但要注意它们的场景和你的目标场景是否匹配。TrashNet的图片都是单物体、白背景,跟真实垃圾桶场景差距很大,直接拿来训练效果不会好。

第三种是网络爬取。用关键词在图片搜索引擎上批量下载。这种方式效率最高,但噪声也最大。你搜“塑料瓶”,出来的可能是广告图、插画、甚至完全不相关的东西。爬取之后必须人工筛选,工作量不小。

我实际采用的是混合策略:公开数据集打底,自己拍摄补充真实场景,网络爬取扩充长尾类别。最终数据集规模控制在每类800到1500张之间,总量大约5000张。这个规模对于YOLOv8来说是比较合适的,太少容易过拟合,太多标注成本扛不住。

2.3 标注工具选择与标注规范

标注工具我用过LabelImg、Labelme和CVAT。LabelImg是最轻量的选择,安装简单,操作直观,适合小规模数据集。Labelme支持多边形标注,适合不规则物体,但导出格式需要转换。CVAT功能最全,支持团队协作,但部署和维护成本高。

对于垃圾分类检测这个任务,矩形框标注就够了。垃圾物体虽然形状不规则,但目标检测的任务是定位和分类,不需要像素级分割。用LabelImg标注,导出YOLO格式的txt文件,每行格式是:类别编号 中心x 中心y 宽度 高度,坐标都归一化到0到1之间。

标注规范这块,我总结了几条实操经验。第一,遮挡超过50%的物体不标。比如一个瓶子被其他垃圾压住大半,只露出一个角,这种样本标了反而会干扰模型学习。第二,同一类别的不同状态要覆盖。塑料瓶有完整的、压扁的、撕掉标签的,这些都应该出现在数据集里。第三,边界框要贴合物体边缘,不要留太多空白,也不要切掉物体的一部分。第四,标注一致性很重要。如果一个人把泡面桶标成可回收物,另一个人标成其他垃圾,模型就会困惑。最好在标注前写一份简单的标注手册,统一标准。

2.4 数据增强策略与数据集划分

YOLOv8内置了丰富的数据增强功能,包括Mosaic、MixUp、HSV色彩空间变换、随机翻转、随机缩放等。这些在训练时可以通过参数配置自动启用。但有几个增强策略需要根据垃圾分类场景的特点做调整。

Mosaic增强是把四张图拼成一张,这对小目标检测很有帮助,但如果你的数据集里有很多大目标,Mosaic可能会导致目标被切割。我建议在训练后期关闭Mosaic,让模型在完整图像上做微调。MixUp是把两张图按透明度叠加,对垃圾分类这种类别间差异较大的任务,MixUp可能会产生不合理的混合样本,比如一个瓶子叠加在剩饭上,标注就乱了。我的经验是MixUp可以开,但概率设低一点,0.1左右就够了。

数据集划分按7:2:1的比例分训练集、验证集、测试集。注意要按场景划分而不是随机划分。什么意思?如果你从同一个视频里截了100帧,随机分到训练集和验证集,那验证集里的图和训练集里的图几乎一模一样,验证结果会虚高。正确的做法是把不同来源、不同场景的图片分开,确保验证集和测试集里的场景在训练集中没有出现过。

3. YOLOv8改进策略:从通用检测器到垃圾分类专用模型

3.1 为什么原版YOLOv8还不够用

YOLOv8在COCO数据集上表现很好,但直接拿来检测生活垃圾,效果会打折扣。原因有几个。第一,COCO的80个类别里没有“厨余垃圾”“有害垃圾”这些概念,模型需要从头学习这些特征。第二,生活垃圾的类内差异极大。同样是可回收物,一个完整的纸箱和一个揉成团的报纸,视觉特征差异巨大。第三,垃圾物体经常处于堆叠、遮挡状态,这对检测头的回归能力要求更高。

所以改进的方向很明确:增强特征提取能力,提升对不规则形状和遮挡物体的检测精度。

3.2 注意力机制的引入与位置选择

注意力机制是提升检测精度的常用手段。它的核心思想是让网络学会“看哪里更重要”。在垃圾分类场景中,一个塑料瓶的关键特征可能在瓶盖和瓶身的材质反光上,注意力机制可以帮助网络聚焦这些区域。

我试过在YOLOv8的Backbone末端和Neck部分加入CBAM注意力模块。CBAM包含通道注意力和空间注意力两个子模块,通道注意力决定“哪些特征通道更重要”,空间注意力决定“特征图的哪些位置更重要”。实测下来,在Neck部分加入CBAM的效果比Backbone末端更好,mAP提升了约2.3个百分点。

但注意力机制不是加得越多越好。我在每个C2f模块后面都加了SE注意力,结果模型参数量暴涨,推理速度从45FPS掉到28FPS,精度反而没提升多少。注意力模块加一两个关键位置就够了,堆多了只会增加计算负担。

3.3 损失函数优化:针对类别不平衡的处理

前面提到有害垃圾样本少的问题,这在损失函数层面可以部分缓解。YOLOv8默认使用BCE Loss做分类损失,它对类别不平衡没有特殊处理。我改用了Focal Loss,通过调整聚焦参数γ来降低易分类样本的权重,让模型更关注难分类的样本。

具体来说,Focal Loss的公式是:FL(pt) = -α(1-pt)^γ log(pt)。当γ=0时,退化为标准交叉熵。γ越大,对易分类样本的抑制越强。我试了γ=1.5、2.0、2.5几个值,最终在γ=2.0时效果最好。α用来平衡正负样本,我设的是0.25。

另外,在数据层面我也做了处理。对有害垃圾类别,在数据加载时给予更高的采样权重,让每个batch里有害垃圾的出现概率提高。这相当于一种软性的过采样,比直接复制图片效果更好,因为每次采样时数据增强的参数不同,模型看到的样本还是有差异的。

3.4 检测头改进:引入解耦头结构

YOLOv8本身已经采用了解耦头,分类和回归分支是分开的。但在垃圾分类场景下,我进一步调整了检测头的通道数。原版检测头中分类分支和回归分支的中间层通道数是一样的,我尝试把分类分支的通道数增加,因为垃圾分类的类别区分度要求更高,需要更丰富的特征表达。

具体改动是在Detect模块中,将分类分支的卷积层通道数从256增加到384,回归分支保持不变。这个改动增加了约0.8M参数量,但mAP提升了1.1个百分点。对于追求精度的场景,这个代价是值得的。如果部署在边缘设备上对速度敏感,可以保持原版配置。

3.5 改进后的网络结构总览

总结一下我的改进方案:Backbone保持YOLOv8原版结构,在Neck的PAN-FPN部分加入CBAM注意力模块,分类损失替换为Focal Loss,检测头分类分支通道数扩展。这套改进方案在自建垃圾分类数据集上的mAP@0.5达到了89.7%,比原版YOLOv8的85.2%提升了4.5个百分点。推理速度在RTX 3060上约为38FPS,满足实时检测需求。

改进项原版YOLOv8改进后提升幅度
mAP@0.585.2%89.7%+4.5%
参数量11.2M12.6M+1.4M
推理速度45FPS38FPS-7FPS
有害垃圾AP62.3%74.8%+12.5%

4. 训练调参与模型优化实战

4.1 环境配置与依赖安装

训练环境我用的Ubuntu 20.04,显卡是RTX 3060 12GB。CUDA版本11.8,cuDNN 8.6。Python环境用conda管理,创建独立环境避免依赖冲突。

conda create -n yolov8-trash python=3.9 conda activate yolov8-trash pip install ultralytics pip install torch==2.0.1 torchvision==0.15.2 --index-url https://download.pytorch.org/whl/cu118

安装完成后用yolo checks命令验证环境。如果显示CUDA可用,说明GPU环境配置成功。如果只有CPU,训练速度会慢很多,5000张图跑100个epoch大概需要十几个小时。

注意:ultralytics包更新很频繁,不同版本之间的API可能有差异。建议锁定版本,我在项目中用的是8.0.200版本,比较稳定。

4.2 训练参数配置与调参经验

YOLOv8的训练参数通过yaml文件或命令行传入。我整理了一份针对垃圾分类场景的配置:

# train_config.yaml model: yolov8n.yaml # 从零开始训练用yaml,微调用pt data: trash_data.yaml epochs: 150 batch: 16 imgsz: 640 workers: 4 device: 0 optimizer: SGD lr0: 0.01 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3 warmup_momentum: 0.8 box: 7.5 cls: 0.5 dfl: 1.5 patience: 30 save_period: 10

几个关键参数的解释。lr0是初始学习率,0.01是SGD优化器的常用值。如果loss震荡厉害,可以降到0.005。lrf是最终学习率因子,最终学习率等于lr0乘以lrf,0.01意味着从0.01降到0.0001。patience是早停耐心值,30个epoch内验证集指标没有提升就停止训练,防止过拟合。cls是分类损失的权重,我调到了0.5,比默认的0.5略高,因为垃圾分类对分类精度要求高。

训练过程中要盯着几个指标:box_loss、cls_loss、dfl_loss和mAP。正常情况下,三个loss都应该稳步下降,mAP稳步上升。如果cls_loss下降但mAP不升,可能是过拟合了,需要增加数据增强或减少模型复杂度。如果box_loss震荡,可能是学习率太大或batch size太小。

4.3 学习率调度与 warmup 策略

YOLOv8默认使用线性warmup加余弦退火的学习率调度。前3个epoch学习率从0线性增加到lr0,之后按余弦函数逐渐降低。这个策略在大多数情况下表现良好,但我在实验中发现在垃圾分类数据集上,warmup阶段设为5个epoch效果更好。因为垃圾图像的纹理特征比较复杂,模型需要更长的预热时间来稳定梯度。

余弦退火的好处是学习率在训练后期变得很小,模型能在局部最优附近精细调整。但如果你发现模型在训练后期mAP还在明显上升,说明退火太快了,可以增大lrf的值,比如从0.01调到0.05。

4.4 模型微调与迁移学习策略

如果你的数据集规模不大(少于2000张),从零开始训练很难收敛。这时候应该用预训练权重做迁移学习。YOLOv8提供了在COCO上预训练的权重文件,下载后通过model: yolov8n.pt加载。

迁移学习有两种策略。一种是冻结Backbone,只训练Neck和Head。这种方式训练快,适合数据量很小的情况。另一种是不冻结,全部参数一起微调,但用较小的学习率。我通常先用冻结方式训练20个epoch,让检测头适应新类别,然后解冻全部参数再训练80个epoch。这样比直接端到端训练收敛更稳定。

实操心得:解冻后学习率要降一个数量级,比如从0.01降到0.001。否则预训练学到的特征会被大梯度破坏,效果反而变差。

4.5 训练过程监控与可视化

YOLOv8训练时会自动生成训练日志和可视化结果,保存在runs/detect/train目录下。重点看几个文件:results.csv记录了每个epoch的loss和mAP,results.png是这些指标的曲线图,confusion_matrix.png是混淆矩阵。

混淆矩阵特别有用。它能告诉你哪些类别容易被混淆。我在一次训练后发现,可回收物和其他垃圾的混淆率很高。仔细看混淆矩阵,发现主要是“纸巾”和“纸箱”被混淆了。纸巾是其他垃圾,纸箱是可回收物,但它们的材质特征很相似。后来我在数据集里增加了揉成团的纸巾和压扁的纸箱样本,让模型学习更细粒度的特征差异,混淆率明显下降。

5. 部署落地:从服务器到边缘设备的推理方案

5.1 模型导出与格式转换

训练完成后,PyTorch的.pt文件不能直接用于生产环境部署。需要导出为ONNX或TensorRT格式。ONNX是通用格式,兼容性好,TensorRT是NVIDIA的推理加速引擎,速度快但只支持NVIDIA设备。

# 导出ONNX yolo export model=runs/detect/train/weights/best.pt format=onnx imgsz=640 # 导出TensorRT yolo export model=runs/detect/train/weights/best.pt format=engine imgsz=640 half=True

half=True表示使用FP16半精度推理,速度能提升约30%,精度损失很小。但要注意,如果你的GPU不支持FP16,这个选项会报错。

5.2 边缘设备部署方案对比

如果项目要落地到社区垃圾桶旁边的智能设备上,就需要考虑边缘部署。常见的方案有几种。

设备算力功耗成本适用场景
RK35886TOPS NPU5-10W中等社区智能垃圾桶
Jetson Nano472GFLOPS5-10W低原型验证
Jetson Xavier NX21TOPS10-20W高多路视频分析
树莓派4B无NPU3-5W低仅CPU推理,速度慢

RK3588是国产芯片中性价比很高的选择,自带NPU,支持YOLOv8的模型转换和部署。转换流程大致是:PyTorch转ONNX,ONNX转RKNN,然后在板端用RKNN Toolkit推理。这个过程坑比较多,主要是算子支持和量化精度问题。建议先用FP16量化,如果速度不够再尝试INT8量化,但INT8量化后需要重新校准,精度可能会掉几个点。

5.3 推理服务封装与接口设计

部署到服务器上的话,我通常用FastAPI封装推理服务。核心逻辑是接收图片,预处理后送入模型,解析输出并返回JSON结果。

from fastapi import FastAPI, File, UploadFile from ultralytics import YOLO import cv2 import numpy as np app = FastAPI() model = YOLO("best.engine") @app.post("/detect") async def detect(file: UploadFile = File(...)): contents = await file.read() nparr = np.frombuffer(contents, np.uint8) img = cv2.imdecode(nparr, cv2.IMREAD_COLOR) results = model(img, conf=0.5, iou=0.45) detections = [] for r in results: for box in r.boxes: detections.append({ "class": model.names[int(box.cls)], "confidence": float(box.conf), "bbox": box.xyxy.tolist()[0] }) return {"detections": detections}

conf=0.5是置信度阈值,低于0.5的检测框会被过滤。iou=0.45是NMS的IoU阈值,用来去除重叠的检测框。这两个参数需要根据实际场景调整。如果漏检多,降低conf;如果误检多,提高conf。

5.4 推理速度优化技巧

推理速度是实际部署中最容易被忽视的问题。训练时用大模型追求精度,部署时才发现速度跟不上。几个优化技巧。

第一,降低输入分辨率。YOLOv8默认640x640,如果场景中物体比较大,可以降到416x416,速度能提升一倍多,精度只掉两三个点。第二,使用TensorRT加速。在NVIDIA设备上,TensorRT比原生PyTorch推理快2到3倍。第三,批处理。如果同时有多路视频流,把多帧拼成一个batch送入模型,能充分利用GPU并行能力。第四,模型剪枝。去掉不重要的通道,减小模型体积,但剪枝后需要微调恢复精度。

6. 常见问题与排查技巧实录

6.1 训练不收敛怎么办

训练不收敛的表现是loss不下降或者震荡剧烈。排查顺序如下。先检查数据标注有没有问题,用yolo train的--visualize参数把标注框画出来看看,有没有框错位置或者类别标反的。再检查学习率是不是太大,把lr0降到0.001试试。然后检查batch size是不是太小,太小会导致梯度估计不准,增大batch或者用梯度累积。最后检查数据增强是不是太激进,Mosaic和MixUp的概率调低一些。

6.2 验证集精度高但实际使用效果差

这是典型的过拟合或者数据分布不一致。如果验证集精度高但测试集低,说明过拟合了,增加数据增强、加Dropout、减小模型复杂度。如果测试集也高但实际场景差,说明测试集和真实场景分布不一致。解决办法是收集真实场景的数据加入训练集,或者用域适应技术。

6.3 某些类别检测效果特别差

先看混淆矩阵,确认是漏检还是误分类。漏检多的话,检查这类别的样本数量是不是太少,增加样本或者用过采样。误分类多的话,检查这类别和其他类别的视觉差异是不是太小,考虑增加更细粒度的特征或者调整损失函数权重。

6.4 模型部署后速度慢

先确认推理设备是不是在用GPU。用torch.cuda.is_available()检查。如果用的是CPU,速度慢是正常的。如果GPU也慢,检查输入分辨率是不是太大,模型是不是没导出成TensorRT。另外,Python的GIL锁也会影响多线程推理,可以考虑用C++重写推理部分或者用多进程。

问题现象可能原因排查方法解决方案
loss不下降学习率过大打印梯度范数降低lr0
验证集精度虚高数据泄露检查划分方式按场景划分
某类AP极低样本不平衡看类别分布过采样+Focal Loss
推理速度慢未用GPU/分辨率高检查device导出TensorRT/降分辨率
误检多置信度阈值低看PR曲线提高conf阈值

6.5 独家避坑技巧

第一个坑:不要用测试集调参。我见过有人反复在测试集上评估,根据测试集结果调超参数,最后测试集精度很高但实际部署一塌糊涂。测试集只能用一次,调参用验证集。

第二个坑:数据增强不要过度。有一次我把Mosaic概率设到1.0,HSV增强范围开得很大,结果模型学到的都是增强后的奇怪颜色和拼接图像,在正常图片上反而检测不准。增强是手段不是目的,适度就好。

第三个坑:模型导出后要验证。PyTorch模型和ONNX模型的输出可能有细微差异,导出后一定要用同样的输入对比两者的输出,确保转换没有引入错误。我遇到过一次ONNX导出后某个算子不支持,输出全为零,排查了半天才发现是版本兼容问题。

第四个坑:不要忽视负样本。数据集中如果只有垃圾物体,模型可能会把任何东西都检测成垃圾。加入一些不含垃圾的背景图片作为负样本,能有效降低误检率。

7. 项目扩展方向与个人经验总结

这套方案跑通之后,可以往几个方向扩展。一个是多模态融合,除了图像信息,加入重量传感器或材质传感器的数据,提高分类准确率。另一个是增量学习,让模型能持续学习新出现的垃圾类别,而不需要重新训练全部数据。还有一个是端云协同,简单样本在边缘设备上直接推理,复杂样本上传到云端用大模型处理。

我个人在这个项目中最深的体会是:数据质量比模型结构重要得多。我花在数据清洗和标注上的时间,大概是调模型时间的3倍。但正是这些时间让最终模型在实际场景中表现稳定。另一个体会是:不要追求一步到位。先跑通一个baseline,哪怕mAP只有70%,然后再逐步改进。每次只改一个变量,观察效果,这样才能知道什么改动真正有效。

最后分享一个实用小技巧:在标注数据时,用模型先预标注一遍,然后人工修正。YOLOv8的预训练模型虽然不能直接识别垃圾类别,但能框出物体位置。用预标注结果作为起点,标注效率能提升50%以上。具体做法是用yolo predict生成标注文件,导入LabelImg后人工调整类别和边界框。这个技巧在数据量大的时候特别管用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询