
简介这份资源是面向高校学生与深度学习入门者的垃圾分类目标检测完整项目包适用于毕业设计、期末大作业与课程设计场景帮助读者快速获得一套可运行、可复现的检测系统方案。压缩包共126个文件约66.06MB包含20个Python源码文件、13个Jupyter Notebook实验记录、12个Vue前端组件、18张运行截图与结果图以及ONNX模型、SQLite数据库、Dockerfile、YAML配置和PPT、Word报告等文档覆盖从数据处理、模型训练到Web端展示的完整链路。目前已有252人学习下载。代码附有详细注释新手也能看懂部署指南与参考报告可直接用于答辩与文档撰写数据集与训练脚本齐备省去自行收集与调试的时间适合作为深度学习目标检测方向的实战参考。1. 从一张宿舍桌面照片说起垃圾分类目标检测到底在做什么把一张堆着外卖盒、快递纸箱、果皮和饮料瓶的桌面照片丢给模型它要做的不是判断「这图脏不脏」而是把画面里每个垃圾实例框出来并告诉你是可回收物、厨余垃圾、有害垃圾还是其他垃圾。这就是基于深度学习的垃圾分类目标检测系统要解决的核心问题多类别、多尺度、密集小目标的检测任务。它和普通图像分类最大的区别在于分类只回答「图里有什么」检测要回答「在哪里、有几个、分别是什么」。这套东西适合谁如果你正在做课程大作业、毕设或者想用 Python 把深度学习从「跑通 MNIST」推进到「能落地一个完整系统」垃圾分类检测是个非常合适的载体数据集公开、类别定义清晰、YOLO 系列开箱即用、部署路径成熟。它不玄学但坑不少尤其是数据集标注质量和类别映射这两块翻车的人一抓一大把。下面我按「数据 → 训练 → 部署 → 报告」这条线把能抄作业的部分全写清楚。2. 数据集怎么选、怎么标、怎么转成 YOLO 能吃的格式2.1 垃圾分类数据集的三种来源与取舍做这个题目数据集基本逃不出三条路。第一条是直接用公开的垃圾分类数据集常见的有华为云垃圾分类数据集、TrashNet 的扩展检测版以及各类竞赛里放出的带框标注版本。第二条是自己爬图加标注用 labelImg 或 Label Studio 手工画框。第三条是拿分类数据集「改造」成检测数据集比如 TrashNet 原本是单张单物体的分类图你得用显著性检测或人工补框才能变成检测格式。我的建议是优先用带 VOC 或 YOLO 标注的公开检测数据集自己标 2000 张以上的工作量对一个大作业来说太重而且标注一致性很难保证。如果公开数据集类别和你需要的四分类对不上就做类别映射而不是重新标。常见做法是把公开数据集的细类归并到「可回收物 / 厨余垃圾 / 有害垃圾 / 其他垃圾」四个大类下映射表单独存一份 JSON训练和推理都读它避免硬编码。提示类别映射一旦确定就不要中途改。改一次所有已训练的权重和已标注的数据都要重新对齐这是最常见的返工来源。2.2 把 VOC 标注转成 YOLO 格式的脚本与四个边界坑YOLO 系列包括 yolov8、yolov11吃的是归一化后的class x_center y_center width height格式每张图对应一个同名.txt。VOC 是 XML转换脚本必须处理边界情况。下面是我常用的转换脚本import os import xml.etree.ElementTree as ET # 类别映射把公开数据集的细类归并到四大类 CLASS_MAP { plastic: 0, paper: 0, glass: 0, metal: 0, # 可回收物 food: 1, fruit: 1, vegetable: 1, # 厨余垃圾 battery: 2, medicine: 2, lamp: 2, # 有害垃圾 ceramic: 3, tissue: 3, other: 3 # 其他垃圾 } def voc_to_yolo(xml_dir, out_dir, img_w, img_h): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() # 优先读 XML 里真实的尺寸读不到才用传入的默认值 size root.find(size) w int(size.find(width).text) if size is not None else img_w h int(size.find(height).text) if size is not None else img_h lines [] for obj in root.iter(object): name obj.find(name).text.strip().lower() if name not in CLASS_MAP: continue # 未映射类别直接丢弃不要瞎猜 cls_id CLASS_MAP[name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 裁剪到图像边界防止标注越界导致归一化后为负 xmin, ymin max(0, xmin), max(0, ymin) xmax, ymax min(w, xmax), min(h, ymax) if xmax xmin or ymax ymin: continue # 宽高为 0 的脏框直接跳过 xc (xmin xmax) / 2.0 / w yc (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) out_name os.path.splitext(xml_file)[0] .txt with open(os.path.join(out_dir, out_name), w) as f: f.write(\n.join(lines)) voc_to_yolo(Annotations, labels, 640, 640)逻辑说明脚本先读 XML 里的真实宽高而不是无脑用 640因为归一化必须基于原图尺寸否则框会整体偏移。四个边界坑分别是——标注越界xmax 超过图像宽度、宽高为 0 的脏框、未映射类别、以及 XML 里 size 缺失。前三个在代码里都做了处理第四个用默认值兜底。参数上CLASS_MAP是唯一需要你按自己数据集改的地方其余不用动。2.3 训练集 / 验证集划分与 data.yaml 写法划分比例我一般用 8:1:1 或 8:2小数据集低于 3000 张建议 8:2别切太碎。划分要按「图像」而不是按「框」来切否则同一张图的框被分到两个集合验证指标会虚高。划分完写data.yamlpath: ./dataset train: images/train val: images/val nc: 4 names: [recyclable, kitchen, hazardous, other]nc必须和names长度一致names的顺序必须和CLASS_MAP里的 id 严格对应。这个对应关系错了模型训练能跑但推理结果全是错的而且 loss 曲线看起来还挺正常属于最阴的坑之一。3. 用 YOLOv8 训练垃圾分类模型参数、命令与显存控制3.1 环境配置与最小可跑命令环境这块Python 3.9 到 3.11 都行装 ultralytics 一条命令搞定pip install ultralytics # 验证安装能打印版本号就说明环境通了 yolo version训练的最小命令是yolo detect train datadataset/data.yaml modelyolov8n.pt epochs100 imgsize640 batch16这里modelyolov8n.pt用的是 nano 版本参数量小、显存占用低适合 6G 到 8G 显存的机器。如果你显存只有 4G把batch降到 8 或 4imgsz降到 512。epochs100对垃圾分类这种类别数少、场景相对固定的任务通常够用但要看早停别硬跑。注意imgsz改了之后验证和推理也要用同样的尺寸否则 mAP 会掉得莫名其妙。这是新手最容易忽略的一致性要求。3.2 关键参数怎么调从学习率到数据增强YOLOv8 默认用 SGD 加余弦退火学习率lr00.01。垃圾分类数据集如果偏小低于 5000 张我一般把lr0降到 0.005 到 0.008避免前期震荡。lrf是最终学习率比例默认 0.01保持不动即可。数据增强方面mosaic1.0默认开启对小目标检测帮助很大但垃圾分类里如果有大量「单物体占满画面」的图mosaic 拼接后会出现不自然的组合可以降到 0.5。hsv_h、hsv_s、hsv_v控制颜色抖动垃圾图像颜色差异大保持默认即可。flipud0.0建议保持关闭因为垃圾通常有重力方向上下翻转不符合物理常识会让模型学到错误特征。参数默认值小数据集建议作用lr00.010.005~0.008初始学习率batch164~8批大小受显存限制imgsz640512~640输入分辨率mosaic1.00.5~1.0马赛克增强flipud0.00.0上下翻转建议关闭patience5020~30早停耐心值3.3 训练过程怎么看loss 曲线与 mAP 的读法训练日志里重点看三个东西box_loss、cls_loss和mAP50。box_loss下降说明框回归在收敛cls_loss下降说明分类在收敛。如果box_loss一直不降大概率是标注格式有问题回去检查归一化。如果cls_loss震荡剧烈多半是类别不平衡厨余垃圾和其他垃圾的样本数往往差好几倍可以考虑对少数类做过采样。mAP50到 0.85 以上对垃圾分类来说算合格mAP50-95能到 0.6 以上就不错了。如果验证集 mAP 远低于训练集说明过拟合加数据或加增强如果两者都低说明欠拟合加 epoch 或换更大的模型yolov8s、yolov8m。4. 推理、部署与报告把模型变成能演示的系统4.1 单图推理与批量推理的代码写法训练完的权重默认在runs/detect/train/weights/best.pt。单图推理from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) # conf 是置信度阈值iou 是 NMS 的 IoU 阈值 results model.predict(test.jpg, conf0.25, iou0.45, saveTrue) for r in results: for box in r.boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) xyxy box.xyxy[0].tolist() print(f类别{model.names[cls_id]} 置信度{conf:.2f} 框{xyxy})conf0.25是常用起点漏检多就降到 0.15误检多就升到 0.4。iou0.45控制重叠框的合并密集场景可以升到 0.5。批量推理把路径换成文件夹即可saveTrue会把画框结果存到runs/detect/predict。4.2 用 Gradio 搭一个能演示的 Web 界面大作业要演示光有命令行不够。用 Gradio 十几行就能搭出上传图片返回检测结果的界面import gradio as gr from ultralytics import YOLO import numpy as np model YOLO(runs/detect/train/weights/best.pt) def detect(img): results model.predict(img, conf0.25, iou0.45) # plot() 返回带框的 BGR 图转成 RGB 给前端 annotated results[0].plot() return annotated[:, :, ::-1] demo gr.Interface(fndetect, inputsgr.Image(typenumpy), outputsgr.Image()) demo.launch(server_name0.0.0.0, server_port7860)server_name0.0.0.0是为了让同局域网的其他设备也能访问答辩时用手机演示很方便。plot()返回的是 BGR必须反转通道否则颜色会偏。4.3 报告 PPT 该放什么从指标到失败案例报告 PPT 别堆代码评委看的是你的判断力。我一般放这几页任务定义与类别体系、数据集规模与划分、模型选型理由、训练曲线、mAP 对比表、混淆矩阵、失败案例。失败案例这一页最加分放几张漏检或误检的图分析原因比如透明塑料瓶和背景对比度低、小目标被 mosaic 拼接后语义混乱比只报高 mAP 有说服力得多。页面内容数据来源任务定义四分类体系与判定标准自定义数据集各类别样本数、划分比例统计脚本模型选型为什么选 YOLOv8n 而非更大模型显存与精度权衡训练曲线box_loss、cls_loss、mAPresults.csv对比表不同 imgsz / batch 的 mAP多次实验失败案例漏检误检图与原因分析验证集5. 避坑与排查垃圾分类检测最常见的五个翻车点5.1 现象训练 loss 正常但推理全是同一类原因data.yaml里names的顺序和标注文件里的 class id 对不上或者转换脚本里CLASS_MAP的 id 和 yaml 不一致。模型学到的映射是错的但训练过程本身自洽所以 loss 看起来正常。解决写一个校验脚本随机抽 20 张图把标注框画回原图人工确认类别和框位置。这一步花十分钟能省掉几小时的重训。5.2 现象mAP 卡在 0.5 上不去原因标注质量差框画得松或紧或者同一类物体在不同图里标注标准不一致。垃圾分类里「其他垃圾」这个类最容易出问题因为定义模糊标注员各标各的。解决统一标注规范写一份带正反例的标注手册。已经标完的数据用模型预测结果反查标注异常——如果模型高置信度预测的框和标注框 IoU 很低大概率是标注错了。5.3 现象显存溢出训练中途崩原因batch或imgsz设太大或者workers太多导致内存也爆。YOLOv8 默认workers8在 Windows 上容易出问题。解决batch减半imgsz降到 512workers设成 2 或 0。Windows 下建议workers0虽然慢一点但稳定。5.4 现象验证集 mAP 高实际拍照检测效果差原因训练集和实际场景的域差异。公开数据集多是白底或简单背景实际宿舍、办公室背景杂乱光照也不同。解决加实际场景的图做微调哪怕只有几百张。或者用更强的数据增强比如随机裁剪、亮度对比度扰动、加噪声。5.5 现象推理速度慢演示卡顿原因用了大模型yolov8m/l或者没开半精度。CPU 推理也会很慢。解决换yolov8n推理时加halfTrue需要 GPU或者导出 ONNX 用 onnxruntime 跑。演示机器有 GPU 的话model.predict(..., device0)指定显卡。6. 把 mAP 再抬 3 个点的两个技巧TTA 与类别重映射模型训完之后如果指标还差一口气有两个成本很低但有效的技巧。第一个是测试时增强TTA推理时对同一张图做水平翻转、多尺度缩放把多次预测结果做 NMS 融合。YOLO 里可以直接开results model.predict(test.jpg, augmentTrue, conf0.25, iou0.45)augmentTrue会启用 TTAmAP 通常能涨 1 到 2 个点代价是推理时间翻倍。演示场景对速度不敏感值得开。第二个是类别重映射。垃圾分类的四分类里「其他垃圾」往往是个筐什么难分的都往里扔导致这个类的 precision 很低。我的做法是先把模型训成更细的类别比如 8 到 10 类推理时再把细类映射回四大类。这样模型学到的特征更 discriminative映射回大类后「其他垃圾」的误检会明显减少。代价是标注成本高但如果公开数据集本身就有细类标注这一步几乎零成本。# 细类到四分类的推理后映射 FINE_TO_COARSE {0: 0, 1: 0, 2: 1, 3: 1, 4: 2, 5: 3, 6: 3, 7: 3} def remap(results): for r in results: for box in r.boxes: fine_id int(box.cls[0]) box.cls[0] FINE_TO_COARSE[fine_id] return results这两个技巧我都用过TTA 是稳赚不赔类别重映射要看数据集支不支持。最后说个血泪经验别在最后一天改类别体系。我见过太多人答辩前一晚把四分类改成三分类结果所有权重、报告、PPT 全部重来。类别体系在动手标注之前就定死后面只做加法不做减法。希望帮到你。本文还有配套的精品资源点击获取