资讯中心

基于YOLOv8改进的生活垃圾图像识别系统:从数据集到部署全流程

📅 2026/9/28 6:43:05
基于YOLOv8改进的生活垃圾图像识别系统:从数据集到部署全流程
垃圾分类这件事说起来简单做起来是真磨人。我在社区做过一次调研发现超过七成的居民其实有分类意识但站在垃圾桶前面还是会犹豫——手里拿着一个沾了油渍的外卖盒到底是可回收还是其他垃圾这种犹豫直接导致分类准确率上不去。人工分拣成本高、效率低而且分拣员长期在恶劣环境下工作健康风险不小。这就是为什么我决定动手做一套基于深度学习的生活垃圾图像识别系统核心用的是YOLOv8目标检测框架并针对垃圾图像的特点做了几处关键改进。整套系统从数据集构建、模型训练、改进策略到最终部署推理我都跑通了实测下来在自建数据集上mAP0.5能稳定在92%以上。这篇文章我会把整个设计与实现过程拆开讲清楚包括我踩过的坑、参数怎么调、改进为什么有效适合有一定Python基础、想做一个完整目标检测项目的朋友参考也适合正在做垃圾分类相关课题的同学直接抄作业。1. 为什么垃圾分类场景不能直接套用通用检测模型1.1 垃圾图像和常规目标检测任务的本质差异很多人做目标检测项目第一反应是拿COCO或者VOC数据集上预训练好的模型直接fine-tune。这个思路在行人检测、车辆检测上没问题但放到垃圾图像上就会出问题。原因在于垃圾图像有几个非常特殊的性质。第一是类内差异极大。同样是塑料瓶有透明的矿泉水瓶、有绿色的雪碧瓶、有捏扁的、有带标签的、有装了一半液体的。这些在像素层面的分布差异比猫和狗之间的差异还大。通用模型的特征提取器是在自然图像上训练的它学到的纹理和边缘模式跟垃圾图像不匹配。第二是类间差异极小。一次性纸杯和塑料杯在外观上非常接近陶瓷碎片和玻璃碎片在颜色和反光特性上也很难区分。更麻烦的是很多垃圾是复合材质——比如纸盒内衬锡箔的牛奶盒你说它是可回收还是其他垃圾这种边界模糊的样本会让模型在训练时产生梯度冲突。第三是遮挡和形变严重。垃圾在垃圾桶里是堆叠的一个瓶子可能只露出一半一个纸团可能完全变形。通用目标检测模型对这种非刚性形变的鲁棒性并不好。我在最初用YOLOv8n的官方权重直接推理垃圾图像时发现它对瓶子这个类别的召回率只有60%出头大量被遮挡的瓶子直接漏检。这不是模型能力不行而是特征分布不匹配。1.2 垃圾分类的类别体系怎么定才合理类别体系的设计直接决定了项目能不能落地。我见过很多项目直接照搬可回收物、有害垃圾、厨余垃圾、其他垃圾四大类然后让模型去分类。这个做法在检测任务里是有问题的因为四大类太抽象了模型需要先识别出具体物体瓶子、纸箱、电池再映射到类别。两步走不如一步到位。我的做法是采用两级类别体系检测层识别具体物体类别映射层负责归入四大类。检测层我最终定了20个细分类别覆盖了社区场景下90%以上的常见垃圾检测类别映射大类样本量标注难度塑料瓶可回收物1200低易拉罐可回收物980低纸箱可回收物850低报纸可回收物760中玻璃瓶可回收物690中金属罐可回收物620低旧衣服可回收物540中充电电池有害垃圾480低灯管有害垃圾420中药品包装有害垃圾390高油漆桶有害垃圾310中菜叶厨余垃圾1100低果皮厨余垃圾1050低剩饭厨余垃圾890中蛋壳厨余垃圾720低茶渣厨余垃圾650低烟头其他垃圾830低陶瓷碎片其他垃圾560高一次性餐具其他垃圾940中卫生纸其他垃圾780低这个类别体系的好处是模型学的是具体物体的视觉特征这些特征是可学习的、有区分度的而映射到四大类只是一个查表操作零成本。而且当政策调整时比如某个城市把某种垃圾重新归类只需要改映射表不用重新训练模型。1.3 YOLOv8相比前代在垃圾检测上的实际优势我选YOLOv8不是因为它最新而是因为它在几个关键点上确实适合这个场景。Anchor-Free架构是最大的优势。YOLOv5及之前用的是Anchor-Based需要针对数据集聚类生成先验框。垃圾的形状太不规则了——一个捏扁的易拉罐可能是任意长宽比Anchor机制在这种场景下反而成了负担。YOLOv8的Anchor-Free设计直接预测目标中心点和宽高省去了聚类调参的麻烦对小目标和极端长宽比目标的适应性更好。C2f模块替代了C3模块梯度分流更充分。垃圾图像里很多目标纹理复杂比如报纸上的文字、包装袋上的图案C2f的多分支结构能提取更丰富的特征。解耦头把分类和回归分支分开了。垃圾检测里分类和定位的关注点差异很大——分类关注材质和纹理定位关注边缘和轮廓。解耦之后两个任务互不干扰实测比耦合头在垃圾数据集上mAP高了约2.3个百分点。Task-Aligned Assigner正样本分配策略对遮挡场景更友好。它根据分类得分和定位精度的联合指标来分配正样本而不是单纯看IoU。垃圾堆叠场景下被遮挡目标的IoU可能很低但Task-Aligned Assigner仍然能给它分配足够的正样本召回率明显提升。2. 数据集构建从零到可训练的真实操作路径2.1 数据采集的渠道和避坑要点数据集是目标检测项目的命脉。我见过太多人在这步偷懒直接用网上的公开数据集结果训练出来的模型在真实场景下完全不能用。公开数据集的问题在于拍摄角度单一、背景干净、光照均匀跟真实垃圾桶场景差距太大。我的数据来源分三块第一块是自采。我跑了周边五个小区和三个商圈的垃圾投放点用手机拍了大约3000张原始图像。拍摄时有意覆盖不同时段早中晚、不同天气晴天阴天雨天、不同角度俯拍、平拍、斜拍。这里有个经验不要只拍单个垃圾要拍垃圾在垃圾桶里堆叠的真实状态这才是模型部署后面对的分布。第二块是公开数据集补充。我用了TrashNet和TACO的部分数据但只取那些背景复杂的样本背景干净的直接剔除。TrashNet大概有2500张筛选后能用的大约1200张。第三块是数据增强生成。用Albumentations做了离线增强包括随机裁剪、旋转、色彩抖动、高斯噪声、运动模糊。增强倍数控制在3倍左右再多容易过拟合增强模式。采集阶段最大的坑是隐私问题。垃圾投放点经常有人经过拍摄时要注意避开人脸和车牌。我的做法是拍摄后统一用检测模型把人脸区域模糊掉虽然增加了工作量但这是必须做的。2.2 标注规范LabelImg和Labelme怎么选标注工具我两个都用了最后主力用LabelImg原因是它直接输出YOLO格式的txt文件省去了格式转换步骤。Labelme输出的是JSON需要额外写脚本转YOLO格式多一道工序就多一个出错点。标注规范我定了三条硬规则遮挡超过70%的目标不标。这种样本标了也是噪声模型学不到有效特征。堆叠目标逐个标。哪怕只露出一个角只要能判断类别就单独标一个框不要合并成一个大框。边界框紧贴目标边缘不要留太多背景。垃圾检测里背景干扰很大框太松会让模型学到背景特征。标注一致性是个大问题。我一开始自己标了500张后来找了两个同学帮忙结果发现三个人对一次性餐具的边界理解不一致——有人把餐盒和盖子标成一个框有人分开标。后来我写了一份标注手册配了20张示例图明确每种情况的标法一致性才上来。提示标注完成后一定要做一次交叉验证。随机抽100张让另一个人重新标计算IoU一致性。如果平均IoU低于0.85说明标注规范有问题需要重新对齐。2.3 数据集划分与类别平衡处理划分比例我用的是7:2:1训练集70%、验证集20%、测试集10%。这里有个细节划分时要按场景分层抽样不能随机分。因为如果训练集里全是小区场景验证集里全是商圈场景验证指标会虚低误导调参方向。类别不平衡是垃圾数据集的固有问题。菜叶、果皮这种样本很容易采到上千张而灯管、油漆桶这种有害垃圾很难找到。我的处理策略是过采样焦点损失组合对样本量少于500的类别在训练时通过WeightedRandomSampler提高采样权重权重设为该类样本数的倒数。损失函数用YOLOv8默认的BCEWithLogitsLoss但我把困难样本的权重调高了。具体做法是在训练几个epoch后统计每个类别的AP对AP低于0.5的类别在其正样本的loss上乘1.5倍系数。这套组合下来最少样本的油漆桶类别AP从最初的0.41提升到了0.78效果很明显。3. 针对垃圾图像的YOLOv8改进策略3.1 注意力机制嵌入为什么选CBAM而不是SE垃圾图像的核心难点是材质区分。塑料和玻璃在形状上可能很像但反光特性不同纸和布在颜色上可能接近但纹理不同。这些差异需要模型关注通道维度和空间维度的细粒度特征。我对比了SE、ECA、CBAM三种注意力机制在垃圾数据集上的表现注意力类型mAP0.5参数量增加推理耗时增加无89.200SE90.10.3M2msECA90.40.01M1msCBAM91.60.5M4msCBAM效果最好原因是它同时做了通道注意力和空间注意力。通道注意力负责看什么特征比如反光特性空间注意力负责看哪里比如瓶口区域。垃圾图像里这两个维度都很关键。嵌入位置我试了三种Backbone末端、Neck的每个C2f之后、检测头之前。最终选的是在Neck的P3和P4特征层后各加一个CBAM。P3负责小目标烟头、瓶盖P4负责中等目标瓶子、罐子这两个尺度是垃圾检测的主力。P5层加CBAM反而会引入噪声因为大目标在垃圾场景里很少。代码实现上我是在ultralytics的nn/modules里新增了一个CBAM类然后在yaml配置里插入。注意CBAM的通道注意力模块里MLP的缩减比我设的是16设8会过拟合设32效果下降。3.2 小目标检测头增加P2层的取舍烟头、瓶盖、电池这类小目标在垃圾场景里占比很高但原始YOLOv8的最小检测尺度是P3stride8对于小于16x16像素的目标检测效果很差。我统计了一下测试集里大约18%的目标面积小于32x32像素。增加P2检测头stride4理论上能提升小目标检测但代价是计算量大幅增加。我做了对比实验不加P2mAP0.5为91.6小目标AP为72.3推理速度45FPSRTX 3060加P2mAP0.5为92.8小目标AP为81.5推理速度31FPS小目标AP提升了9.2个百分点但速度掉了30%。这个取舍要看部署场景。如果是服务端部署加P2没问题如果要在边缘设备上跑就得慎重。我最终的方案是加P2但做通道裁剪。P2层的通道数从原来的64降到32这样速度回到38FPS小目标AP仍有79.8。具体操作是在yaml里把P2分支的C2f的output channels减半。3.3 损失函数优化CIoU替换为WIoU的实测对比YOLOv8默认用的是CIoU损失。CIoU考虑了重叠面积、中心点距离和长宽比在常规目标上表现很好。但垃圾检测里有个特殊问题低质量样本的梯度干扰。什么是低质量样本就是那些标注框和预测框IoU很低、但确实包含目标的样本。比如一个被压扁的纸箱标注框是紧贴可见部分的但模型预测的框可能偏大或偏小。CIoU对这类样本会给出很大的梯度导致模型在训练后期震荡。WIoUWise-IoU的核心思想是动态调整样本权重。它对高质量样本给予正常梯度对低质量样本降低梯度权重避免它们主导训练方向。我换成WIoU v3之后训练曲线明显更平滑最终mAP提升了1.4个百分点。具体实现是在loss.py里把bbox_loss的计算替换掉。WIoU v3有个超参数beta控制异常值的敏感度我设的是1.5设1.0效果不明显设2.0会过度抑制低质量样本导致召回率下降。3.4 数据增强策略的针对性调整YOLOv8默认的增强包括Mosaic、MixUp、HSV抖动、随机翻转等。这些在通用场景下没问题但垃圾场景需要针对性调整。Mosaic我保留了但把概率从1.0降到0.7。Mosaic把四张图拼成一张能增加小目标和上下文多样性但垃圾图像里很多目标本身就有遮挡Mosaic叠加后遮挡更严重反而有害。MixUp我关掉了。MixUp把两张图按透明度叠加在垃圾场景下会产生大量半透明垃圾的伪样本模型会学到错误的纹理特征。HSV抖动我加强了。垃圾图像的光照条件差异极大有的在室内灯光下有的在室外强光下。我把HSV的H增益从0.015提到0.03S和V增益从0.7提到0.9让模型对光照变化更鲁棒。新增了随机阴影增强。用Albumentations的RandomShadow模拟垃圾被其他物体遮挡阳光的情况。这个增强让模型在阴影场景下的召回率提升了约5个百分点。4. 训练调参与模型收敛的实战记录4.1 超参数配置的完整清单和调整逻辑我的训练配置基于YOLOv8m中等规模因为nano版精度不够large版推理太慢。以下是关键超参数和我的调整理由# 训练配置 epochs: 300 batch: 16 imgsz: 640 optimizer: AdamW lr0: 0.001 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 5 warmup_momentum: 0.8 box: 7.5 cls: 0.5 dfl: 1.5几个关键点的解释优化器选AdamW而不是SGD。SGD在垃圾数据集上收敛太慢而且对学习率非常敏感。AdamW的自适应学习率让前期收敛快很多配合weight_decay做正则化过拟合风险也可控。lr0设0.001而不是默认的0.01。垃圾数据集只有一万多张太大学习率会导致早期震荡。0.001配合余弦退火训练曲线很稳。box损失权重设7.5。默认是7.5我没改。但cls权重我从默认的0.5降到了0.5其实没变因为类别不平衡已经通过采样处理了不需要额外加权。dfl权重从1.5保持默认。warmup_epochs设5。前5个epoch用线性预热学习率从0慢慢升到0.001。这个对AdamW尤其重要能避免初期梯度爆炸。4.2 训练过程中的Loss曲线解读与异常处理训练到第80个epoch左右我遇到了一个典型问题box loss持续下降但cls loss震荡。这说明定位在改善但分类不稳定。排查过程是这样的先看混淆矩阵发现塑料瓶和玻璃瓶之间互相误判严重。再可视化特征图发现两个类别的特征在深层几乎重叠。根因是这两个类别在训练集里的样本外观太像——都是透明圆柱体。解决方案有两个方向一是增加区分性样本我补采了200张带明显标签的塑料瓶和带颜色玻璃瓶二是在分类损失里引入类间margin我参考了ArcFace的思路在分类头后面加了一个小的margin惩罚让不同类别的特征向量在角度上拉开距离。第二个方案实现复杂我最终用的是第一个方案加简单的标签平滑label smoothing0.1cls loss的震荡幅度明显减小。另一个异常是第150epoch后验证集mAP停滞。这是典型的学习率过大导致无法进入局部最优。我把余弦退火的最终学习率从0.0001降到0.00001又跑了50个epochmAP从91.2提升到92.1。4.3 模型选择在精度和速度之间找平衡点我训练了YOLOv8n、s、m、l四个版本在测试集上的表现如下模型mAP0.5mAP0.5:0.95参数量推理速度(FPS)模型大小YOLOv8n87.362.13.2M986.2MBYOLOv8s90.566.811.2M7221.5MBYOLOv8m92.870.325.9M4549.7MBYOLOv8l93.171.043.7M2883.7MB从m到lmAP只提升了0.3但速度掉了近40%。这个边际收益太低所以我最终选YOLOv8m作为主力模型。如果部署到边缘设备我会用YOLOv8s加P2检测头mAP能到91.2左右速度还有55FPS。还有一个细节模型融合。我把YOLOv8m和YOLOv8s的预测结果做了WBFWeighted Boxes FusionmAP提升到93.4但推理时间翻倍。这个方案适合对精度要求极高的服务端场景实时场景不推荐。5. 从训练完成到实际部署的完整链路5.1 模型导出与推理加速的实操细节训练完的.pt文件不能直接用于生产需要导出成推理格式。我对比了几种格式导出格式推理速度(FPS)精度损失部署便利性PyTorch .pt450高ONNX68-0.1高TensorRT FP16135-0.3中TensorRT INT8210-1.8低OpenVINO82-0.2中ONNX是性价比最高的选择。导出命令很简单yolo export modelbest.pt formatonnx opset12 simplifyTruesimplifyTrue会调用onnx-simplifier做图优化能去掉一些冗余算子推理速度提升约10%。TensorRT FP16适合NVIDIA显卡部署速度提升明显精度损失可接受。但导出时要注意TensorRT对动态shape支持不好最好固定输入尺寸为640x640。INT8量化我试了但没采用。精度掉了1.8个百分点对于垃圾分类这种对误判容忍度低的场景代价太大。如果非要量化建议用PTQ训练后量化而不是QAT量化感知训练PTQ实现简单精度损失也可控。5.2 部署环境的依赖管理部署环境我用的是Ubuntu 20.04 Python 3.9 CUDA 11.8。这里有个坑ultralytics的版本和torch版本必须匹配。我一开始装了ultralytics 8.0.100配torch 2.0.1结果推理时CUDA报错。后来换成ultralytics 8.0.196配torch 2.1.0才稳定。依赖清单我整理了一份直接可复现pip install ultralytics8.0.196 pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118 pip install onnx1.15.0 onnxruntime-gpu1.17.0 pip install opencv-python4.8.1.78 pip install numpy1.24.3注意numpy版本不要超过1.24否则和opencv有兼容性问题。这个坑我踩了两个小时才定位到。如果是CPU部署比如没有独立显卡的工控机把onnxruntime-gpu换成onnxruntime推理速度大概在8-12FPS勉强能用。建议用OpenVINO做CPU加速能到20FPS左右。5.3 推理后处理从检测框到分类结果的映射逻辑模型输出的是检测框和类别还需要映射到四大类。这个映射逻辑我写成了一个独立的配置模块方便后续调整CATEGORY_MAP { 塑料瓶: 可回收物, 易拉罐: 可回收物, 纸箱: 可回收物, 报纸: 可回收物, 玻璃瓶: 可回收物, 金属罐: 可回收物, 旧衣服: 可回收物, 充电电池: 有害垃圾, 灯管: 有害垃圾, 药品包装: 有害垃圾, 油漆桶: 有害垃圾, 菜叶: 厨余垃圾, 果皮: 厨余垃圾, 剩饭: 厨余垃圾, 蛋壳: 厨余垃圾, 茶渣: 厨余垃圾, 烟头: 其他垃圾, 陶瓷碎片: 其他垃圾, 一次性餐具: 其他垃圾, 卫生纸: 其他垃圾 }后处理里还有一个多目标投票逻辑。一张图里可能检测到多个垃圾最终输出应该是什么我的做法是如果检测到有害垃圾优先提示有害垃圾因为危害最大否则按置信度加权投票取权重最高的类别。置信度阈值我设的是0.35NMS的IoU阈值设0.5。阈值太低会引入大量误检太高会漏检。0.35是我在验证集上扫出来的最优值。5.4 实际场景测试中的问题和修复部署到实际垃圾桶场景后我发现了几个训练时没暴露的问题问题一反光干扰。垃圾桶旁边的金属栏杆在阳光下反光模型把它误判为金属罐。修复方法是在训练集里补充了500张带反光干扰的负样本同时在推理时加了一个简单的亮度过滤——如果检测框区域的平均亮度过高且纹理熵过低直接丢弃。问题二运动模糊。有人扔垃圾时动作很快摄像头拍到的图像有运动模糊。模型对模糊图像的召回率下降了约15%。修复方法是在数据增强里加了运动模糊增强同时把推理时的输入尺寸从640提到800给模型更多细节。问题三夜间低照度。夜间场景下模型几乎失效。这个靠算法解决成本太高我的方案是硬件层面加了一个补光灯同时训练时用了Gamma校正增强模拟低照度双管齐下后夜间召回率从32%提升到71%。6. 一些容易被忽略但很关键的工程经验6.1 模型版本管理和实验追踪做改进类项目实验次数会非常多。我一开始用Excel记后来发现根本管不过来。转用WandB做实验追踪每次训练的配置、指标、模型文件都自动记录还能可视化对比不同改进策略的效果。模型文件命名我定了规范yolov8m_cbam_p2_wiou_v3_best.pt把关键改进点都体现在文件名里。这样过一个月回头看不用翻日志就知道这个模型用了哪些改进。6.2 推理服务的接口设计如果要把模型做成服务接口设计要考虑几点输入支持base64编码的图像和图像URL两种方式输出返回检测框坐标、类别、置信度、映射后的大类超时设置3秒超时超时返回错误码而不是阻塞批处理支持一次传入多张图内部做batch推理吞吐量能提升3倍我用FastAPI搭了一个简单的服务单卡RTX 3060上QPS能到25左右满足小区级别的并发需求。6.3 持续迭代的数据闭环模型上线不是终点。我在服务里加了一个低置信度样本回传机制当检测结果的最高置信度在0.35到0.5之间时把这张图存下来定期人工审核后加入训练集。这样模型能持续看到新的难样本每个月重新训练一次mAP能保持稳定甚至缓慢提升。这个闭环的关键是审核成本控制。如果每张都审人力扛不住。我的做法是只回传边界样本每天大概200-300张一个人半小时能审完。6.4 关于YOLOv8改进的几点个人体会最后说几个我在改进过程中体会比较深的点。改进不是越多越好。我一开始把CBAM、P2、WIoU、BiFPN全加上了结果mAP反而下降了0.8。原因是模块之间会互相干扰BiFPN的加权融合和CBAM的注意力在特征层面有冲突。后来逐个做消融实验只保留CBAMP2WIoU三个改进效果最好。消融实验是必须做的不然你根本不知道哪个改进真正有效。改进要针对数据集的痛点。如果你的数据集小目标不多加P2就是浪费算力如果类别不平衡不严重改损失函数收益也很小。先分析数据集的分布特征再决定改哪里。训练日志比最终指标更有价值。我很多改进灵感来自看loss曲线的形状而不是看最终的mAP数字。比如cls loss的震荡模式告诉我分类边界有问题box loss的下降速度告诉我定位能力是否饱和。不要迷信SOTA。论文里的改进是在特定数据集上验证的换到你的场景不一定work。我试过好几个在COCO上涨点的改进在垃圾数据集上要么没效果要么掉点。自己的验证集才是唯一标准。这套系统我从零开始做前后花了大约三个月其中数据集构建占了一个半月模型改进和调参占了一个月部署和测试占了半个月。如果让我重新做一遍我会把更多时间花在数据采集和标注上因为数据质量的上限决定了模型性能的上限改进策略只是逼近这个上限的手段。

看完文章,想为自己的企业也做一次专业网站诊断?

尧图顾问免费为您评估现有网站,并给出建站/改版建议与报价方案。

免费获取方案