简介:本资源是一套基于YOLOv8的垃圾分类识别系统完整实现方案,面向人工智能方向本科生、毕业设计与课程设计学习者,解决现实场景中垃圾图像自动识别与定位难题。压缩包共11个文件,含2个核心Python脚本(annotate.py用于辅助标注、rename_dataset.py支持数据集批量管理)、1个预训练模型yolov8n.pt、1个数据配置yaml文件、2张预测效果示意图(PNG)、1份项目说明README.md及必要工程配置文件(.gitignore)和系统缓存文件(.DS_Store),整体大小为10.21MB。目前已有30人学习下载,适合初学者快速掌握YOLOv8目标检测落地流程。读者可直接复现从数据准备、模型微调、预测可视化到工程化部署的全链路,尤其获得实用工具脚本、结构清晰的数据组织范式及真实场景下的检测效果参考图,显著降低深度学习项目实践门槛。 开头部分我就直接以博主口吻切入,不绕弯子。这个标题我太熟悉了,每年毕设季都能看到一堆类似的项目压缩包,但真正能把YOLOv8垃圾分类识别从数据集做到训练再到部署全链路跑通的,其实不多。这篇文章我就把整个项目的技术脉络和实操细节完整拆给你看。
1. 项目解读:这个"垃圾分类识别"到底在做什么
1.1 标题背后的真实需求
"基于YOLOv8的垃圾分类识别设计"这个项目标题,乍一看是毕设或者课设的标准题目,但它背后代表的需求其实很实在:用目标检测模型实现垃圾类别的自动识别与定位。对比分类任务,目标检测输出的是目标的类别和位置信息,也就是每个垃圾在图中的具体坐标框,这意味着后续可以接机械臂抓取、智能分拣流水线,或者终端拍照识别报警,应用场景比单纯分类要广得多。
这类项目对学生的要求不是仅仅跑通一个模型,而是要完整掌握从数据处理、模型训练、评估优化到部署落地的整个链路。YOLO系列因为工业部署成熟、代码生态完善,是这类项目的第一选择。而YOLOv8作为Ultralytics在2023年初推出的版本,相比YOLOv5,在骨干网络、头部结构、正负样本分配上都做了重构,精度和训练效率都有提升,拿来作为项目基座是要比老版本更有说服力的。
1.2 为什么选YOLOv8而不是其他模型
这个选择不是拍脑袋。实际对比过YOLOv5和YOLOv8的话会发现,YOLOv8最大的变化有三个:一是C3模块换成了C2f模块,梯度回传路径更丰富,特征提取能力更强;二是Head从耦合头改成了Decoupled-Head,分类和回归各走各的分支,收敛速度更快;三是正负样本分配从静态匹配换成了TaskAlignedAssigner,让样本分配更贴合任务难易程度。这三个改动直接带来的收益是:同尺寸模型下,mAP有小幅提升,且训练更稳定。
拿手头的GTX 1660Ti来说,6GB显存跑YOLOv8s,batch size设16、输入640分辨率,显存占用大概在4到5GB之间,能流畅训练。如果换成YOLOv8m或者更大的模型就会开始吃力,得降低batch或者开梯度累积。所以对于大多数没有高端显卡的学生党,YOLOv8s和YOLOv8n是性价比最高的选择。这个选型思路在项目里很关键,决定了你后面一系列参数怎么调。
2. 环境与数据集准备
2.1 环境配置的几个关键点
YOLOv8的环境配置本身不算复杂,因为Ultralytics把依赖打包得比较完整,用pip安装ultralytics包就行。但实际配环境的时候,有几个坑值得提前说。
首先,Python版本建议3.8到3.10之间。PyTorch方面,网上有不少人在问PyTorch 2.1.3支不支持YOLOv8,实际上Ultralytics官方对PyTorch版本没有严格限制,1.8以上的版本跑YOLOv8都没问题,只是PyTorch 2.x的torch.compile能带来一定的速度提升。不过对于1660Ti这种显卡,没必要追求太新的版本,PyTorch 1.13或者2.0.1搭配CUDA 11.7/11.8就很稳。CUDA版本再往上走驱动容易出幺蛾子。
再有一个经常被忽略的是ultralytics包和torch的版本兼容。有次我在新环境里装的是最新版ultralytics,结果它依赖的opencv-python版本和torchvision的某些底层库冲突,导致训练时随机崩溃,最后是把ultralytics降到8.0.x版本才解决。建议装的时候直接指定版本号,不要无脑装最新。
命令参考:
conda create -n yolov8 python=3.9 conda activate yolov8 pip install torch==2.0.1 torchvision==0.15.1 --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics==8.0.100装完后可以用一行命令验证环境:
yolo predict model=yolov8n.pt source=bus.jpg如果能正常跑出检测结果,说明环境没问题了。
2.2 数据集构建与标注实操
垃圾分类的数据集,公开的有华为的垃圾分类数据集、TrashNet、以及一些Kaggle上的垃圾分类集合。TrashNet是比较经典的一个,包含玻璃、纸、金属、塑料、纸板、一般垃圾六类,大概两千多张图,作为入门训练集够用了。但如果想要更好的效果,更推荐自己采集加公开数据混合,因为公开数据集的场景单一,真正部署到实际场景时泛化能力会差很多。
数据标注是另一个大头。网上搜"yolov8数据标注具体操作"的人特别多,其实核心就三步:装标注工具、画框、导出成YOLO格式。工具上LabelImg和LabelMe都行,LabelImg更轻量,适合矩形框标注;LabelMe支持多边形,适合形状不规则的物体。分类垃圾的场景,矩形框足够,用LabelImg就行。
标注完成后,LabelImg默认导出的是Pascal VOC格式的XML文件,需要转成YOLO格式的txt。YOLO格式每个txt文件对应一张图片,每行是"类别id x_center y_center width height",坐标值是归一化到0到1之间的。转换脚本自己写就行,网上也有一堆现成的,但强烈建议自己写一遍,理解格式转换的逻辑,后面排查问题会省很多事。
数据集目录结构要按照YOLO的约定来:
dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/最后写一个data.yaml文件,里面指定路径、类别数和类别名称。路径这块要特别注意,最好用绝对路径,因为Ultralytics在部分版本里对相对路径的解析有bug,训练时会报找不到图片。
3. 模型训练与核心参数选择
3.1 训练文件的修改要点
YOLOv8的训练入口有两种方式:一是直接用命令行yolo train,二是写Python脚本调YOLO类。项目实践中我更推荐用Python脚本,因为参数可以写死在代码里,可复现性更好,也方便后面做实验记录。
关键配置就三个文件:data.yaml、模型yaml、训练脚本。如果你用的是官方预训练权重微调,模型yaml(yolov8s.yaml)不需要改太多,主要改nc参数为你的类别数。data.yaml里nc和names必须和标注的id一一对应,这里最容易出错,类别顺序对不上,训练出来的模型预测结果全是乱的。
训练脚本的参考写法:
from ultralytics import YOLO model = YOLO('yolov8s.yaml').load('yolov8s.pt') model.train( data='data.yaml', epochs=100, imgsz=640, batch=16, device=0, workers=4, optimizer='SGD', lr0=0.01, cos_lr=True, patience=20, cache=True, project='runs/detect', name='garbage_cls' )有人问load('yolov8s.pt')和直接YOLO('yolov8s.yaml')的区别:加载预训练权重是迁移学习,训练收敛快、精度高,尤其适合数据量不大的垃圾分类项目;不加载预训练权重是从零训练,需要的数据量和时间都多得多。数据量没有上万张的话,务必用预训练权重微调。
3.2 训练参数的深度解读
超参数这块是很多人稀里糊涂的地方。先说epochs,不是越大越好。垃圾分类数据集通常在几千张的量级,100个epoch左右基本就收敛了。我习惯加上patience=20做早停,连续20轮验证集指标不提升就自动停止,省时间还防止过拟合。
batch size的确定要看显存。1660Ti的6GB显存,yolov8s跑batch 16是极限了,再大就OOM。如果显存不够,有两个办法:一是减小imgsz,从640降到512,显存占用能低不少,但小目标检测精度会下降;二是开启梯度累积,Ultralytics里虽然没有直接参数,但可以通过减小batch配合手动梯度累积来实现,不过操作麻烦,不如直接换yolov8n模型。
说到yolov8n,这是YOLOv8系列里的轻量级版本,参数量只有3.2M左右。如果训练设备实在太拉胯(比如只有4GB显存的笔记本),yolov8n是能跑起来的底线。代价是精度会比s版本低一些,但对垃圾分类这种类别间外观差异大的任务来说,n版本的精度也够用。
优化器选择上,SGD和AdamW都在用。我的经验是:数据量小、预训练权重微调,SGD配cos_lr往往能磨到更好的局部最优,尤其对mAP50-95这类指标更友好;AdamW收敛更快,前期loss下降猛,适合快速看效果。我一般先用SGD跑一版完整的,再用AdamW跑个30个epoch做对比,取验证集指标高的那个。
训练过程中的损失函数曲线怎么看?YOLOv8训练会输出train/box_loss、train/cls_loss、train/dfl_loss以及对应的验证集版本。正常情况是随着迭代次数增加,所有loss都在下降然后趋于平稳。如果发现验证集loss在下降一段后反弹,那就是过拟合了,可以加数据增强、降低学习率或者提前停止。Ultralytics的训练日志会存成result.csv文件,直接用Excel或者Python的pandas画曲线图都行,网上搜"yolov8画损失函数曲线图"能找到很多工具脚本,但自己写一个也就是几行matplotlib的事。
4. 模型评估与改进落地
4.1 评估指标不只是看mAP
训练结束后,Ultralytics会在runs/detect/name/目录下保存weights、混淆矩阵、PR曲线、验证集预测图等文件。很多人只看一眼mAP50就认为完事了,其实不够。
对垃圾分类项目,我建议重点看三个东西:一是混淆矩阵,能直接看出哪些类别之间容易互相认错,比如纸和纸板这类外观相近的类别;二是PR曲线,观察精确率和召回率的平衡点,如果PR曲线下的面积(AP)在某个类别特别低,说明这个类别的训练样本可能不够或者标注框质量差;三是看验证集的可视化预测图,确认预测框位置是否贴合真实物体边界,有没有漏检或误检。
如果在训练时设置了plots=True,这些图会自动保存在训练目录下,非常方便。
4.2 从C2f到注意力机制:YOLOv8改进方向
垃圾分类项目做到一定程度,为了拿高分或者提升效果,很多人会去研究YOLOv8改进。这个方向非常深,但也确实能提点。最近两年比较火的改进方向主要有三个:注意力机制、特征融合结构、下采样方式。
注意力机制这块,最常见的是在C2f里插入SE、ECA、EMA或者CBAM模块。其中EMA注意力机制(Efficient Multi-Scale Attention)和ECA(Efficient Channel Attention)都是轻量级方案,不会给模型增加太多参数量,但对精度的提升是实打实的。具体操作上,网上有人分享将EMA融入YOLOv8的C2f模块的代码,核心就是在C2f的Bottleneck里插入一个EMA分支,然后修改yaml文件中的模块配置。我自己试过把ECA塞进C2f里,在垃圾数据集上mAP50-95大概涨了1到2个百分点,代价是推理速度慢了约10%,可以接受。
另外还有一个常见的改进是替换下采样模块,把普通的Conv下采样换成ADown。ADown是YOLOv9里提出的结构,主要思路是在下采样时用平均池化和卷积并行提取特征再融合,能减少信息丢失。改起来也不难,在ultralytics的nn/modules/block.py里定义一个ADown类,然后在yaml里把对应位置换成ADown就行。这类改进的本质就是让特征图在下采样过程中保留更多细节,对小目标垃圾的检测有帮助。
需要提醒的是,改模型结构不是改完就万事大吉,训练需要重新跑,而且因为结构变了,加载预训练权重时会出现部分层不匹配的情况,需要把strict参数设为False只加载匹配的层。这个细节很多人忽略,导致训练半天发现精度还不如原版。
4.3 端侧小模型与速度优化的平衡
垃圾分类最终如果要做成手机App或者嵌入式设备上的应用,模型大小和推理速度就必须纳入考虑。YOLOv8官方提供了n/s/m/l/x五个尺寸,从n到x精度递增、速度递减。手机上用的话,yolov8n是最合适的,量化成INT8后模型只有几MB,推理一帧能在几十毫秒内完成。
如果想主动压缩模型,可以考虑剪枝和蒸馏。剪枝最简单的方式是通过结构化剪枝把通道数降下来,但这个操作比较复杂,需要自己写剪枝逻辑。蒸馏相对友好一些:用yolov8l或者yolov8x当老师模型,yolov8n当学生模型,让学生模型学习老师模型的输出分布。在垃圾分类这类中等难度的任务上,蒸馏后的n模型精度可以接近s模型,但体积和速度优势明显。
对于1660Ti训练的用户,还有一个细节值得注意:开启AMP混合精度训练能显著减少显存占用和训练时间,Ultralytics默认就开着AMP开关,不用额外配置。但有个别显卡驱动版本和AMP不兼容,表现为loss出现NaN,如果遇到这种情况,把amp=True改成amp=False关掉就行。
5. 模型导出与部署实践
5.1 导出ONNX与嵌入式部署
训练好的模型,最终要落地。YOLOv8官方支持导出ONNX、TensorRT、OpenVINO、CoreML、TFLite等多种格式,一条命令就能搞定。最常用的中间格式是ONNX,因为绝大多数嵌入式平台的推理框架都支持转ONNX再转自家格式。
导出ONNX的命令:
yolo export model=best.pt format=onnx opset=12 simplify=True这里simplify=True会用onnx-simplifier对模型进行简化,去掉一些冗余算子。导出后建议用onnxruntime跑一遍验证输出是否正常,避免导出出的模型算出来的结果和PyTorch原模型差太多。
很多人关心YOLOv8的模型怎么输出成C语言格式,其实走了弯路。一般在嵌入式平台上都是通过推理框架来调用,比如瑞芯微RK3588上用RKNN-Toolkit把ONNX转成RKNN格式,然后写C++或者Python代码调用RKNN的API推理。直接输出C语言数组的形式适合没有NPU的裸机环境,但实际项目里很少这样干。
5.2 RK3588等嵌入式平台的迁移要点
RK3588部署YOLOv8是目前特别火的方向,因为它自带6 TOPS算力的NPU,跑yolov8s可以做到实时。但部署过程有不少坑。
最大的坑是RKNN-Toolkit对YOLOv8的支持版本问题。早期版本的RKNN-Toolkit不兼容YOLOv8的输出结构,需要自己在模型里改动,后来RKNN-Toolkit2更新到1.5以上版本才原生支持。所以在部署前一定要确认你用的RKNN-Toolkit版本,版本太低的话识别结果全乱飘,那不是模型的问题,是转换工具的问题。
另一个坑是量化。RKNN默认用INT8量化来换取速度,但量化需要准备校准数据集,一般从训练集里挑几百张有代表性的图片就够。校准数据选不好,量化后的模型精度会断崖式下跌。我踩过这个坑,第一次用全黑图片做校准,量化后模型几乎瘫痪,后来换成包含各类垃圾的200张图片,精度才恢复正常。
嵌入式端部署还有几个实际问题:一是输入图像的预处理方式要保持和训练一致,YOLOv8用的是letterbox加RGB归一化到0到1,不能搞错;二是输出的后处理,模型输出的是一堆预测框信息,需要做NMS非极大值抑制,这部分在PC上用ultralytics自带方法就行,但在嵌入式平台上要自己写或者用平台提供的NMS算子;三是内存管理,NPU推理时输入输出的Tensor格式和大小要提前分配好,否则反复申请释放内存会导致帧率不稳。
5.3 手机端的部署思路
手机端部署YOLOv8,主要包括Android端和iOS端。Android上常用NCNN或者MNN框架,先把YOLOv8导出成ONNX再转成NCNN的格式。网上搜"yolov8手机安装包"能找到不少打包好的APK示例工程,但直接跑别人的APK意义不大,真正要做的是自己用Android Studio和NCNN编译一个检测App,把YOLOv8模型集成进去。
手机端需要注意的问题是算力限制。即便旗舰手机,运行yolov8s的耗时也要在100毫秒以上,yolov8n才能做到流畅。所以手机上一般用yolov8n加上INT8量化,同时考虑NPU加速或者GPU加速。Android端的NCNN支持Vulkan GPU加速,可以明显提升推理速度,但需要自己配置好vulkan环境。
我自己试过在骁龙888上跑yolov8n的INT8模型,输入尺寸320,单帧推理时间大概在30到50毫秒之间,已经接近实时了。如果是做垃圾分类的演示App,这个性能完全够用。
6. 常见问题与排查技巧实录
6.1 训练阶段的典型问题
问题一:训练时显存溢出(OOM)
这是最常见的问题。如果1660Ti跑yolov8s batch 16直接OOM,先把batch降到8试试;还不行就用yolov8n。另外关闭cache=True参数(这个参数会把图片缓存到显存加速读取,但显存占用会大增),以及把workers调低减少内存开销,都是缓解办法。
提示:训练时如果看到一个Epoch突然卡住然后报CUDA out of memory,不一定真的显存不够,可能是数据加载worker进程占用了过多CPU内存导致的。把workers从8降到2,问题往往能解决。
问题二:loss为NaN
Loss变成NaN是训练中让人头大的问题。常见原因有两个:一是学习率太高,把lr0从0.01降到0.001;二是AMP混合精度问题和驱动不兼容,把amp关掉试试。还有个别情况是数据标注文件里有空框或者坐标越界(比如框的坐标值大于图片尺寸或者出现负数),这类数据会让模型计算损失时出问题,排查时要检查所有txt标注文件,确保每行都是有效的正数坐标。
问题三:训练完模型预测效果很差
如果训练时mAP看着不错,但自己拿照片测试时效果很差,大概率是训练集和测试集的数据分布不一致。比如训练集里的垃圾图片都是白色背景单独摆放的,测试时你拿厨房里杂物堆叠的照片去预测,模型当然扛不住。解决方法是训练时增加数据增强的强度,或者在数据集里掺入更多场景复杂的图片,让模型见过更多"世面"。
6.2 推理与部署阶段的典型问题
问题一:导出ONNX后推理结果不对
导出的ONNX用onnxruntime推理出来的框和PyTorch原模型不一致,最常见的坑是预处理不一致。YOLOv8训练时的预处理是letterbox缩放加归一化,ONNX推理时你要用一模一样的预处理方式,尤其是letterbox的填充值(默认是114)不能搞错。另外一个坑是推理后输出Tensor的解码方式,YOLOv8输出的是一个1x84x8400的Tensor(以80类为例),需要做维度变换、阈值过滤和NMS,很多人在这一步写错了索引导致结果错乱。
问题二:嵌入式平台推理速度慢
NPU推理速度不达标,最常见的原因是模型某些算子没有跑到NPU上而跑到CPU上了。RKNN-Toolkit在转换模型时会输出日志,如果发现某些层的runtime是CPU而不是NPU,就要检查该层是不是有不支持的算子。解决思路是把模型里的一些自定义模块替换成标准算子,或者改模型结构避开不支持的层。还有一个常见原因是输入分辨率设得过大,嵌入式场景下320到480的分辨率足够,没必要硬上640。
问题三:类别ID对应错误
这个问题在部署后尤为致命。模型输出的是类别ID(比如0代表纸板),你在后端写业务逻辑时把0对应成了玻璃,那整个系统就全乱了。解决方法是部署时写好一个类别映射表,用data.yaml里的类别顺序,不要自己记一个顺序,最好从配置文件中读取。
6.3 数据标注阶段的避坑指南
标注阶段的问题通常会延迟到训练和评估时才暴露,排查成本极高。这里分享几个容易踩的坑。
第一,标注框要尽量贴合物体边缘。很多人标注垃圾时喜欢随手拉一个大框,把物体周围的环境背景也框进去。这样做的后果是模型学到的是"背景+物体"的组合特征,一旦物体换了环境就识别不出来。正确做法是让边界框四边紧贴目标物体的边缘,哪怕是物体的边缘有阴影或者反光,也要坚持贴合实际轮廓。
第二,类别不平衡要提前处理。垃圾分类数据集中,塑料瓶的图像数量可能远多于玻璃碎片或者有害垃圾。如果不处理,模型对少样本类别的召回率会很低。解决方法是先统计每类的图片数量,对少样本类别做数据增强复制(比如水平翻转、旋转、亮度变化),或者用在线数据增强让模型在每个epoch看到更多少样本类的变体。
第三,标注文件的命名要和图片文件严格对应。YOLO格式要求每张图片xxx.jpg对应一个xxx.txt,如果命名不对,训练时该图片会被当成无标注图片跳过,白白浪费数据。检查方法很简单:统计数据集里的标注文件数和图片文件数是否一致,不一致的话就是有配对问题。
第四,不要一个人闷头标所有数据。如果条件允许,找两三个人一起标,然后交叉检查。每个标注者对"物体边界在哪"的理解不同,个人风格会导致标注框尺度不一致,这种噪声会直接影响回归头的收敛。交叉验证可以在标注阶段就过滤掉那些明显的错误框。
6.4 时间成本与项目管理的心得
最后聊点项目管理的经验。垃圾分类识别这类项目,最耗时间的往往不是写代码和训练,而是数据准备。我自己做的时候,采集加标注大概用了两周,训练和调参用了不到三天。所以如果你在赶时间,千万别压缩数据准备的时间,后续的坑全是从这里埋下的。
合理安排流程的话,我会建议:第一天先配置环境并跑通一个yolov8n的官方预训练模型,验证代码全链路通畅;接下来一周专门做数据采集和标注;标注完成后写数据转换脚本并做EDA(探索性数据分析),检查类别分布和标注质量;然后再花两到三天训模型、调超参;最后留一两天做部署和文档整理。这样排下来,整个项目三周内能顺利交付。
还有一点,项目中所有实验要养成记录的习惯。比如训练时用了什么超参数、改了什么模型结构、验证集指标是多少,全部记下来。不要觉得这是浪费时间,当你面对十几个实验结果不知道选哪个时,一份好的实验记录能帮你快速定位和复盘。我习惯在每次训练时把配置参数复制一份到notes里,训练结束后把mAP截图和混淆矩阵也一起记录,最后写报告时非常轻松。
对于想再往上一步的读者,你可以尝试把垃圾分类从检测扩展到实例分割(YOLOv8-seg),或者结合跟踪算法(ByteTrack)做一个视频流的实时分拣方案,甚至可以把这个识别能力封装成API接入手淘的流水线。技术底座搭好后,扩展的方向就完全看你自己的想象力了。
本文还有配套的精品资源,点击获取