做过图像识别方向的朋友应该都清楚,垃圾分类检测系统这几年几乎成了计算机视觉入门项目的标配。但真正把它从"跑通一个Demo"做到"能在现场稳定工作",中间隔着的距离比大多数人想象的要远。这篇文章我想完整梳理一遍我实际搭建一套垃圾分类检测系统的全过程,包括数据集怎么搞、模型怎么选、训练参数怎么调、部署到边缘设备时踩了哪些坑,以及最后联动机械结构让检测结果真正驱动分类动作的关键细节。内容适合正在做课程设计、毕业设计,或者想用视觉方案解决实际分拣问题的朋友参考,我会把能直接复用的经验和教训都写出来。
先说清楚这套系统解决的实际问题:社区投放点、校园分类垃圾桶、小型回收站里,人工分拣效率低且一致性差,尤其厨余垃圾混入可回收物之后,整桶可回收物的价值都会大打折扣。视觉检测方案的核心就是把"人眼判断"替换成"摄像头加模型判断",在垃圾进入对应桶之前完成类别识别和数据上报。下面直接进入正题。
1. 为什么一个摄像头加一块板子就能重新定义垃圾分类
1.1 先搞清楚:这个系统到底解决谁的什么问题
我开始做这个项目之前,先列了一份需求清单,而不是急着找数据集。不同场景对检测系统的要求差异非常大:
- 社区智能分类桶:识别对象是居民手持的垃圾袋或单件垃圾,要求识别速度快、支持品类多,但精度要求相对宽松,因为还有人工复核环节。
- 小型回收站分拣线:传送带上连续过检,要求高吞吐、低延迟,误判会直接影响回收物纯度,对精度要求苛刻。
- 校园/园区示范点:更看重交互体验和趣味性,经常需要语音反馈、屏幕展示,检测只是整个交互链路的一环。
我最终定位在"可落地到社区和校园的轻量级检测终端"这个方向上,核心指标就是两个:单帧推理延迟不超过100毫秒,常见单件垃圾的分类准确率在90%以上。这个目标不高不低,既不会让模型选型过于痛苦,又能真实跑通业务闭环。
1.2 四分类体系下的检测难度分层
国内垃圾分类通用体系是四分类:可回收物、有害垃圾、厨余垃圾、其他垃圾。但直接把这四类作为模型输出类别,模型会非常困惑——因为"可回收物"内部包含塑料瓶、纸箱、玻璃瓶、易拉罐,外观差异极大,"厨余垃圾"在图像上则往往是形态不规则、颜色杂乱的混合物。
这个项目我没法用README或教程里的通用说法糊弄自己,必须明确:模型真正要学的是"物理单品",而不是抽象分类。所以我采用的是两级结构:检测模型先识别出具体物品(比如"矿泉水瓶""纸板箱""玻璃瓶"),再由规则引擎映射到四分类的最终结果。这样做的好处是训练目标清晰、误判链路可追溯,排查"为什么这瓶酱油被分进了有害垃圾"这类问题时,能直接定位是检测错了还是映射规则错了。
2. 数据准备比想象中更磨人:采集、清洗与标注的血泪清单
2.1 每类垃圾该准备多少张图才有底气
很多教程会告诉你"每类500张就能训练",但这话只说对了一半。500张的前提是背景多样、视角多样、光照多样,如果500张全是同一块灰色背景布上拍的俯视图,模型的泛化能力会非常差。
我的实践标准是:每个目标类别至少800张真实场景图像,其中包含至少5种不同背景、3种不同拍摄高度、白天和夜间各占一部分比例。优先级最高的是"真实投放场景"的图像——垃圾桶旁边、传送带上、水泥地上,这些才是推理时真正会遇到的环境。
类别数量上我选了12个常见单品:矿泉水瓶、易拉罐、玻璃瓶、纸板箱、报纸、塑料袋、一次性餐盒、果皮、剩菜、电池、灯管、烟蒂。12类覆盖了四分类体系中80%以上的常见投放场景,又不至于让标注工作量翻倍。
2.2 标注规范:边界框怎么打才能让模型少犯迷糊
标注工具我用的LabelStudio,支持矩形框和标签管理,比LabelImg顺手一些,多人协作时可以用Web端统一管理标注进度。但工具只是辅助,真正决定模型上限的是标注规范。
我制定了几条硬性规则:
- 遮挡超过50%的物体不标注,宁可漏掉也不给模型错误的监督信号。
- 对于弯曲、折叠的物体(塑料袋、报纸),用贴近可见区域轮廓的矩形框,不要把大量空白背景框进来。
- 同一张图里的多个同类物体全部独立标注,不能只标一个。
- 模糊到人眼都难判断类别的图直接删除,不纳入训练集。
这几条规则执行完之后,训练出来的模型边界框明显更紧实,误检率也下降了不少。反而是我最早犯的错——为了追求数量,把大量模糊图、严重遮挡图也标进去——导致loss怎么调都降不下去。
2.3 数据质量检查:被忽略的高重复样本陷阱
标注完成之后,一定要做重复样本检查。我的训练集里一度存在大量从视频中连续抽帧得到的图像,相邻帧之间只有微小位移,模型在训练时会反复看到几乎一样的样本,相当于变相放大了这类样本的权重,导致真实场景下的泛化能力变差。
处理方式其实简单:对每个类别按感知哈希去重,相似度高于阈值的只保留一张;再按"拍摄场景"做一次分层抽样确认。这一步花不了多少时间,但对训练效果的影响是决定性的。清洗之后我从12类共9600张图压缩到了7200张左右,训练出来的模型反而更稳了。
3. 模型选型与训练调参:我为什么锁死YOLOv8而不是去追新
3.1 检测框架横向对比:YOLO系列、SSD、Faster R-CNN
检测模型的选择会直接影响后续所有工作,这里值得多花点篇幅说清楚。我把主流方案放在一张表里对比过:
| 模型框架 | 推理速度 | 精度表现 | 部署难度 | 社区资料丰富度 |
|---|---|---|---|---|
| Faster R-CNN | 慢(数百毫秒级) | 高 | 较高 | 多,但偏学术 |
| SSD | 较快 | 中小目标一般 | 中等 | 一般 |
| YOLOv5 | 快 | 较高 | 低 | 非常多 |
| YOLOv8 | 快 | 较高且均衡 | 低 | 多,官方支持完善 |
| YOLOv9/v11 | 更快 | 高 | 中等 | 相对较少 |
对于垃圾分类这个场景,目标通常不算小(单件垃圾占画面比例较大),不需要极端的小目标检测能力,更需要的是"部署方便、社区案例多、踩坑有人分享"。YOLOv8的ultralytics框架把训练、验证、导出封装得很完整,一套API走到底,所以我最终选了YOLOv8n作为主力模型,在保证精度的前提下把体积压到最小。
后来我也看到有人用更新版本的YOLO做类似项目,起点更高,但遇到问题时能参考的资料少很多。如果你追求的是项目稳妥完成而不是发论文,选资料最全的方案永远是最优解。
3.2 训练环境与关键超参的取值逻辑
训练用的是单张消费级显卡,显存8GB,这个配置跑YOLOv8n没有任何压力。环境直接用ultralytics的pip包,PyTorch 2.x配合CUDA 11.8,Python版本3.10。整个环境搭建半小时内搞定。
关键超参我是这么取的,每个数值背后都有理由:
- 输入分辨率640×640:YOLOv8的默认值,对单件垃圾足够,再往上提会明显拉慢推理速度。
- batch size 16:8GB显存下能稳定跑满,再大会爆显存。
- epochs 150:在小数据集上训练150轮足够让模型收敛,我观察loss曲线在100轮附近就基本平了。
- 学习率0.01:配合ultralytics自带的余弦退火调度,从头训练时这个值比较稳,不会出现起步震荡。
- mosaic增强开启:把4张图拼成一张训练,能显著改善模型对小目标的鲁棒性,后期我在最后20轮关闭了mosaic,让模型适应真实的单目标分布。
训练命令就是一行:
yolo detect train data=waste.yaml model=yolov8n.pt epochs=150 imgsz=640 batch=16 device=0waste.yaml里的路径和类别名我在开始训练前反复核对过,因为类别顺序一旦错了,后面所有评估结果都会跟着错。
3.3 训练过程中必须盯住的三个信号
训练不是把命令敲完就完事了。我每隔一段时间就看三个指标:
- box_loss持续下降但cls_loss震荡:说明模型在学定位,但类别区分吃力,大概率是数据问题,回头检查有没有类别样本量失衡。
- 验证集mAP50达到0.95以上但mAP50-95只有0.6出头:说明检测框大致位置对,但框的精细度不够,可以试试增大输入分辨率或者调整置信度阈值。
- 某个类别单独拉出来AP特别低:几乎可以断定这类样本的多样性不足,优先补数据而不是调参。
我的最终结果:12类平均mAP50达到0.97,其中"灯管"和"烟蒂"这两类稍低,一个因为透明材质难分辨,一个因为个体太小。这两类的优化思路我放在后面第5章展开。
4. 从训练机到分拣现场:模型压缩与部署的全过程
4.1 ONNX导出与TensorRT加速的实际收益
模型训练完只是第一步,要在边缘设备上达到实时推理,必须做模型转换和加速。我先后试过三种导出方式:
- 直接PyTorch推理:延迟约180毫秒,显存占用偏高,不满足实时要求。
- ONNX导出加CPU推理:延迟降到约280毫秒,反而更慢,原因是CPU上的ONNXRuntime对YOLOv8结构中的某些算子优化一般。
- ONNX导出加TensorRT(FP16精度):延迟稳定在45毫秒左右,GPU利用率和功耗表现都可接受。
TensorRT的加速效果非常明显,但配置过程有些繁琐,需要根据显卡型号下载对应版本的TensorRT包,再通过trtexec工具把ONNX模型编译成engine文件。我用的是一块嵌入式GPU开发板,显存不大,FP16量化后模型体积从14MB缩到7MB左右,精度损失不到1个百分点,完全在可接受范围内。
导出命令参考:
yolo export model=best.pt format=onnx dynamic=True trtexec --onnx=best.onnx --saveEngine=best_fp16.engine --fp164.2 实时推理流水线的工程细节
模型推理只是流水线的一环。完整的实时检测流程是:摄像头采集图像 → 图像预处理(缩放、归一化) → TensorRT推理 → 后处理(解码检测框、NMS去除重叠框) → 输出类别和坐标。
最容易出问题的是预处理环节。训练时的数据增强里包含了随机色域变换,但推理时不能做这些,必须用固定的归一化参数,否则会出现"训练时好好的,一上线准确率暴跌"的诡异问题。我在预处理里严格复用了训练时的letterbox参数,保持长宽比缩放到640×640,剩余部分用灰色填充,这样才不会让图像变形影响检测。
后处理里的置信度阈值我调到0.35,NMS的IoU阈值保持默认的0.7。置信度阈值太低会出现大量误检框,太高又会漏掉重叠摆放的垃圾,0.35是比较均衡的值。
4.3 联动硬件:让检测结果真正驱动分类动作
检测系统要真正服务于分类,不能停在"屏幕上画个框"这个层面。我做了一个联动方案:当检测到某件垃圾的置信度超过阈值时,通过串口向分拣控制板发送类别指令,控制板驱动对应垃圾桶的翻板机构完成投放。
这块的通信协议是最容易被人忽略的细节。我定义了一个极简的ASCII协议,格式是SCL:类别ID;置信度;时间戳\n。控制板解析到SCL:3;0.96;1714000000这样的帧之后,确认类别ID合法就执行翻板动作,否则丢弃并记录日志。协议里加时间戳的原因是为了事后排查"哪一帧图像对应哪一次分拣动作",在联调时帮了大忙。
摄像头到控制板的整体时延分配大概是:采集加预处理10毫秒,推理45毫秒,串口传输加机械动作300毫秒左右。对于日常投放场景,这个响应速度完全够用。
5. 实测翻车实录:相似垃圾、光照干扰和遮挡难题
5.1 最头疼的误判:透明塑料瓶与玻璃瓶
实测中遇到最多的误判案例就是透明矿泉水瓶和透明玻璃瓶。两者在外观上高度相似——都是透明、圆柱形、有反光——人眼有时都要凑近了才能分辨,模型更是经常把它们混在一起。
我一开始尝试在模型层面强行区分,降低置信度阈值、增加这两类的样本量,效果都不理想。后来换了个思路:不再让视觉模型硬扛全部判断,而是在透明瓶类别的置信度落在模糊区间(比如0.4到0.7)时,触发一次额外的材质判定逻辑——通过目标区域的颜色直方图和纹理特征做个二次判断。虽然仍然是图像层面的启发式规则,但实测把这两类的混淆率降低了40%以上。
这件事给我的启发是:不是所有问题都该用模型解决。合理的规则兜底,比盲目加数据更高效。
5.2 光照变化让准确率坐了过山车
晴天中午的强光、傍晚的暖色灯光、室内的荧光灯,不同光照条件下同一件垃圾在图像里的表现差异很大。我的模型在室内灯光下mAP50到了0.97,拿到户外强光下一测直接掉到0.88,这个落差让我意识到训练数据里户外样本太少。
补救措施分两层。第一层是最直接的数据层面:补充了大量逆光和强曝光场景下的样本,并且在增强策略里加大了对亮度扰动和HSV色域扰动的力度。第二层是硬件层面:在部署现场的投放口增加了补光灯,让相机看到的画面亮度尽量稳定。补光的思路是从安防摄像头那里学来的——尽量改变环境去适配模型,而不是无限提高模型对环境变化的鲁棒性。
5.3 难例挖掘与针对性增强的补救措施
针对"烟蒂"这类小目标检测弱的问题,我做了三件事:
- 把训练数据里烟蒂所在的图片集中挑出来,统计它们的真实尺寸占比,发现普遍小于画面的3%,属于小目标范畴。
- 在数据增强中增加了随机裁切放大(将小目标区域裁出来放大后再拼回原图),强制模型去学习小目标的特征。
- 将mosaic增强的强度在小目标类别上稍微提高了比例,让模型在训练中看到更多"小尺寸"的正样本。
这三步走完,"烟蒂"的AP从0.78提到了0.91。虽然还是12类里最低的,但实际使用中已经不容易漏检了。难例挖掘的通用方法论其实就是一句话:把模型最容易犯错的样本找出来,分析它们为什么错,再针对性地让它们在训练中出现得更频繁。
6. 更远一步:从单帧检测到完整的分拣闭环
6.1 硬件选型与成本控制的思考
整套系统的成本大头在算力板和摄像头。算力板我最终用的是嵌入式GPU开发板,功耗低、支持TensorRT,单块成本在几百元到千元这个区间,适合批量部署。如果只做算法验证,用普通电脑加USB摄像头就够了,成本能压到最低。
摄像头选型有一个参数很关键:视场角。视场角太小,垃圾投放口三分之一的区域在画面之外;视场角太大,每件垃圾在画面里太小,小目标检测压力陡增。我实际用下来80°到100°的水平视场角最合适,能在有效检测距离内同时覆盖投放口和等待区。
还有一个容易被忽略的细节:摄像头安装角度。我以前习惯从正上方俯拍,后来发现斜向下45°视角对"人手持垃圾靠近投放口"这个动作的鲁棒性更好,因为正俯拍会被人的手部遮挡。这个调整不需要改任何代码,但对检测成功率的提升是立竿见影的。
6.2 个人经验总结与给后来者的建议
整套系统从零到稳定运行,我最大的体会是:视觉检测项目里,模型训练只占最后20%的精力,前面80%的时间基本都在和数据、环境、硬件打交道。很多刚开始做这个方向的朋友把时间全花在调整网络结构上,其实是在错误的方向上努力。
给你几个可直接抄的建议:
- 先搭通"摄像头到推理到输出"的最小闭环,再回头优化模型精度,不要让前期的完美主义拖住进度。
- 每一类垃圾单独统计精确率和召回率,只看整体准确率会掩盖个别类别的严重缺陷。
- 置信度阈值不要只拍脑袋定,画一遍置信度-准确率曲线,在曲线拐点附近选值。
- 所有实验记录都写下来,包括数据集版本、增强配置、超参、评价指标。我复现不了自己两周前的"最佳结果"时,才发现有个实验参数当时忘了记。
这套系统的下一步,我打算在检测结果之上叠加一个投放行为的时序判断,根据目标在画面中的轨迹判断它是不是"被正确投放进了对应的桶",而不是仅仅"被识别出来了"。检测只是眼睛,判断行为才算有了脑子。这个方向做扎实了,垃圾分类终端才真正谈得上"智能"两个字。