首页 / 资讯中心 / 文章详情

基于YOLOv8改进的生活垃圾图像识别与分类系统实战解析

基于YOLOv8改进的生活垃圾图像识别与分类系统实战解析 ★ FEATURED ARTICLE
做毕设或者练手项目很多人一上来就选“图像识别”结果跑几个开源demo就卡住了。我今天想聊的这套东西是一个完整走通的基于YOLOv8改进的生活垃圾图像识别与分类系统——从数据集清洗、模型主干改进、训练复现到常见坑的排查整个链路都有。核心就是用深度学习里的目标检测思路把瓶盖、纸盒、电池这类东西在复杂背景下逐个框出来并打上类别标签同时针对小目标和易混类别做专项优化。这篇内容适合正在做相关毕业设计、准备算法竞赛或者想正经上手YOLOv8改进手法的人看。这类课题在网上名气很大但真正能写清楚“从哪下手改进”的教程很少。多数人卡在三个地方一是数据集选得不对模型怎么调都学不出好效果二是改进模块往模型里一塞就完事不做消融也不看结果答辩一问就露馅三是训练时一堆玄学报错不知道是数据问题还是参数问题。下面按我实际做完一整套项目的顺序把每个环节掰开讲。1. 整体设计与改进思路1.1 为什么拿YOLOv8当基线而不是其他模型先说结论做垃圾分类识别这种需要“研究改进”的课题以YOLOv8作为基线是目前最稳妥的选择没有之一。我自己对比过Faster R-CNN、SSD、YOLOv5和YOLOv8最后留下的就是YOLOv8。原因有三层。第一层是生态YOLOv8由ultralytics团队维护一个pip命令装好数据格式、训练脚本、评估脚本全都有不需要自己用OpenCV手工写anchor匹配和NMS省掉的工程量够你多做好几轮对比实验。第二层是精度和速度的平衡垃圾分类里大量目标是易拉罐、纸团、果皮这类中尺寸目标对实时性的要求没有交通检测那么高但也不能慢到单帧200毫秒以上YOLOv8在V100这类卡上能以100FPS稳定跑做演示和答辩现场推理都很合适。第三层是改进空间既然论文题目写了“基于改进算法的研究”就不能只套一个现成框架YOLOv8结构相对规整主干、颈部、检测头三层分工明确想动哪一层改哪一层非常容易定位。顺带说说为什么不选更新的YOLOv11或者YOLOv10。不是新版本不好而是对垃圾识别场景来说新版本的目标检测专精度确实更强但对应的公开资料和代码注释还没沉淀够很多改进点没有现成的模块可以引用你去做二次创新的难度会直线上升。做研究类项目选的工具既要能用还要方便后续复现和写论文YOLOv8正处于这个最佳位置。1.2 垃圾分类图像识别任务的真实难点不少人以为垃圾分类识别就是“给目标画框”这么简单真上手做才发现完全不是。这个任务的难点非常有特点和通用目标检测很不一样。首先是小目标问题。生活垃圾里有一大批东西是很小很碎的烟头、五号电池、瓶盖、牙签、棉签。如果摄像头离垃圾箱有一段距离这些目标在640x640的输入图像里往往只有十几到几十个像素。标准YOLOv8下采样32倍后这种小目标在特征图上只剩下1到2个像素很容易在检测头里被直接丢掉。这也是我在实验中发现漏检率最高的类别所在。其次是类间相似度高。塑料瓶和玻璃瓶外形几乎一致硬纸盒和纸箱只有纹理区别透明的塑料盒和玻璃盒在光线不足时尤其难分辨。普通卷积特征在高层语义上能够区分猫和狗但区分“同外形、不同材质”的目标需要模型学到非常细的材质纹理线索这对特征提取的要求是很苛刻的。第三是背景极其杂乱。垃圾不是摆在干干净净的桌子上让你拍的实际场景里经常是多个目标堆叠、遮挡、半埋在塑料袋里、潮湿反光、阴影覆盖。目标之间的边缘都不清晰哪怕human标注员都要犹豫半天更别说模型。第四是类别分布极度不均衡。按国内常见四分法可回收垃圾和厨余垃圾的样本非常多但有害垃圾电池、过期药品、灯泡样本往往只有前者的十分之一。如果数据不处理直接训练模型会严重偏向高频类有害垃圾几乎全部漏检。而有害垃圾又恰恰是垃圾分类里最需要识别准确的类别。这里还有个很多人忽略的点垃圾分类识别的标注质量。公开的垃圾数据集里错标、漏标、边界框过大的标注比比皆是。我清洗数据时发现其中一部分类别标签互相混淆这种脏数据如果不处理改任何模型结构都是白费力气。1.3 改进方向怎么确定说到改进很多人的第一反应是“把注意力机制加上”、“把主干换成Transformer”但这样拍脑袋选方案多半做不出有效果的实验。我做这个课题时改进方向的确定完全是反过来的——先跑一版baseline把各类别的检测结果拆开看哪些类别mAP低再去针对性地做结构改进。跑了第一版实验之后我看到的现象非常清晰烟头、电池、瓶盖这类小目标召回率很低但大目标精度已经不错玻璃瓶、塑料瓶之间容易互相误判有害垃圾总体表现最差。基于这个诊断我把改进工作收敛到了三个方向上。第一个方向是注意力机制用来强化特征。垃圾识别要靠材质和纹理细节普通卷积在浅层感受野小天然不够敏感注意力机制可以显式地让模型聚焦到关键区域。第二个方向是特征融合结构用来解决小目标。YOLOv8默认的颈部特征金字塔对高层语义特征利用得多但小目标需要更浅层的高分辨率特征图这里需要改结构。第三个方向是损失函数和样本均衡用来解决类别不均衡和框回归不准的问题。很多教程会鼓励一股脑堆十几个模块比如同时加Transformer、注意力、可变形卷积、ASFF结果训练时间翻了好几倍精度还未必上去。真实项目里改进是“对症下药”不是“多多益善”。每个模块都要能对应到上一轮实验暴露的问题上这才叫有逻辑的改进。2. 数据集垃圾分类识别的命门2.1 数据集选型目标检测项目里数据决定上限模型只是尽量逼近这个上限。垃圾分类识别的公开数据集不少但质量和适用范围差异很大我建议按下面这张表来选。数据集规模类别体系标注格式主要优缺点TrashNet约5000余张6类玻璃、纸、纸板、塑料、金属、其他图像级分类无边框适合做分类基线但无检测框且背景单一华为云垃圾分类数据集常见版本约10000张4大类、40小类YOLO/VOC/COCO均有贴近国内分类标准类别粒度细但部分小类样本少Garbage Classification约15000张有机、无机、可回收等通常含几十小类图像分类为主背景简单检测任务需二次标注自建数据集视需要自定义标注工作量大最贴近实际场景但工程量高我自己是用华为云垃圾分类数据集打底再补充了一部分自行拍摄的宿舍、小区垃圾投放点照片。注意一个容易踩的大坑很多版本标注格式是VOC的XML需要统一转成YOLO的txt格式再丢给ultralytics训练。另外如果题目的研究偏向“生活场景中的垃圾”不建议直接用TrashNet做检测训练因为它本来就是单物体、简单背景的学术数据集模型在它上面训练得很理想一到真实场景马上掉点。2.2 数据清洗与标注格式转换数据下载好之后第一件事不是直接训练而是清洗。我拿到数据后做了这么几步先写脚本检查每张图片能不能正常解码把损坏图片筛掉再按文件名查重把数据集里重复出现的图片删除防止训练集和验证集出现同源数据导致指标虚高接着抽查了一部分标注把明显错标、漏标的样本挑出来。质量较差的标注我观察下来有两个典型问题一是边界框把背景全包进去比如瓶子被标成一个带大片阴影的框导致模型学到的目标边界有大量背景噪声二是标签对不上有的数据集把金属罐标成玻璃瓶这类错误直接会让两个容易混淆的类更难分。清洗完成后是格式转换。ultralytics训练推荐的结构如下datasets/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml其中data.yaml关键配置为path: datasets/ train: images/train val: images/val nc: 4 names: 0: recyclable 1: kitchen 2: hazardous 3: other注意这里为了演示我把类别压缩成了国内四分法的4大类。如果是做论文也可以保留40小类但小类数据不均衡问题会更突出训练难度明显加大属于另一种取舍。转换标注时如果VOC格式是像素坐标(xmin, ymin, xmax, ymax)需要手动归一化import os import xml.etree.ElementTree as ET def convert_voc_to_yolo(xml_path, out_path, img_w, img_h): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text cls_id class_map[name] box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))当时为了数据这步大约花了两个整天但之后训练几乎没有出现“箱子里没框”、“类别张冠李戴”这类幺蛾子回头想想这时间花得非常值。2.3 数据增强与类别不平衡处理数据处理好之后下一步是考虑要不要做增强。YOLOv8官方训练脚本默认已经开启了Mosaic增强这东西在小目标多的场景是一把双刃剑它能把四个图拼在一起强制模型学习多种尺度对小目标提升有帮助但拼图过程中目标会被截断、缩小如果小目标本身就只有几个像素mosaic反而会把它们拼没。我在训练时把mosaic概率保留在默认的1.0初期数值在最后10个epoch关掉让模型在接近真实分布的数据上微调收敛。除此之外还加了亮度扰动、对比度扰动、轻微的随机旋转和灰度化。这是因为真实垃圾投放点经常有夜间灯光、逆光、阴影增强后模型对这些情况鲁棒不少。针对样本不均衡除了常规的按类别加权损失外最有效的办法是对少样本类别做平移复制增强——把有害垃圾这类样本在不改变内容的条件下做小幅平移、缩放和亮度调整扩充到接近其它类别数量。我实测用这个方式有害垃圾的召回率能提升几个百分点比单纯调损失权重更直接。3. 改进算法设计3.1 Backbone侧注意力机制怎么加才有用讲具体改进前先把YOLOv8的基本结构说清楚。它大体分三段Backbone负责从原始图像逐级提取特征Neck负责把不同层级的特征融合起来Head负责在融合后的特征图上做分类和回归。改进可以发生在任意一段但常见论文做法集中在Backbone和Neck。我第一个改动是给Backbone引入协调注意力CACoordinate Attention。注意不是SE或者CBAM虽然这两个在开源项目里更常见但垃圾分类识别里我更推荐CA。SE只建模通道关系会丢失位置信息CBAM虽然加了空间注意力但空间注意力本质还是局部卷积的堆叠对长距离依赖帮助有限。CA的思路是把横向和纵向的位置信息分别编码进注意力权重让模型在关注“哪个通道重要”的同时也知道“图像里哪里重要”。用一句话理解CA相当于让模型既知道“材质纹理”这个通道特征很关键也知道“画面右下角那堆东西”更值得看。我在C2f结构里插入了CA模块写出来后就是类似C2f-CA的结构。训练时对比过加了CA之后玻璃瓶和塑料瓶的区分能力明显变好因为CA能增强材质边界这种细粒度特征的响应。3.2 Neck侧从PANet到加权特征融合YOLOv8默认的Neck是PANet结构思路是把Backbone中不同尺度的特征做自顶向下、自底向上的双向融合。这个结构本身不差但在小目标很多的垃圾分类场景里它有一个短板不同层级的特征在融合时是无差别相加的。可以打个比方现在要判断一个瓶子是塑料的还是玻璃的既需要浅层的高分辨率纹理信息也需要深层的语义信息来判断“这确实是个瓶子”。但PANet在融合时对两者一视同仁如果这时浅层特征被噪声占主导融合结果反而不如不融合。解决思路是给不同层级特征分配可学习的融合权重让模型自己学会哪些层更重要。我参考了加权双向特征融合的思路在Neck的特征叠加过程中为每条输入路径加上了一个可学习的系数同时在后处理时做了归一化。实际效果是小目标烟头、瓶盖的召回率比原版PANet提升了一个档次。原理很好理解小目标主要靠浅层高分辨率特征原本浅层特征在融合时占比不够加权后浅层特征的贡献被显式放大小目标检测自然受益。这个改动可以在不改动太多推理耗时的情况下拿到稳定涨点属于性价比很高的改进项。3.3 检测头与小目标优化改进完Neck之后还有一类目标非常难处理——极度小目标。YOLOv8默认从3个尺度输出预测分别对应下采样8倍、16倍、32倍的特征图。对于640x640的输入最小检测尺度是80x80的特征图每个像素对应原图8个像素。一个烟头在图上只有14x14像素映射到80x80特征图上不足2个像素特征信息几乎完全丢失。我的改动是增加一个更浅的检测层用4倍下采样的P2特征图再输出一组预测。这等于给模型加了一个“放大镜”专门处理小目标。注意增加P2检测层会带来额外的计算量推理速度会下降一些但垃圾分类场景对实时性要求不苛刻换来几个点的小目标召回率提升非常值得。如果不想增加额外检测层导致显存压力太大还有另一个折中方案把输入分辨率从640提高到960。这个方法不用动模型结构对小目标的增益同样明显但训练时间和推理时间都会成倍增加。我当时在改进版里是两者选一优先用P2检测层显存仍有余量再考虑分辨率增幅。3.4 损失函数调整损失函数是很多改进论文不会细说但影响很大的地方。YOLOv8默认用CIoU损失做边界框回归CIoU考虑了重叠面积、中心点距离和宽高比已经很完善。但在垃圾分类里我发现一个现象目标之间本来就堆叠挤压很多框的长宽比很极端CIoU对“宽高比相同但方向不同”的情况不太敏感容易导致框回归不精确。我换成了SIoU损失它在CIoU的基础上额外引入了角度惩罚能够更快地把预测框“掰正”到跟目标框同一个方向收敛更平稳框的定位也更准。在垃圾识别这种目标边缘模糊的场景里框定位准了类别判断的特征区域也会随之更干净。同时针对有害垃圾样本少的问题我在分类损失中按类别逆频率加了权重。这里有个操作细节权重不要设置得过高否则模型会过拟合到少量有害垃圾样本上出现训练集mAP很高但验证集崩盘的情况。我的经验是权重控制在2至3倍区间并且优先靠数据增强扩样损失权重只做辅助。4. 环境配置与完整训练实操4.1 硬件与软件环境准备说到环境配置这是不少入门者最容易崩溃的一步。先说硬件。我的主力训练卡是单张RTX 309024GB显存训练改进版YOLOv8m增加P2层后640分辨率、batch size 16时刚好能跑满。如果只有8GB显存的卡建议用COCO预训练权重并在训练时关掉部分增强或者直接把模型换成n/s版本。我看到过有人在1660Ti上硬跑m模型batch size压到2甚至1这时候BatchNorm统计都会失真训出来的模型大概率是不稳定的。软件栈方面我用的是最主流的组合Ubuntu 20.04 / Windows 11 Python 3.8 PyTorch 1.13 或 2.x CUDA 11.7 / 11.8 / 12.1取决于驱动 ultralytics 8.x安装ultralytics非常简单pip install ultralytics安装完成后先跑一个官方预训练模型的推理测试确认环境能正常加载权重和输出结果再继续后面的训练。4.2 模型配置文件怎么改ultralytics允许通过一个yaml文件定义模型结构。以YOLOv8n为例最小的配置内容如下# yolo11n.yaml 简化示例 nc: 4 scales: # 模型缩放因子n对应0.25 n: [0.25, 0.25, 0.25] backbone: - [-1, 1, Conv, [64, 3, 2]] - [-1, 1, Conv, [128, 3, 2]] - [-1, 3, C2f, [128, True]] - [-1, 1, Conv, [256, 3, 2]] - [-1, 6, C2f, [256, True]] - [-1, 1, Conv, [512, 3, 2]] - [-1, 6, C2f, [512, True]] - [-1, 1, Conv, [1024, 3, 2]] - [-1, 3, C2f, [1024, True]] - [-1, 1, SPPF, [1024, 5]] head: - [-1, 1, nn.Upsample, [None, 2, nearest]] - [[-1, 6], 1, Concat, [1]] - [-1, 3, C2f, [512]] # 类似地有其他分支我在这里把两个地方做了改动。一是把backbone中特定几层的基础模块从C2f替换成C2f-CA引入注意力。二是检测头的最终输出列表里加入P2层的输出索引并调整了后续层的输入参数。改完模型文件之后建议先跑一个过拟合小实验只拿几十张图训练几个epoch确认结构改动没有语法错误再放开正式训练。4.3 训练参数设置与完整流程训练命令非常简单所有参数都可以通过命令行指定yolo train \ modelyolov8m.yaml \ datadata.yaml \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ optimizerAdamW \ patience20 \ projectrun_results \ namebaseline各参数含义给第一次训练的人解释一下epochs训练轮数垃圾数据集规模中等150轮足够过多容易过拟合过少则loss还没降下去。imgsz输入分辨率640是精度和速度的平衡点。显存充足且小目标多可以试960。batch批大小越大收敛越稳定但受显存限制尽量不低于8。lr0初始学习率AdamW下0.01是个常见起点SGD下通常设为0.01到0.02之间。patience早停验证集指标连续多少轮不涨就停止防止无效长时间训练。训练过程中我一般盯两类东西。一是终端输出的loss趋势如果loss在逐渐下降并趋于平坦属于正常现象二是每隔50个epoch在验证集上跑一次预测可视化光看loss容易自欺欺人直接看图才知道模型是不是真的学会了区分玻璃和塑料。模型会自动保存best.pt和last.pt。这里有个迁西经验如果改进版模型的best.pt精度不如baseline先不要急着否定改进方向很大概率是学习率或者增强参数没配合好把初始学习率调低四分之一再试一轮结果往往就不一样了。5. 实验结果对比与调优5.1 指标怎么选毕设或者论文里的实验环节指标选对了事半功倍。垃圾分类识别最常用的是COCO风格指标mAP50和mAP50-95。mAP50看的是预测框和真实框IoU超过0.5就算检测到的平均精度mAP50-95则是对0.5到0.95之间多个IoU阈值求平均后者更严格也更敏感于框定位质量。除了mAP还要报精确率Precision和召回率Recall。垃圾分类里召回率特别重要宁可把瓶子错分成可回收垃圾也不能漏掉一个有害垃圾电池。所以在论文里要特意分析每个类别的召回率。我实验里记录了以下数据数据会随数据集分布变化这里强调相对比较意义模型mAP50mAP50-95参数量推理耗时(ms)YOLOv8n 基线82.161.33.2M6.4注意力改进83.763.53.3M7.1特征融合改进85.265.83.4M8.0P2检测层86.967.93.8M9.6从这张表可以清晰看到每个改进点都带来持续增益同时只增加了很小的参数量和推理代价这是理想意义上的消融结果。论文写作时还可以把这张表的mAP和召回率做成分图表示细粒度类别差异。5.2 可视化分析光有表格还是不够的答辩时最常见的追问就是“你怎么证明改进起作用了”。因此还需要三类可视化结果。第一类是loss曲线把baseline和改进版的训练loss画在同一个坐标系里对比收敛速度和最终收敛值。改进版如果收敛更低、更平缓就能直观说明结构改动的有效性。画曲线可以用ultralytics自动生成的results.csv读进来用matplotlib画即可。第二类是Grad-CAM热力图把所有类别的梯度信息叠加到输入图像上看模型“注意力的重心”到底在哪。改进版的热力图应该更集中在目标本体上而不是散落在背景边缘。这会非常直观地展示注意力机制的贡献。第三类是预测结果对比图选几组典型case——比如一个密集堆满瓶子的小垃圾桶旁边有烟头和果皮。baseline可能漏检烟头或把塑料瓶框成玻璃瓶改进版要有明显修正。这几张截图是答辩时的强有力素材。5.3 部署与推理优化训练完成的模型最终不能只停留在笔记本上还得能演示、能实时推理。最轻量的做法是直接加载pt文件用ultralytics写推理脚本from ultralytics import YOLO model YOLO(best.pt) results model.predict(test.jpg, conf0.35, iou0.45, imgsz640) for r in results: r.save(filenameresult.jpg)但这样推理速度不理想。想进一步加速可以导出成ONNX格式yolo export modelbest.pt formatonnx imgsz640ONNX可以在CPU上直接用ONNXRuntime跑也可以在边缘设备上接TensorRT或者RKNN。如果以后要把系统部署到RK3588这类开发板上还需要做一步量化把FP32权重转成FP16或者INT8小目标场景下建议优先用FP16INT8会在极小目标上产生明显精度损失这是我从实测里得到的教训。6. 常见问题与避坑记录6.1 环境配置报错速查我整理了一下实操中最常出现的问题供大家直接对照。报错或现象原因解决方案CUDA out of memory显存不够batch或imgsz过大减小batch到4或2降低imgsz到480换轻量版模型DNN inference error / 版本冲突CUDA与PyTorch版本不匹配直接用配套的conda环境尽量不混装下载权重超时网络访问预训练服务器不稳定手动下载pt文件放到指定目录或配置镜像源训练结果出现NaN学习率过高降低lr0切换优化器检查标签坐标是否越界6.2 训练不收敛与指标上不去很多人遇到loss下降但mAP纹丝不动第一反应是换模型结构但多数情况下是数据没准备好。常见原因包括数据集标注格式错误、类别索引对不上、标签坐标没有归一化到0~1、还有train和val划分时发生数据泄漏。检查的第一步就是把验证集里的一部分预测结果可视化输出看框位置是否正确。如果框位置偏得离谱先修数据不要动模型。另一个很常见的问题是类别不平衡被忽略。如果有害垃圾样本只占5%即便mAP整体看起来不错有害垃圾的召回率也会很低。我建议在训练时打开每个类别的详细指标输出逐个类看Precision和Recall而不是只看汇总的mAP。6.3 改进模块无效怎么排查最好的排查方法是做消融实验。假如你加了CA注意力之后mAP没有提升先从三件事查起第一注意力模块是否真的参与到了计算图里很多人改了yaml但权重没保存对第二模块放在哪一层更合适浅层和深层效果差异可能很大试着在Backbone不同stage各加一次第三训练轮数是否足够注意力参数需要更多轮数才能适应150轮不够就先加到200轮左右。还有一个技巧是做小规模对照实验。只拿200张图像分别训练基线模型和改进模型5个epoch如果改进版在这么小的规模下也没有表现出优势那这个模块对当前任务大概率无效赶紧换方案。这样排查一次只需要十几分钟比盲目堆结构高效得多。最后说一点我做这类项目最深的心得深度学习项目里最值钱的是流程不是某个灵光一现的模块。数据集清洗、诊断模型短板、小规模对照、逐点消融这一套流程走通了换任何目标检测项目都能用。如果你正准备做垃圾分类识别的设计建议先跑一版baseline把指标打印出来再回头按我的思路选一两个改进点深挖不要贪多选三四个能互相印证的改进就足够撑起一篇完整研究了。
阅读完成 · 觉得有帮助?
咨询建站