2026/10/1 1:29:23

YOLOv8垃圾分类识别实战:从训练到部署的完整指南

YOLOv8垃圾分类识别实战:从训练到部署的完整指南 简介这份资源是基于YOLOv8的垃圾分类识别项目完整设计包面向深度学习入门者、人工智能课程设计学生及毕业设计开发者帮助解决垃圾自动分类识别这一典型目标检测任务。包内共11个文件以Python脚本、YAML配置、PNG效果图、预训练权重pt文件及Markdown说明文档为主压缩包约10.21MB涵盖数据集重命名、图像标注辅助、模型配置与识别结果预览等模块。其中数据集管理脚本可批量整理样本标注工具辅助绘制边界框配合data.yaml完成类别与路径配置yolov8n.pt权重便于快速验证与迁移训练。项目围绕可回收、厨余、有害及其他垃圾等类别展开涉及图像预处理、数据增强、多轮迭代训练与实时检测部署思路并附README说明安装使用方式。目前已有32人学习下载适合希望掌握YOLOv8实战流程、快速搭建垃圾分类识别系统的读者参考借鉴。1. 从一张垃圾桶照片说起YOLOv8 垃圾分类识别到底在做什么你拍一张小区垃圾桶的照片扔给模型它框出四个瓶子和两个纸盒分别打上「可回收物」和「其他垃圾」的标签——这就是基于 YOLOv8 的垃圾分类识别要干的事。它属于目标检测任务不是简单的图像分类分类只告诉你「这张图是塑料瓶」检测要告诉你「塑料瓶在左上角纸盒在右下角各自多大」。垃圾分类场景里一张图往往混着三四种垃圾只做分类根本没法用必须上检测。这个方向适合谁做毕业设计的学生、想跑通一个完整检测 pipeline 的算法新手、需要给智能垃圾桶或分拣设备做视觉模块的嵌入式工程师。它不需要你从零设计网络YOLOv8 把 backbone、neck、head 都封装好了你主要的工作量在数据集和训练调参上。但「封装好」不等于「无脑跑」——垃圾分类的类别定义、标注一致性、小目标密集堆叠这几个坑不踩一遍mAP 上不去。下面按「先立住原理、再动手复现、最后避坑」的顺序讲透。2. YOLOv8 垃圾分类识别的技术底座与选型理由2.1 为什么是 YOLOv8 而不是 v5 或两阶段检测器垃圾分类识别对速度有硬要求。分拣线上的传送带不会等你单帧推理超过 50ms 基本就没法做实时分拣。YOLOv8 在同等精度下比 YOLOv5 快一截而且它把 anchor-based 换成了 anchor-free 的解耦头对小目标密集场景更友好——垃圾袋里挤在一起的瓶瓶罐罐正是小目标密集的典型。两阶段检测器Faster R-CNN 那一类精度可能略高但推理速度差一个量级部署到边缘设备上更吃力。垃圾分类这个任务类别区分度其实不低塑料瓶和纸盒的外观差异明显不需要两阶段那种极致精度YOLOv8 的精度-速度平衡点刚好卡在甜区。YOLOv8 有 n/s/m/l/x 五个尺度。垃圾分类识别我一般从 yolov8n 或 yolov8s 起步n 参数量约 3Ms 约 11M。如果部署目标是 RK3588 或 Orin 这类边缘板n 和 s 是首选如果只是服务器端跑m 可以试试。别一上来就上 x垃圾分类的数据集规模通常撑不起大模型过拟合风险高。2.2 垃圾分类的类别体系怎么定这是最容易被忽视、但影响最大的一步。国内主流是四分法可回收物、有害垃圾、厨余垃圾、其他垃圾。但落到检测任务上四分法太粗——「可回收物」下面有塑料瓶、易拉罐、纸箱、玻璃瓶外观差异巨大模型学起来很吃力。我的做法是分两层检测层用细类塑料瓶、易拉罐、纸箱、玻璃瓶、电池、药品、菜叶、果皮、烟头、纸巾……业务层再做细类到四分法的映射。这样模型学的是外观特征映射逻辑用代码控制改分类标准不用重训模型。# 细类到四分法的映射表业务层用 CATEGORY_MAP { plastic_bottle: recyclable, # 塑料瓶 - 可回收物 can: recyclable, # 易拉罐 - 可回收物 cardboard: recyclable, # 纸箱 - 可回收物 glass_bottle: recyclable, # 玻璃瓶 - 可回收物 battery: hazardous, # 电池 - 有害垃圾 medicine: hazardous, # 药品 - 有害垃圾 vegetable: kitchen, # 菜叶 - 厨余垃圾 fruit_peel: kitchen, # 果皮 - 厨余垃圾 cigarette: other, # 烟头 - 其他垃圾 tissue: other, # 纸巾 - 其他垃圾 } def to_four_category(detected_class: str) - str: 把检测到的细类映射到四分法未登记的归入其他垃圾 return CATEGORY_MAP.get(detected_class, other)这段映射逻辑的好处是模型只管认外观业务规则随时可改。如果哪天分类标准从四分法变成两分法改字典就行不用重新标注、重新训练。参数上CATEGORY_MAP的 key 必须和训练时data.yaml里的names完全一致大小写、下划线都不能错否则映射会静默失败全部落到other。2.3 数据集的来源与标注工具选择垃圾分类没有像 COCO 那样现成的权威数据集。常见做法是三条路一是自己拍手机拍几百张不同光照、不同角度的垃圾桶照片二是用公开的垃圾数据集做底子比如 TrashNet但它是分类数据集没有框得自己补标注三是爬取电商产品图做合成。标注工具用 labelme 或 labelImg 都行。labelme 输出 JSONlabelImg 输出 XML最后都要转成 YOLO 的 txt 格式。我一般用 labelImg因为它直接支持 YOLO 格式导出省一步转换。标注时有个血泪经验同一类垃圾的框要尽量贴紧物体边缘不要留太多背景。垃圾分类场景背景杂乱垃圾桶、地面、手框松了模型会学到背景特征换个场景就翻车。3. 从零跑通 YOLOv8 垃圾分类训练环境、数据、命令3.1 环境搭建CPU 版和 GPU 版的分岔路环境配置是新手第一道坎。如果你只是先跑通流程、验证代码CPU 版够用但要真正训练出能用的模型必须上 GPU。GTX 1660 Ti6G 显存是很多人的入门卡跑 yolov8n、batch8、imgsz640 没问题再大就爆显存。Ubuntu 20.04 上搭 CPU 版环境的最小步骤# 创建虚拟环境Python 3.8-3.10 都行3.9 最稳 conda create -n yolo_garbage python3.9 -y conda activate yolo_garbage # 安装 PyTorch CPU 版注意CPU 版不要装 CUDA 相关的包 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 安装 ultralytics pip install ultralytics # 验证安装 yolo checksyolo checks会打印环境信息重点看两行PyTorch 版本和 CUDA 是否可用。CPU 版这里 CUDA 显示不可用是正常的。如果你有 GPU把第一行 pip 换成对应 CUDA 版本的命令比如 CUDA 11.8 用--index-url https://download.pytorch.org/whl/cu118。装完再跑yolo checksCUDA 那行应该显示可用。注意PyTorch 版本和 CUDA 版本必须匹配。装错了不会报错但训练时会静默回退到 CPU速度慢十倍你还以为是模型问题。3.2 数据集目录结构与 data.yaml 写法YOLO 格式的数据集目录长这样garbage_dataset/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 训练标签 txt │ └── val/ # 验证标签 txt └── data.yaml每张图片对应一个同名 txt每行格式是class_id x_center y_center width height坐标全部归一化到 0-1。比如一张 640x480 的图里有个塑料瓶框在 (100, 200) 到 (300, 400)那 txt 里写0 0.3125 0.625 0.3125 0.4167。data.yaml是训练的入口配置# data.yaml path: /home/user/garbage_dataset # 数据集根目录绝对路径最稳 train: images/train # 相对 path 的训练图目录 val: images/val # 相对 path 的验证图目录 nc: 10 # 类别数必须和 names 长度一致 names: # 类别名顺序即 class_id 0: plastic_bottle 1: can 2: cardboard 3: glass_bottle 4: battery 5: medicine 6: vegetable 7: fruit_peel 8: cigarette 9: tissuenc和names长度不一致是最常见的报错来源训练启动时会直接抛异常。path用绝对路径相对路径在不同工作目录下跑会找不到文件。names的顺序就是标注时 class_id 的顺序标错了只能重标没有后悔药。3.3 训练命令与关键参数逐个拆解启动训练就一行命令但参数含义得搞清楚yolo detect train \ data/home/user/garbage_dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/garbage \ nameexp1逐个说modelyolov8n.pt是预训练权重。第一次跑会自动下载下载慢的话可以手动下好放到当前目录。用预训练权重比从零训练收敛快得多垃圾分类这种中等规模数据集不用预训练基本训不动。epochs100是最大轮数。垃圾分类数据集通常几千张图100 轮够收敛。但别死守这个数配合patience20用——20 轮内验证集指标没提升就早停省时间。imgsz640是输入分辨率。垃圾分类里小目标多烟头、瓶盖分辨率太低小目标直接糊没了。640 是平衡点显存够可以上 800 或 960小目标召回会明显改善。batch16看显存调。GTX 1660 Ti 6G 显存跑 yolov8n imgsz640batch16 差不多是上限。爆显存就降到 8再不行降到 4。batch 太小训练不稳定可以配合lr0调小一点。lr00.01是初始学习率。YOLOv8 默认用 SGD 时 lr00.01用 Adam 时建议降到 0.001。如果你换了优化器没改学习率loss 会震荡不收敛。训练过程中会在runs/garbage/exp1/下生成results.csv记录每轮的 loss 和 mAP。想看损失函数曲线直接用 pandas 读这个 csv 画图import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/garbage/exp1/results.csv) df.columns df.columns.str.strip() # 列名可能带空格先清理 fig, axes plt.subplots(1, 2, figsize(12, 4)) axes[0].plot(df[epoch], df[train/box_loss], labeltrain box loss) axes[0].plot(df[epoch], df[val/box_loss], labelval box loss) axes[0].set_xlabel(epoch); axes[0].set_ylabel(loss); axes[0].legend() axes[1].plot(df[epoch], df[metrics/mAP50(B)], labelmAP50) axes[1].plot(df[epoch], df[metrics/mAP50-95(B)], labelmAP50-95) axes[1].set_xlabel(epoch); axes[1].set_ylabel(mAP); axes[1].legend() plt.tight_layout() plt.savefig(training_curve.png, dpi150)看曲线有个判断标准train loss 持续降但 val loss 开始升就是过拟合该早停或加数据增强。两条都降但 mAP 不涨可能是学习率太小或类别不平衡。mAP50 到 0.8 以上、mAP50-95 到 0.5 以上垃圾分类这个任务就算能用了。4. 推理、验证与部署模型训完之后干什么4.1 用训练好的权重做单图推理和批量验证训练完最好的权重在runs/garbage/exp1/weights/best.pt。单图推理yolo detect predict \ modelruns/garbage/exp1/weights/best.pt \ sourcetest_images/ \ conf0.25 \ saveTrueconf0.25是置信度阈值低于这个值的框不输出。垃圾分类场景建议从 0.25 起步调高到 0.5 漏检会变多调低到 0.1 误检会变多。具体值看你的业务更怕漏检还是更怕误检——分拣线怕误检把可回收物扔进其他垃圾可以调到 0.4智能垃圾桶提示怕漏检可以降到 0.15。批量验证用yolo detect val它会输出每个类别的 precision、recall、mAP。重点看哪几个类别拖后腿。垃圾分类里「纸巾」和「其他垃圾」经常混淆因为纸巾本身就是其他垃圾标注时容易混。如果某一类 mAP 明显低先回去查标注一致性别急着调模型。4.2 导出 ONNX 与边缘部署的衔接点要在 RK3588、Orin 这类板子上部署得先把 PyTorch 权重转成 ONNXyolo export \ modelruns/garbage/exp1/weights/best.pt \ formatonnx \ imgsz640 \ opset12 \ simplifyTrueopset12是兼容性最好的版本RK3588 的 RKNN 工具链对 12 支持最稳。simplifyTrue会做图优化去掉冗余算子转 RKNN 时少踩坑。导出后在同目录生成best.onnx可以用onnxruntime验证一下推理结果和 PyTorch 是否一致import onnxruntime as ort import numpy as np sess ort.InferenceSession(best.onnx) # YOLOv8 输入是 1x3x640x640归一化到 0-1 dummy np.random.rand(1, 3, 640, 640).astype(np.float32) outputs sess.run(None, {images: dummy}) print(输出张量形状:, [o.shape for o in outputs])输出形状一般是[1, 14, 8400]14 4 个框坐标 10 个类别分数8400 是候选框数。如果形状不对检查imgsz和nc是否和训练时一致。ONNX 验证通过再走 RKNN 或 TensorRT 的转换流程那一步的坑主要在量化校准集的选择上——校准集要用真实场景图别用训练图否则量化后精度掉得厉害。5. 垃圾分类识别训练里最容易翻车的五个坑5.1 坑一mAP 死活上不去loss 看着正常现象训练 loss 平稳下降但 mAP50 卡在 0.4 左右不动。原因九成是标注问题。要么框太松背景占比大要么同一类垃圾的框标准不一致有人贴边、有人留白要么类别标错把「其他垃圾」标成了「可回收物」。模型在学一堆自相矛盾的样本loss 能降但泛化不了。解决抽 50 张训练图把标注框画回图上肉眼检查。重点看同一类物体的框是否一致。发现不一致就重标别心疼。标注质量决定上限调参只能逼近上限。5.2 坑二验证集 mAP 很高实际用全是误检现象val 集 mAP50 到 0.9拿手机拍张新图推理框出一堆乱七八糟的东西。原因训练集和验证集来自同一批照片光照、角度、背景高度相似。模型记住了这批图的背景特征换场景就失效。这是数据泄漏的变体。解决验证集必须和训练集在拍摄场景上分开。比如训练集用白天室内拍验证集至少混入傍晚、室外、不同垃圾桶的图。有条件的话留一批完全没参与训练的「测试集」训练全程不碰最后只跑一次。5.3 坑三小目标烟头、瓶盖召回率极低现象大件垃圾检测正常烟头、瓶盖这类小目标几乎检不出来。原因imgsz640 下一个烟头可能只占十几个像素经过 backbone 下采样后特征基本消失。YOLOv8 的 P3 层虽然负责小目标但输入分辨率不够时也无能为力。解决三个方向。一是提高 imgsz 到 800 或 960显存不够就降 batch二是数据增强里开启 mosaic 和 copy-paste人为增加小目标密度三是如果还不行考虑在 head 部分加一个更高分辨率的检测层P2但这会显著增加计算量边缘设备慎用。5.4 坑四训练到一半显存爆了现象前几十轮正常突然报 CUDA out of memory。原因YOLOv8 默认开启 mosaic 增强某些 batch 里拼出来的图目标特别多显存占用波动大。另外如果开了cacheTrue把图片缓存到内存/显存数据量大时也会爆。解决先把batch降一半试试。还爆就关掉cache或者设mosaic0.5降低 mosaic 触发概率。GTX 1660 Ti 6G 这种卡跑 yolov8s imgsz640 时 batch 别超过 8。5.5 坑五转 ONNX 后推理结果和 PyTorch 对不上现象PyTorch 推理正常转成 ONNX 后框的位置偏移或类别全乱。原因最常见的是预处理不一致。PyTorch 推理时 ultralytics 内部做了 letterbox 填充你手动写 ONNX 推理时如果直接 resize 不填充输入分布就变了。另一个原因是opset版本和推理引擎不匹配。解决ONNX 推理的预处理必须复现 letterbox等比缩放后填充灰边到 640x640同时记录缩放比例和填充偏移后处理时再映射回原图坐标。别偷懒用普通 resize。导出时opset12配合simplifyTrue能规避大部分算子兼容问题。6. 把 mAP 再往上推一档两个我常用的微调技巧第一个技巧是类别权重平衡。垃圾分类数据集天然不平衡——塑料瓶可能几百个电池可能就几十个。模型会偏向多数类少数类召回惨不忍睹。YOLOv8 本身没有直接的类别权重参数但可以在数据集层面做文章对少数类做过采样或者用 copy-paste 增强把少数类实例贴到其他图上。我一般把每个类别的实例数控制在 200-2000 之间低于 200 的类必须增强高于 2000 的类适当欠采样。第二个技巧是冻结 backbone 做 warmup。如果你用的是 yolov8s 以上的模型且数据集只有一两千张直接全量微调容易过拟合。可以先冻结 backbone 训 10 轮让 head 先适应你的类别数再解冻全量训。命令里加freeze10就行数字表示冻结前 10 层。# 第一阶段冻结 backbone只训 head yolo detect train datadata.yaml modelyolov8s.pt epochs10 freeze10 lr00.01 # 第二阶段解冻全量小学习率微调 yolo detect train datadata.yaml modelruns/detect/train/weights/last.pt epochs90 lr00.001这个两阶段策略我在多个小数据集项目里用过比直接全量训练稳定最终 mAP 通常能高 2-3 个点。代价是训练时间翻倍但垃圾分类这种规模的数据集多花一两个小时换几个点精度值。最后说个习惯每次训练完别只看 mAP 数字一定把val_batch0_pred.jpg和val_batch0_labels.jpg并排看一遍。预测图和标注图放一起哪个类漏了、哪个类框歪了一目了然。这个动作帮我省了无数次盲目调参的时间。希望帮到你。本文还有配套的精品资源点击获取