ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于YOLOv8改进算法的垃圾分类识别:从数据集构建到边缘部署实战

基于YOLOv8改进算法的垃圾分类识别:从数据集构建到边缘部署实战 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检测头分类分支通道数扩展。这套改进方案在自建垃圾分类数据集上的mAP0.5达到了89.7%比原版YOLOv8的85.2%提升了4.5个百分点。推理速度在RTX 3060上约为38FPS满足实时检测需求。改进项原版YOLOv8改进后提升幅度mAP0.585.2%89.7%4.5%参数量11.2M12.6M1.4M推理速度45FPS38FPS-7FPS有害垃圾AP62.3%74.8%12.5%4. 训练调参与模型优化实战4.1 环境配置与依赖安装训练环境我用的Ubuntu 20.04显卡是RTX 3060 12GB。CUDA版本11.8cuDNN 8.6。Python环境用conda管理创建独立环境避免依赖冲突。conda create -n yolov8-trash python3.9 conda activate yolov8-trash pip install ultralytics pip install torch2.0.1 torchvision0.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乘以lrf0.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和mAPresults.png是这些指标的曲线图confusion_matrix.png是混淆矩阵。混淆矩阵特别有用。它能告诉你哪些类别容易被混淆。我在一次训练后发现可回收物和其他垃圾的混淆率很高。仔细看混淆矩阵发现主要是“纸巾”和“纸箱”被混淆了。纸巾是其他垃圾纸箱是可回收物但它们的材质特征很相似。后来我在数据集里增加了揉成团的纸巾和压扁的纸箱样本让模型学习更细粒度的特征差异混淆率明显下降。5. 部署落地从服务器到边缘设备的推理方案5.1 模型导出与格式转换训练完成后PyTorch的.pt文件不能直接用于生产环境部署。需要导出为ONNX或TensorRT格式。ONNX是通用格式兼容性好TensorRT是NVIDIA的推理加速引擎速度快但只支持NVIDIA设备。# 导出ONNX yolo export modelruns/detect/train/weights/best.pt formatonnx imgsz640 # 导出TensorRT yolo export modelruns/detect/train/weights/best.pt formatengine imgsz640 halfTruehalfTrue表示使用FP16半精度推理速度能提升约30%精度损失很小。但要注意如果你的GPU不支持FP16这个选项会报错。5.2 边缘设备部署方案对比如果项目要落地到社区垃圾桶旁边的智能设备上就需要考虑边缘部署。常见的方案有几种。设备算力功耗成本适用场景RK35886TOPS NPU5-10W中等社区智能垃圾桶Jetson Nano472GFLOPS5-10W低原型验证Jetson Xavier NX21TOPS10-20W高多路视频分析树莓派4B无NPU3-5W低仅CPU推理速度慢RK3588是国产芯片中性价比很高的选择自带NPU支持YOLOv8的模型转换和部署。转换流程大致是PyTorch转ONNXONNX转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, conf0.5, iou0.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}conf0.5是置信度阈值低于0.5的检测框会被过滤。iou0.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.0HSV增强范围开得很大结果模型学到的都是增强后的奇怪颜色和拼接图像在正常图片上反而检测不准。增强是手段不是目的适度就好。第三个坑模型导出后要验证。PyTorch模型和ONNX模型的输出可能有细微差异导出后一定要用同样的输入对比两者的输出确保转换没有引入错误。我遇到过一次ONNX导出后某个算子不支持输出全为零排查了半天才发现是版本兼容问题。第四个坑不要忽视负样本。数据集中如果只有垃圾物体模型可能会把任何东西都检测成垃圾。加入一些不含垃圾的背景图片作为负样本能有效降低误检率。7. 项目扩展方向与个人经验总结这套方案跑通之后可以往几个方向扩展。一个是多模态融合除了图像信息加入重量传感器或材质传感器的数据提高分类准确率。另一个是增量学习让模型能持续学习新出现的垃圾类别而不需要重新训练全部数据。还有一个是端云协同简单样本在边缘设备上直接推理复杂样本上传到云端用大模型处理。我个人在这个项目中最深的体会是数据质量比模型结构重要得多。我花在数据清洗和标注上的时间大概是调模型时间的3倍。但正是这些时间让最终模型在实际场景中表现稳定。另一个体会是不要追求一步到位。先跑通一个baseline哪怕mAP只有70%然后再逐步改进。每次只改一个变量观察效果这样才能知道什么改动真正有效。最后分享一个实用小技巧在标注数据时用模型先预标注一遍然后人工修正。YOLOv8的预训练模型虽然不能直接识别垃圾类别但能框出物体位置。用预标注结果作为起点标注效率能提升50%以上。具体做法是用yolo predict生成标注文件导入LabelImg后人工调整类别和边界框。这个技巧在数据量大的时候特别管用。
返回列表