ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLO垃圾四分类实战:从数据集构建到嵌入式部署全指南

YOLO垃圾四分类实战:从数据集构建到嵌入式部署全指南 简介垃圾分类是环保智能化的重要环节YOLO四分类数据集面向目标检测初学者、算法工程师及环保项目开发者提供覆盖可回收垃圾、有害垃圾、厨余垃圾和其他垃圾四类目标的标注数据。每一张图片对应的txt标注文件记录了目标类别与边界框位置共含1999个标签文件另有1个yaml文件用于配置类别名称与训练路径压缩包整体约540.75MB契合YOLOv5、YOLOv8等主流模型的训练输入要求。到目前为止已有2086人学习使用该数据集数据组织清晰、标注规范可直接下载后投入训练与验证。借助这批数据开发者能够节省大量人工标注时间快速搭建垃圾分类识别系统并根据真实场景进行模型调优进而提升分类准确性与分拣效率为垃圾自动回收和资源再利用提供可靠的数据支撑。1. 项目概述1.1 先聊一下这个项目打算解决什么问题垃圾分类这事听起来简单真做起来一堆麻烦。小区垃圾房旁边几个桶排成一行上面贴着分类指南但大家丢垃圾的时候照样犹豫——这个沾了油的披萨盒是纸还是厨余用过的湿纸巾是其他还是可回收我做过一段时间社区环保相关的视觉项目发现真正缺的不是宣传单而是能自动识别垃圾类别的前端设备。于是就有了这个从零开始打造YOLO垃圾四分类数据集的计划目标是训练一个能通过摄像头实时识别垃圾所属类别的模型再挂到嵌入式设备上放在垃圾房旁边当“AI督导员”。这个项目选YOLO做检测模型是深思熟虑的。市面上做垃圾分类的算法不少有拿ResNet做图像分类也有拿Faster R-CNN做检测的但实际部署到现场后能稳定跑实时推理的没几个。YOLO系列走到现在yolov8、yolov9甚至yolo v10都已经比较成熟了速度、精度、部署链路三方面都均衡社区生态也足够好。相比分类模型检测模型能在画面里同时定位多个垃圾框出一个“可回收塑料瓶”和框出整张图片是“可回收”后者对后续机械臂抓取或者人机交互都有意义。四分类是参考国内常见的生活垃圾分类标准可回收垃圾、厨余垃圾、有害垃圾、其他垃圾。数据集的核心工作是采集足够多的实拍图片完成标注转成YOLO训练需要的格式然后在这个基础上把检测模型训起来最后落到一个能用的推理服务上。整个过程看起来不复杂但拖垮项目的往往不是模型训练而是数据集的细节——类别不平衡、标注框不规范、场景单一导致泛化差这些问题后面展开讲。1.2 为什么数据集才是整个项目的核心很多初学者拿到yolov8就开始跑train跑出来的模型在验证集上看着挺像回事一换环境就废了。问题几乎都出在数据上。YOLO对标注格式很敏感对图像质量和多样性也极其挑剔。一份烂数据集喂给再好的模型产出也是烂结果。垃圾识别这个场景有一个特殊难点垃圾本身长什么样跟“场景”强相关。同样一个塑料瓶在干净的室内桌面上拍和躺在湿漉漉的垃圾桶里拍特征是两回事。阳光下、夜晚、荧光灯下颜色和纹理都会变化。真实场景里垃圾往往互相遮挡、堆叠、变形甚至已经破裂。所以这个数据集必须包含大量真实环境图片不能只在网上爬点干净图就开训。2. 数据集的整体设计与采集策略2.1 四分类的类别定义与样本规划做分类任务之前先把类别边界定义清楚。我做的四分类参照《生活垃圾分类标志》标准设定为可回收垃圾塑料瓶、纸箱板、易拉罐、玻璃瓶、旧衣物、塑料袋厨余垃圾剩菜剩饭、果皮、蔬菜残叶、骨头、蛋壳有害垃圾废电池、废灯管、过期药品、油漆桶其他垃圾烟蒂、陶瓷碎片、受污染的纸巾、一次性餐具这里有个关键点像“塑料袋”这种物品其实是典型的边界模糊项。干净塑料袋是可回收沾了油污就是其他垃圾。做检测模型的时候不能过度纠结这种细枝末节否则标注一致性会崩掉。我的处理方式是在数据集的标注规范里写清楚脏污塑料袋归到其他垃圾。如果你打算复现这个项目建议先把类似的边界清单列好让所有标注人员按同一套规则执行不然标注返工能让你怀疑人生。样本数量规划上每个类别我至少采集了1200张有效图片整个数据集总量在5000张上下。考虑到真实场景中可回收垃圾和厨余垃圾出现频率远高于有害垃圾如果按等量采集模型会对有害垃圾的少数类别学习不足。我的做法是可回收占30%厨余占30%其他占25%有害占15%。有害垃圾样本少是因为真实场景里确实少见再通过后续数据增强补足。2.2 图像采集的真实环境策略采集图片是我踩坑最多的地方。第一次偷懒从搜索引擎批量下载了上千张垃圾图片训出来的模型在测试视频里惨不忍睹——换个光线就找不到瓶子了。后来老老实实重新采集原则是“哪里用就在哪里拍”。我带着摄像头和手机跑了三个地方小区垃圾房、餐饮店后厨、办公楼楼道垃圾桶。分别对应室外半开放场景、室内强光场景和弱光环境。每个场景拍相同比例的目标类别保证模型不会过拟合到单一背景。在垃圾房拍照的时候要注意角度。摄像头会安装在桶的上方斜45度左右所以采集时要模拟这个视角不能总是俯拍90度。垃圾堆放状态也分了三种散落在地面、堆在桶内、单个放置。尤其是桶内状态目标与垃圾桶边缘有大量遮挡这个一定要有否则实际部署时模型会在桶内物体上疯狂漏检。光线问题没法回避。垃圾房白天和晚上的光照差异极大如果只在白天拍晚上开灯后色温一变模型就瞎了。我一共分三个时间段采上午九点到十一点、下午两点到四点的自然光晚上七点到九点的灯光环境。实测下来晚上单独补充了大约500张图片把白平衡偏移的样本喂进去之后夜间识别率才勉强达标。2.3 标注流程与工具选择标注是个体力活但工具选对了能省一半力。市面上常用三款LabelImg、labelme、Roboflow。我的体感是LabelImg写YOLO格式最直接输出txt文件一次到位适合离线操作。labelme输出json适合多边形标注但我做检测只需要矩形框杀鸡用牛刀。Roboflow有在线团队协作功能自带数据增强和导出多格式缺点是免费额度限制较多。最终选了Roboflow做主力本地用LabelImg做补充。原因是标注这种单调工作一个人干容易疲劳出错Roboflow可以拉两个标注员同步干活管理者在线检查实际标注质量。对于单枪匹马的个人项目LabelImg完全够用照着图形界面画框导出时自动生成YOLO格式的txt。标注规范这里要讲透。YOLO的矩形框是“物体最小外接矩形”要求框尽量贴合目标边缘但允许压缩到最多露出5%的背景。单张图片里每类目标都要标哪怕目标只有十几个像素大能看清轮廓就标。不考虑标注多个角度重叠的复杂情况遮挡超过50%的目标可以不标但遮挡低于50%必须标出可见部分。这里有个容易犯错的点标注文件里的坐标不是像素值是相对比例。YOLO格式的txt每行是“class x_center y_center width height”全部归一化到0~1。举例一个瓶子在640x480的图里检测框左上角是(160,120)右下角是(320,360)换算后x_center是0.375y_center是0.5width是0.25height是0.5。写标注脚本的时候直接用像素值除以图片宽高即可但要注意除法得到的浮点数精度别丢否则训练时框的位置就偏了。3. 数据集格式转换与增强实践3.1 Roboflow导出与目录结构整理标注完成后从Roboflow导出时可以直接选YOLOv8格式。它会自动划分train、valid、test三个子集默认比例是70/20/10。强烈建议用这个划分而不是自己随便切分——Roboflow保证同源图片不会被分到两个集合里避免数据泄漏导致的虚高指标。导出的压缩包解压后目录结构是这样的dataset/ ├── train/ │ ├── images/ │ └── labels/ ├── valid/ │ ├── images/ │ └── labels/ ├── test/ │ ├── images/ │ └── labels/ └── data.yamldata.yaml里记录类别名和对应索引YOLOv8训练时会自动读取。有一点容易被忽略数据增强处理后的图片数量和原图不完全对应Roboflow会在文件名上加上随机后缀所以不要用文件数量去核对增强比例。真正要核对的是每个类别的实例数量而不是图片数量。3.2 数据增强哪些有效哪些是自我感动Roboflow自带的增强选项很多但我建议克制。有些增强对垃圾识别有效有些纯属帮倒忙。实测下来有效的是这几类亮度调整-15%到15%模拟不同光照条件噪声注入最高5%模拟低光环境下的传感器噪点水平翻转扩充左右方向变化。RGB通道偏移也有一点效果模拟色温变化。旋转增强我不建议开太多尤其不要开到90度以上。因为瓶子、纸盒这类物体有明显的竖直方向特征旋转90度后语义上是错的——横着的可乐瓶确实存在但概率低强行增加这种样本反而干扰模型学习。剪裁增强要控制范围我用的是0到20%目标区域占画面太大时剪裁容易把关键特征切掉。整个增强配合下来训练集从5000张扩到了约14000张但验证集和测试集保持纯净没有做任何增强。这点特别重要否则你无法判断模型提升到底是学到了通用特征还是记住了增强后的噪声。3.3 处理类别不平衡的办法按2.1节的规划有害垃圾只有约750张原图即使增强后也就2100张左右比其他类别少一截。直接训练的话模型在有害垃圾上的mAP大概率会掉5个点以上。解决思路有三种我从简到繁都试过。最简单的是在data.yaml或训练参数里给稀有类别加权重YOLOv8支持按类别设置loss权重把有害垃圾的权重提到1.2到1.5。第二种是复制少数类样本做过采样但要用不同的增强参数跑两遍不然模型容易过拟合到同一批样本。第三种是我最后实际采用的给有害垃圾类别增加“合成样本”——把电池、灯管抠出来贴到不同背景的图上再适当旋转、缩放生成新图片。这样做出来的数据虽然带有合成痕迹但对模型学习“电池长什么样”帮助极大。3.4 自制转换脚本的坑如果你不用Roboflow打算完全本地走LabelImg标注再转格式我给你看一个我自己写的小脚本框架避免重复造轮子import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, class_names, out_dir): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_names: continue idx class_names.index(name) box obj.find(bndbox) x_min int(box.find(xmin).text) y_min int(box.find(ymin).text) x_max int(box.find(xmax).text) y_max int(box.find(ymax).text) # 归一化注意防止除零 x_center ((x_min x_max) / 2) / img_w y_center ((y_min y_max) / 2) / img_h w (x_max - x_min) / img_w h (y_max - y_min) / img_h lines.append(f{idx} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_dir .txt, w) as f: f.write(\n.join(lines)) class_names [recyclable, kitchen, harmful, other]注意几个细节坐标归一化时x_center如果小于0或大于1说明框出界了要回头检查标注width或height算出负数是坐标顺序反了需要交换x_min/x_max。这类脚本错误不会报错会悄悄污染整个数据集训出异常模型你都不知道问题在哪。建议写脚本后先跑一个全量统计检查所有txt里的数值是否都在0到1之间。4. 基于YOLOv8的训练与效果调优4.1 环境配置与硬件选择训练之前先把环境跑通。我用的是YOLOv8直接pip安装pip install ultralytics硬件方面很多人问AMD RX 580显卡能不能跑YOLOv8我正好踩过这个坑。RX 580是GCN架构的老卡PyTorch官方对AMD的GPU支持主要走ROCm路线但ROCm对GCN架构的支持非常有限Windows下基本没有可用方案。如果你手上只有这块卡我的建议是不要硬刚本地环境直接用Google Colab的免费GPU跑训练或者租个云GPU卡。我自己训练用的是Colab的T48GB显存跑yolov8s模型、batch size设为16完全没问题。如果你坚持本地跑在Linux下装ROCm 5.7版本碰碰运气过程比较折腾性能还会打折扣不推荐。显存不够时的另一个实用思路换更小的模型版本。yolov8n参数量只有3.2M一张8GB卡轻松带起来batch 32也没压力。代价是精度会掉一些但对于垃圾识别这种相对粗粒度的检测yolov8n的精度完全够用而且推理速度快一倍以上。4.2 训练参数与调优细节配置文件准备好之后训练命令很简单yolo detect train data/path/to/data.yaml modelyolov8s.pt epochs100 imgsz640 batch16 device0这里几个关键参数值得展开说imgsz选640是YOLOv8默认值适合大多数场景。如果你的垃圾目标普遍偏小比如画面里瓶子只有30x30像素建议把imgsz提到768或832小目标识别率会有明显提升代价是训练时间和显存占用同步上涨。epochs我建议先用100跑一轮观察验证集指标变化。YOLOv8自带早停策略连续训练多个epoch验证指标不涨会自动停止。不要盲目追求300个epoch实测垃圾数据集在100到150个epoch时已经收敛再训练只是过拟合训练集验证集mAP反而往下掉。batch size的选择直接受显存约束。目标检测训练时batch越大梯度越稳但不要为了大batch被迫降低imgsz优先保证图片分辨率。8GB显存配yolov8s、imgsz640时batch 16是安全值。如果你用yolov8nbatch可以拉到32。训练完之后不要只盯着mAP50看。mAP50是IoU阈值0.5下的平均精度对框的位置要求比较宽松。更要紧的是mAP50-95它综合了多个IoU阈值下的精度。我在实际项目里遇到过mAP50高达0.93但mAP50-95只有0.52的情况说明模型能大概找到目标位置但框的精确度差。对于垃圾识别场景后续如果要接机械臂抓取mAP50-95比mAP50重要得多。如果mAP50-95偏低优先检查标注框的紧密度而不是换模型。4.3 训练结果评估与常见问题定位训练日志里有一个confusion_matrix.png文件这个要仔细看。它展示的是每个真实类别被预测成哪个类别的比例。我在第一版模型里发现可回收垃圾有12%被预测成了其他垃圾顺着混淆矩阵倒查原因发现是标注时把被压扁的纸箱框得过于宽松框内混入了大量背景区域模型学到的是“那个位置的纹理”而不是纸箱本身。loss曲线同样能暴露问题。YOLOv8的loss分box_loss、cls_loss和dfl_loss三部分。如果cls_loss持续下降但是box_loss卡住不动大概率是标注框质量不高需要重新审视训练集里的框是否贴边。如果两类loss都在降但验证集mAP纹丝不动大概率是过拟合开始了早停阈值调低一点。当然训练集里的脏数据也会在评估阶段露出马脚。我遇到过一次验证集图片里出现了训练集同款背景的图片导致验证集精度虚高。后来核对了Roboflow的划分逻辑确认它不会有这个问题但如果你完全自己划分数据务必加上图片哈希去重防止同场景图片串了集。5. 部署推理与边缘设备适配5.1 模型导出与轻量化处理训练收敛后最后一轮模型是weights/best.pt。这个weights文件用在Python环境里做推理没问题但部署到边缘设备或摄像头端一般要转成ONNX或者TensorRT格式。YOLOv8自带导出命令yolo export modelbest.pt formatonnx imgsz640 opset12 yolo export modelbest.pt formatengine device0 # TensorRT导出ONNX是中间格式好处是跨平台通用但推理效率一般。TensorRT是NVIDIA显卡上的加速方案能把推理速度提升2到4倍。如果你的部署目标是Jetson系列的设备TensorRT是标配如果只是普通电脑上用CPU推理ONNX配合OpenVINO也是可行的。我在树莓派上用ONNX Runtime推理时发现一个坑模型输入尺寸必须固定。训练时用的imgsz640导出后输入就是640x640。实际摄像头画面往往也是640x480或1920x1080需要做letterbox变形把长边缩放到640短边补灰边。这一步如果处理不好目标物会被拉伸变形检测框位置也会偏。建议用ultralytics的LetterBox实现不要自己写缩放细节上容易出错。5.2 摄像头实时检测的工程细节推理服务跑起来之后下一步是接摄像头。如果是USB摄像头分辨率设置不要太贪1080p在树莓派上处理一帧可能就要几百毫秒实时性完全崩了。实测640x480分辨率下yolov8n推理大约18到25毫秒加上预处理和后处理可以达到接近30帧的流畅度。完整推理代码参考import cv2 from ultralytics import YOLO model YOLO(best.onnx) cap cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while True: ret, frame cap.read() if not ret: break results model.predict(frame, imgsz640, conf0.35, devicecpu) annotated results[0].plot() cv2.imshow(Garbage Detection, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()注意conf参数的设置。置信度阈值不是越高越好在垃圾房这种远距离、低光环境下识别置信度普遍偏低。我用0.25试过误检太多用0.5又漏检不少。最后调在0.35到0.4之间实际效果最均衡。部署环境千差万别这个值要现场实测再定。还有一个容易忽略的点平铺在地面的垃圾目标小容易漏检。如果你发现大量目标被漏掉可以尝试把imgsz提到768或832重新导出模型。代价是推理时间变长但对小目标有肉眼可见的提升。我后面在做夜间识别的时候就是这么干的。6. 常见问题与避坑经验速查6.1 数据集类问题现象可能原因解决办法验证集mAP高但现场识别差训练/验证数据同源泄漏用哈希去重保证场景多样性某类目标永远检测不到类别样本太少或标注框严重不准增加该类样本重点检查标注质量同一目标被重复框出NMS阈值过低或标注框重叠调高NMS阈值到0.6以上检查标注是否重复靠近画面边缘的目标识别不了训练样本里目标大多在中心区域采集时故意把目标放在画幅四角部位6.2 训练和部署常见坑训练时看到loss已经降得很低但mAP始终上不去多半是标注坐标出了问题。我曾经有一次因为脚本里没有把x_center归一化为浮点数导致所有框的x坐标都被四舍五入成整数看起来没毛病但框全部偏向画面左侧。这种问题只能靠统计标注分布来发现只要宽度方向的坐标分布明显不均匀就要怀疑转换脚本。部署时的一个大坑是ONNX模型的输入名称不同。YOLOv8导出的ONNX输入名是images但有些老版本是input加载模型时最好先打印一下输入层信息import onnxruntime as ort sess ort.InferenceSession(best.onnx) print(sess.get_inputs()[0].name)之前照着网上的旧教程写死了输入名结果模型加载后推理结果全乱排查半天才找到问题。TensorRT导出还有一件要注意的precision。FP16精度在大多数情况下没问题但FP8混合精度在某些显卡上会导致框的位置偏移。垃圾识别场景对精度要求不高FP16已经能跑到毫秒级所以不是太追求极致性能的话不需要冒险用FP8。6.3 关于泛化能力的最后提醒很多读者拿到这个教程就开始照做但我必须强调一点垃圾四分类看起来类别简单但不同地区的生活习惯差异极大。北方城市的厨余垃圾以白菜帮子、土豆皮为主南方城市会有大量甘蔗渣、玉米衣。如果你的项目要落地到一个具体城市只靠网上数据训练出来的模型是根本扛不住的必须在目标现场补采一定比例的本地数据再微调。我后来给模型做持续迭代的时候采用了“每周增补训练”的方式把现场部署后摄像头拍到的新样本定期拉回来筛选出置信度低或预测错误的图片由人工重新标注后合并进训练集重新训练。这样每轮微调只增加几百张图cost不高但模型的鲁棒性在持续变好。这已经脱离了“一次性训练模型”的范畴变成了一套有闭环的数据运营流程这才是一个实际部署的AI项目应该有的样子。如果你做的是个人学习项目数据集规模可以压缩到每类300到500张先跑通整个流程看效果。但真实的落地项目数据工作的比重至少要占七成以上。训练模型只是最后那一哆嗦前面大量枯燥枯燥的采集、标注、清洗、增强才是决定模型上限的关键。本文还有配套的精品资源点击获取
返回列表