
做过图像识别方向的朋友应该都清楚垃圾分类检测系统这几年几乎成了计算机视觉入门项目的标配。但真正把它从跑通一个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.8Python版本3.10。整个环境搭建半小时内搞定。关键超参我是这么取的每个数值背后都有理由输入分辨率640×640YOLOv8的默认值对单件垃圾足够再往上提会明显拉慢推理速度。batch size 168GB显存下能稳定跑满再大会爆显存。epochs 150在小数据集上训练150轮足够让模型收敛我观察loss曲线在100轮附近就基本平了。学习率0.01配合ultralytics自带的余弦退火调度从头训练时这个值比较稳不会出现起步震荡。mosaic增强开启把4张图拼成一张训练能显著改善模型对小目标的鲁棒性后期我在最后20轮关闭了mosaic让模型适应真实的单目标分布。训练命令就是一行yolo detect train datawaste.yaml modelyolov8n.pt epochs150 imgsz640 batch16 device0waste.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导出加TensorRTFP16精度延迟稳定在45毫秒左右GPU利用率和功耗表现都可接受。TensorRT的加速效果非常明显但配置过程有些繁琐需要根据显卡型号下载对应版本的TensorRT包再通过trtexec工具把ONNX模型编译成engine文件。我用的是一块嵌入式GPU开发板显存不大FP16量化后模型体积从14MB缩到7MB左右精度损失不到1个百分点完全在可接受范围内。导出命令参考yolo export modelbest.pt formatonnx dynamicTrue trtexec --onnxbest.onnx --saveEnginebest_fp16.engine --fp164.2 实时推理流水线的工程细节模型推理只是流水线的一环。完整的实时检测流程是摄像头采集图像 → 图像预处理缩放、归一化 → TensorRT推理 → 后处理解码检测框、NMS去除重叠框 → 输出类别和坐标。最容易出问题的是预处理环节。训练时的数据增强里包含了随机色域变换但推理时不能做这些必须用固定的归一化参数否则会出现训练时好好的一上线准确率暴跌的诡异问题。我在预处理里严格复用了训练时的letterbox参数保持长宽比缩放到640×640剩余部分用灰色填充这样才不会让图像变形影响检测。后处理里的置信度阈值我调到0.35NMS的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%的时间基本都在和数据、环境、硬件打交道。很多刚开始做这个方向的朋友把时间全花在调整网络结构上其实是在错误的方向上努力。给你几个可直接抄的建议先搭通摄像头到推理到输出的最小闭环再回头优化模型精度不要让前期的完美主义拖住进度。每一类垃圾单独统计精确率和召回率只看整体准确率会掩盖个别类别的严重缺陷。置信度阈值不要只拍脑袋定画一遍置信度-准确率曲线在曲线拐点附近选值。所有实验记录都写下来包括数据集版本、增强配置、超参、评价指标。我复现不了自己两周前的最佳结果时才发现有个实验参数当时忘了记。这套系统的下一步我打算在检测结果之上叠加一个投放行为的时序判断根据目标在画面中的轨迹判断它是不是被正确投放进了对应的桶而不是仅仅被识别出来了。检测只是眼睛判断行为才算有了脑子。这个方向做扎实了垃圾分类终端才真正谈得上智能两个字。