news 2026/10/1 1:29:22

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 参数量约 3M,s 约 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 输出 JSON,labelImg 输出 XML,最后都要转成 YOLO 的 txt 格式。我一般用 labelImg,因为它直接支持 YOLO 格式导出,省一步转换。标注时有个血泪经验:同一类垃圾的框要尽量贴紧物体边缘,不要留太多背景。垃圾分类场景背景杂乱(垃圾桶、地面、手),框松了模型会学到背景特征,换个场景就翻车。

3. 从零跑通 YOLOv8 垃圾分类训练:环境、数据、命令

3.1 环境搭建:CPU 版和 GPU 版的分岔路

环境配置是新手第一道坎。如果你只是先跑通流程、验证代码,CPU 版够用;但要真正训练出能用的模型,必须上 GPU。GTX 1660 Ti(6G 显存)是很多人的入门卡,跑 yolov8n、batch=8、imgsz=640 没问题,再大就爆显存。

Ubuntu 20.04 上搭 CPU 版环境的最小步骤:

# 创建虚拟环境,Python 3.8-3.10 都行,3.9 最稳 conda create -n yolo_garbage python=3.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 checks

yolo checks会打印环境信息,重点看两行:PyTorch 版本和 CUDA 是否可用。CPU 版这里 CUDA 显示不可用是正常的。如果你有 GPU,把第一行 pip 换成对应 CUDA 版本的命令,比如 CUDA 11.8 用--index-url https://download.pytorch.org/whl/cu118。装完再跑yolo checks,CUDA 那行应该显示可用。

注意: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: tissue

nc和names长度不一致是最常见的报错来源,训练启动时会直接抛异常。path用绝对路径,相对路径在不同工作目录下跑会找不到文件。names的顺序就是标注时 class_id 的顺序,标错了只能重标,没有后悔药。

3.3 训练命令与关键参数逐个拆解

启动训练就一行命令,但参数含义得搞清楚:

yolo detect train \ data=/home/user/garbage_dataset/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=20 \ project=runs/garbage \ name=exp1

逐个说:

model=yolov8n.pt是预训练权重。第一次跑会自动下载,下载慢的话可以手动下好放到当前目录。用预训练权重比从零训练收敛快得多,垃圾分类这种中等规模数据集,不用预训练基本训不动。

epochs=100是最大轮数。垃圾分类数据集通常几千张图,100 轮够收敛。但别死守这个数,配合patience=20用——20 轮内验证集指标没提升就早停,省时间。

imgsz=640是输入分辨率。垃圾分类里小目标多(烟头、瓶盖),分辨率太低小目标直接糊没了。640 是平衡点,显存够可以上 800 或 960,小目标召回会明显改善。

batch=16看显存调。GTX 1660 Ti 6G 显存跑 yolov8n + imgsz=640,batch=16 差不多是上限。爆显存就降到 8,再不行降到 4。batch 太小训练不稳定,可以配合lr0调小一点。

lr0=0.01是初始学习率。YOLOv8 默认用 SGD 时 lr0=0.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"], label="train box loss") axes[0].plot(df["epoch"], df["val/box_loss"], label="val box loss") axes[0].set_xlabel("epoch"); axes[0].set_ylabel("loss"); axes[0].legend() axes[1].plot(df["epoch"], df["metrics/mAP50(B)"], label="mAP50") axes[1].plot(df["epoch"], df["metrics/mAP50-95(B)"], label="mAP50-95") axes[1].set_xlabel("epoch"); axes[1].set_ylabel("mAP"); axes[1].legend() plt.tight_layout() plt.savefig("training_curve.png", dpi=150)

看曲线有个判断标准:train loss 持续降但 val loss 开始升,就是过拟合,该早停或加数据增强。两条都降但 mAP 不涨,可能是学习率太小或类别不平衡。mAP50 到 0.8 以上、mAP50-95 到 0.5 以上,垃圾分类这个任务就算能用了。

4. 推理、验证与部署:模型训完之后干什么

4.1 用训练好的权重做单图推理和批量验证

训练完,最好的权重在runs/garbage/exp1/weights/best.pt。单图推理:

yolo detect predict \ model=runs/garbage/exp1/weights/best.pt \ source=test_images/ \ conf=0.25 \ save=True

conf=0.25是置信度阈值,低于这个值的框不输出。垃圾分类场景建议从 0.25 起步:调高到 0.5 漏检会变多,调低到 0.1 误检会变多。具体值看你的业务更怕漏检还是更怕误检——分拣线怕误检(把可回收物扔进其他垃圾),可以调到 0.4;智能垃圾桶提示怕漏检,可以降到 0.15。

批量验证用yolo detect val,它会输出每个类别的 precision、recall、mAP。重点看哪几个类别拖后腿。垃圾分类里「纸巾」和「其他垃圾」经常混淆,因为纸巾本身就是其他垃圾,标注时容易混。如果某一类 mAP 明显低,先回去查标注一致性,别急着调模型。

4.2 导出 ONNX 与边缘部署的衔接点

要在 RK3588、Orin 这类板子上部署,得先把 PyTorch 权重转成 ONNX:

yolo export \ model=runs/garbage/exp1/weights/best.pt \ format=onnx \ imgsz=640 \ opset=12 \ simplify=True

opset=12是兼容性最好的版本,RK3588 的 RKNN 工具链对 12 支持最稳。simplify=True会做图优化,去掉冗余算子,转 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 坑三:小目标(烟头、瓶盖)召回率极低

现象:大件垃圾检测正常,烟头、瓶盖这类小目标几乎检不出来。

原因:imgsz=640 下,一个烟头可能只占十几个像素,经过 backbone 下采样后特征基本消失。YOLOv8 的 P3 层虽然负责小目标,但输入分辨率不够时也无能为力。

解决:三个方向。一是提高 imgsz 到 800 或 960,显存不够就降 batch;二是数据增强里开启 mosaic 和 copy-paste,人为增加小目标密度;三是如果还不行,考虑在 head 部分加一个更高分辨率的检测层(P2),但这会显著增加计算量,边缘设备慎用。

5.4 坑四:训练到一半显存爆了

现象:前几十轮正常,突然报 CUDA out of memory。

原因:YOLOv8 默认开启 mosaic 增强,某些 batch 里拼出来的图目标特别多,显存占用波动大。另外如果开了cache=True把图片缓存到内存/显存,数据量大时也会爆。

解决:先把batch降一半试试。还爆就关掉cache,或者设mosaic=0.5降低 mosaic 触发概率。GTX 1660 Ti 6G 这种卡,跑 yolov8s + imgsz=640 时 batch 别超过 8。

5.5 坑五:转 ONNX 后推理结果和 PyTorch 对不上

现象:PyTorch 推理正常,转成 ONNX 后框的位置偏移或类别全乱。

原因:最常见的是预处理不一致。PyTorch 推理时 ultralytics 内部做了 letterbox 填充,你手动写 ONNX 推理时如果直接 resize 不填充,输入分布就变了。另一个原因是opset版本和推理引擎不匹配。

解决:ONNX 推理的预处理必须复现 letterbox:等比缩放后填充灰边到 640x640,同时记录缩放比例和填充偏移,后处理时再映射回原图坐标。别偷懒用普通 resize。导出时opset=12配合simplify=True,能规避大部分算子兼容问题。

6. 把 mAP 再往上推一档:两个我常用的微调技巧

第一个技巧是类别权重平衡。垃圾分类数据集天然不平衡——塑料瓶可能几百个,电池可能就几十个。模型会偏向多数类,少数类召回惨不忍睹。YOLOv8 本身没有直接的类别权重参数,但可以在数据集层面做文章:对少数类做过采样,或者用 copy-paste 增强把少数类实例贴到其他图上。我一般把每个类别的实例数控制在 200-2000 之间,低于 200 的类必须增强,高于 2000 的类适当欠采样。

第二个技巧是冻结 backbone 做 warmup。如果你用的是 yolov8s 以上的模型,且数据集只有一两千张,直接全量微调容易过拟合。可以先冻结 backbone 训 10 轮,让 head 先适应你的类别数,再解冻全量训。命令里加freeze=10就行,数字表示冻结前 10 层。

# 第一阶段:冻结 backbone,只训 head yolo detect train data=data.yaml model=yolov8s.pt epochs=10 freeze=10 lr0=0.01 # 第二阶段:解冻全量,小学习率微调 yolo detect train data=data.yaml model=runs/detect/train/weights/last.pt epochs=90 lr0=0.001

这个两阶段策略我在多个小数据集项目里用过,比直接全量训练稳定,最终 mAP 通常能高 2-3 个点。代价是训练时间翻倍,但垃圾分类这种规模的数据集,多花一两个小时换几个点精度,值。

最后说个习惯:每次训练完,别只看 mAP 数字,一定把val_batch0_pred.jpg和val_batch0_labels.jpg并排看一遍。预测图和标注图放一起,哪个类漏了、哪个类框歪了,一目了然。这个动作帮我省了无数次盲目调参的时间。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 1:27:16

秋招提前批与普通秋招区别及求职策略全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 1:25:48

逻辑运算符与位运算符的本质区别及安全使用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 1:24:56

JMeter性能测试实战:从环境搭建到高并发压测全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 1:24:53

SpringBoot+Vue校园社团管理系统:从源码到毕设的完整实战笔记

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华