简介一套基于Python深度学习的垃圾分类目标检测系统毕业设计资料包面向计算机相关专业毕业生及需要项目实战的开发者。项目经导师指导并认可评审分98分源码本地编译调试通过可直接运行难度适中适合毕业设计、课程设计或入门级目标检测练习。压缩包共126个文件约66.06MB涵盖Python源码、Jupyter Notebook分析脚本、Vue前端页面与JavaScript/CSS样式、说明文档及答辩PPT等此外包含ONNX模型文件、SQLite数据库记录以及Dockerfile环境配置便于复现部署与二次开发。内容覆盖模型代码、前端展示与配套文档可快速定位代码与材料帮助理解从数据标注到模型推理再到界面展示的完整流程。已有304人学习内容组织清晰除可运行代码外还附有参考报告、答辩PPT和说明文档能辅助读者快速理解项目结构、训练流程与系统实现适合作为毕业设计与深度学习实践的有力参考。1. 垃圾分类检测毕设到底在做什么先想清楚这四件事很多人拿到这个题目第一反应是“用个开源模型跑一遍把检测框画出来就交差”结果答辩时被评委一句“你的创新点在哪”“这个框为什么没框住那个塑料瓶”问得下不来台。这个毕业设计真正的落脚点不是“跑通一个Python深度学习代码”而是你能讲清楚从数据标注到模型训练再到目标检测结果的全链路逻辑。它解决的是一张图里“垃圾在哪、属于哪一类”的问题——是目标检测不是图像分类。目标检测任务输出的是“类别位置框”面对的场景是工位摄像头、小区垃圾桶、演示用的手机随手拍。它不要求你把所有垃圾识别的分毫不差但要求你掌握数据怎么组织、标签怎么标、模型怎么选、检测置信度怎么调。这篇文章按“数据准备→模型选型→训练调参→检测推理→答辩验证”的顺序铺开每一段都能直接照着做也会告诉你哪些地方是毕设最容易翻车又最值得提前准备的点。适合正在选题或已经开题、手里只有标题没有方案的本科生也适合想快速把深度学习目标检测流程过一遍的入门者。2. 数据准备公开数据集与自建标注的取舍2.1 垃圾分类目标检测的数据长什么样图像分类里一张图对应一个类别标签放到目标检测里就行不通了一张图里可能同时出现易拉罐、纸箱和塑料袋每个目标都要有自己的坐标框和类别。常见做法是把标注信息放到一个和图片同名的txt文件里每一行是“类别id 中心点x 中心点y 框宽 框高”坐标经过归一化取值范围是0到1。数据集的来源无非两条路。第一条是用公开数据集起步比如常见的华为云垃圾分类数据、Kaggle上的垃圾分类图片这些数据通常已经是整理过的目标检测格式能帮你跳过最枯燥的标注阶段。第二条是自建数据集也就是自己拍照、自己标注。毕设答辩时评委大概率会问“你的数据怎么来的”“标注了多少张”纯用公开数据集容易被追问“那你做了什么工作”纯自建又会在时间上失控。我一般建议混着来主体用公开数据集保证类别覆盖针对性补拍30到50张自己校园或宿舍场景的垃圾图片做微调。比例大概七三开既省时间答辩时又能说出“针对真实场景做了数据补充”这种话技术含量和完成度都说得过去。2.2 用LabelImg把自建数据标成YOLO格式如果补拍了图片要用标注工具生成目标检测需要的标签文件。最常用的标注工具是LabelImg它本身不挑Python版本直接按它的文档装就行。安装完成后操作路径是Open Dir选择图片目录Change Save Dir选择标签输出目录然后在PascalVOC和YOLO格式之间切换成YOLO。标注时按w键画矩形框框住目标后弹出类别输入框填上对应的类别名。一个目标一个框一张图里有多少个垃圾就画多少个。画完之后每个图片旁边会生成一个同名txt文件。下面是把标注好的数据按比例划分成训练集和验证集的Python脚本import os import random import shutil image_dir dataset/images label_dir dataset/labels train_img_dir dataset/train/images val_img_dir dataset/val/images train_lbl_dir dataset/train/labels val_lbl_dir dataset/val/labels for d in [train_img_dir, val_img_dir, train_lbl_dir, val_lbl_dir]: os.makedirs(d, exist_okTrue) images [f for f in os.listdir(image_dir) if f.endswith(.jpg)] random.seed(42) random.shuffle(images) val_count int(len(images) * 0.2) for idx, img in enumerate(images): label img.replace(.jpg, .txt) src_img os.path.join(image_dir, img) src_lbl os.path.join(label_dir, label) if idx val_count: shutil.copy(src_img, os.path.join(val_img_dir, img)) shutil.copy(src_lbl, os.path.join(train_lbl_dir, label)) # 这里故意写错见下方说明 else: shutil.copy(src_img, os.path.join(train_img_dir, img)) shutil.copy(src_lbl, os.path.join(train_lbl_dir, label))注意上面代码里我故意留了一个典型的“翻车点”第20行把验证集标签拷到了train_lbl_dir而不是val_lbl_dir。这类笔误在毕设里经常出现结果就是训练集里混进了验证集标签导致训练时模型“偷看”过验证数据。我自己的习惯是划分完数据后随机挑一张图片打开它的txt文件确认对应关系import os img_id random.choice(os.listdir(val_img_dir)).replace(.jpg, ) print(os.path.exists(fval/labels/{img_id}.txt))划分比例上80%训练、20%验证是够用的如果数据总量少于500张验证集比例可以降到15%。种子固定成42是为了复现实验结果答辩时能说出“我固定了随机种子保证实验可复现”会很加分。2.3 类别定义与标签一致性垃圾分类的类别没有统一标准常见有可回收物、厨余垃圾、有害垃圾、其他垃圾四大类但如果直接把这四类作为目标检测的类别模型会很难学——因为“可回收物”这个类别内部的视觉差异太大了塑料瓶和纸箱长得完全不一样强行归为一类等于让模型在一个框里学多种外观。我见过不少毕设在这个地方翻车类别定义得太粗训练出来的模型mAP看着还行一放到真实场景就狂漏检。更好的做法是拆成具体物品种类比如plastic_bottle、carton、can、banana_peel、battery这类。等训练好之后再做一个类别映射把具体物品映射到四分类上检测输出的是物品名展示给用户的是可回收/不可回收这样的结论两头都说得通。标签一致性指的是标注框的类别名必须和配置文件里的类别顺序严格对应。YOLO格式的txt文件里写的是数字id模型本身不知道数字对应哪个类别全靠训练配置里的类别列表做映射。如果标注时用的类别顺序和训练配置里写的顺序不一致模型会准确地把塑料瓶当成厨余垃圾去训而且你会发现损失还降得下去因为模型学到的是“框住某个视觉模式并输出id1”完全感知不到id1在配置文件里叫什么名字。3. YOLOv8s选型与训练调参从配置到跑通的关键参数3.1 为什么选YOLOv8而不是更旧的版本目标检测模型里YOLO系列是毕设中使用频率最高的理由很实际代码成熟、资料多、训练代码和推理代码封装得干净。目前最常见的版本是YOLOv8它相比YOLOv5在训练速度和精度上都有提升而且ultralytics这个库把训练、验证、推理、导出全部做成了命令行和Python接口对入门者非常友好。具体选哪个尺寸取决于你的硬件。YOLOv8有n/s/m/l/x五个尺寸用n的话在CPU上也能硬着头皮训但精度差一些用l或x的话一张显卡显存低于6G根本跑不动。毕设场景我一般推荐YOLOv8s训练速度适中精度够用显存需求在GTX 1660 Super6G显存这个级别就能跑。如果显卡显存只有4G退到YOLOv8n更稳妥。YOLOv8s的另一个优势是部署简单。最后做演示系统时可以用它自带的predict接口几行Python代码就能读摄像头或者图片输出检测结果不需要自己写前后处理逻辑。做毕业设计的核心诉求是“能展示、能讲清楚”YOLOv8s在这里是性价比最高的平衡点。3.2 数据集配置文件与训练命令用ultralytics训练前要准备一个YAML格式的数据配置文件这是整个训练链路里最容易出错的地方。创建一个garbage.yamltrain: dataset/train/images val: dataset/val/images nc: 4 names: [plastic_bottle, carton, can, banana_peel]train和val路径可以用绝对路径也可以用相对于yaml文件所在目录的路径。最容易踩坑的是路径写法Windows下用反斜杠会出错统一用正斜杠。nc必须和names列表长度一致这个数字错了训练直接报错或者全部标注被当成背景。然后执行训练命令yolo detect train \ datagarbage.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch8 \ lr00.01 \ optimizerSGD \ projectruns/garbage_train \ nameexp1参数含义逐条解释modelyolov8s.pt表示用预训练权重做初始化不是从头训练能大大加快收敛epochs100是训练轮数毕设场景100轮够用再多收益不大imgsz640是输入图片缩放尺寸YOLOv8默认是640图片大目标多可以调到768但显存占用会明显上升batch8是批大小6G显存跑YOLOv8s配batch8比较稳显存不足就降到4。学习率这里有个常见误区很多人用默认lr00.01加Adam优化器结果训练过程震荡得很厉害。我习惯用SGD配合0.01的初始学习率yolov8s这种规模的模型在中小数据集上收敛得更平滑。如果你用Adam建议把学习率降到0.001再开始。3.3 损失下降与验证指标怎么看训练开始后终端会输出每个epoch的box_loss、cls_loss、dfl_loss和precision、recall、mAP50、mAP50-95这几项。前三个是损失值后三个是验证集上的检测效果。毕设不需要死磕mAP50-95这个指标它统计的是更严格的多IoU阈值下的平均精度实际演示场景关注mAP50IoU阈值0.5时的平均精度就足够说服评委。一个能上台演示的模型mAP50大概在0.75以上就算合格0.85以上属于很好。需要警惕的情况是损失一直在降但mAP不涨这种状态超过30个epoch说明模型过拟合了早停比硬训更有效。训练完后模型权重保存在runs/garbage_train/exp1/weights/best.pt。best和last的区别在于best是按验证集mAP保存的最优权重last是最后一个epoch的权重。演示一律用best.pt答辩被问到时能说出“我根据验证集mAP选择最优模型而不是用最后一步的权重”这也是一个加分回答。4. 检测推理与置信度联动把模型变成答辩演示4.1 写一个能跑图片和摄像头的推理脚本训练只是中间过程毕业设计的交付物是“一个能检测垃圾的演示系统”。YOLOv8的推理封装非常简洁用Python几行就能跑起来。下面这个脚本支持图片、视频、摄像头三种输入按参数切换from ultralytics import YOLO import cv2 model YOLO(runs/garbage_train/exp1/weights/best.pt) def detect_image(source: str, conf_thres: float 0.5): results model.predict(sourcesource, confconf_thres, imgsz640) for r in results: boxes r.boxes.xyxy.cpu().numpy() classes r.boxes.cls.cpu().numpy().astype(int) scores r.boxes.conf.cpu().numpy() for box, cls_id, score in zip(boxes, classes, scores): print(fclass{model.names[cls_id]} score{score:.2f} box{box.astype(int)}) def detect_webcam(conf_thres: float 0.5): cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break results model.predict(sourceframe, confconf_thres, imgsz640) annotated results[0].plot() cv2.imshow(garbage detection, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows() if __name__ __main__: detect_image(test_imgs/desk.jpg, conf_thres0.45)这段代码里的model.names[cls_id]是类别id到类别名的映射来自训练时的yaml文件推理时自动加载。results[0].plot()是ultralytics自带的画框函数它会把检测框、类别名、置信度一起画到图上省掉自己写cv2.rectangle的麻烦。conf_thres是置信度阈值低于这个值的检测结果会被过滤掉。置信度阈值在垃圾分类场景里很有讲究。垃圾目标通常尺寸小、外观杂阈值设高了真实目标被过滤设低了背景区域被误检成垃圾。我一般先从0.5开始看检测结果里有没有“该框没框”的漏检和“不该框乱框”的误检再往0.3到0.6之间微调。4.2 置信度阈值与NMS的联动目标检测模型输出的是多个候选框同一个目标周围会有一堆重叠框NMS非极大值抑制负责从中选一个最优框。YOLOv8的predict接口默认已经做了NMS不用自己实现。但有两个参数值得手动调conf控制进入NMS的候选框门槛iou控制NMS对重叠框的合并力度。results model.predict(sourceframe, conf0.35, iou0.6, imgsz640)iou默认是0.7如果场景里垃圾堆叠得厉害比如多个饮料瓶挨在一起可以把iou调低到0.5减少互相遮挡时的吞并误判。反之如果总是把一个物体框成两个框把iou调高让NMS更激进。垃圾分类场景里还有个容易忽视的问题——检测框太小。公开数据集里垃圾通常是一张图的主体框很大但真实演示时垃圾只是画面的一部分比如桌子角落的一个易拉罐。这种场景YOLOv8s直接跑640分辨率容易漏检。常见做法是把推理分辨率调到768或甚至1024代价是推理变慢但对演示来说一帧几百毫秒的延迟可以接受。4.3 做一个简单的可视化统计答辩演示时光画框不够最好能实时显示当前识别到几类垃圾、每类几个。这个功能不涉及模型改动只需要对检测结果做聚合from collections import Counter def count_results(results): for r in results: cls_ids r.boxes.cls.cpu().numpy().astype(int) counter Counter(cls_ids) for cls_id, cnt in counter.items(): print(f{model.names[cls_id]}: {cnt})这类小功能虽然技术含量不高但展示效果很好会让整套系统看起来更完整。如果答辩的时候演示的是实时摄像头可以顺便提一句“这里还做了类别计数可以在后台记录一段时间内各类垃圾出现的频次”对口的是“智能垃圾分类”这个应用场景的落地感。5. 避坑清单毕设里最容易翻车的五个点5.1 数据集和代码在不同电脑间拷贝后路径全崩现象在同一台电脑上训练好好的拷到笔记本上重新训练报FileNotFoundError各种路径找不到。原因标注文件和配置文件里写了绝对路径换机器后路径变了。最常见的是Windows和Linux混用或者自己的电脑和学校机房电脑混用。解决数据划分和训练脚本里统一用相对路径以项目文件夹作为根目录。数据集里的图片路径在yaml中写成dataset/train/images这样的相对形式训练时在项目根目录下执行命令。把runs/目录整个拷走时权重文件内部不绑定路径相对路径改好就能跑。5.2 训练正常但验证集mAP为0现象训练过程看不出问题损失一直在降但每个epoch的mAP50都是0。原因标注文件的类别id和yaml配置不一致或者验证集图片和标签文件没有对应上。更隐蔽的原因是验证集里只有标签没有图片或者图片是png但标签文件后缀写成了jpg。解决把验证集随机挑三张图片出来手动画框对比标注坐标是否落在正确的物体上。写一段脚本检查每张验证集图片是否都有对应标签文件没有的列出来。我习惯在数据准备阶段就做一次完整性校验不要直接开训练。标注坐标如果所有数值都大于1说明忘记归一化了YOLO格式标注必须归一化到0-1区间。5.3 显存不够但不敢降batch现象程序报CUDA out of memory显存不足但同学说batch影响精度不敢随便降。原因YOLOv8s加640分辨率6G显存跑batch8勉强4G显存就只能batch2或4。但很多人把“影响精度”理解成“一定不能降”。解决显存不够时优先降batch到2同时把workers调低到2或4。如果降batch后训练变慢可以同步降低epochs毕设100轮改成60轮加早停。另外可以打开ampTrueYOLOv8默认启用了混合精度训练能省不少显存。一个小技巧是用imgsz480训练最后推理再用640牺牲一点点精度换来训练能跑起来。5.4 训练集和验证集混在一起指标虚高现象训练时验证损失很低mAP接近0.95但拿到新图片上一测效果惨不忍睹。原因数据划分时用了random.shuffle但没有固定种子或者划分后训练集和验证集有图片重叠。另一个常见操作是先用官方数据集训练又用同一份数据做微调然后拿微调后的模型去评测原始验证集——这属于测试集泄露。解决划分前设置random.seed()并把种子固定住划分完成后检查验证集图片名是否在训练集中出现。不要在公开数据集上反复评测同一个模型。如果自建数据量小可以只用一次划分然后把划分代码和数据文件一起放进项目打包答辩时展示“我的数据划分脚本固定了种子可复现”。5.5 答辩当场摄像头无法打开或画面卡死现象演示摄像头识别时程序报错无法打开摄像头或者画面延迟严重垃圾都拿走了框才出现。原因教室或答辩用的电脑没有摄像头驱动或者摄像头被其他程序占用。推理延迟来源于分辨率太高和显卡太弱。解决答辩演示准备两个方案摄像头能用就演示实时不能用就降级到图片识别。提前准备10到20张测试图片放在项目目录里现场用图片跑效果稳定且可控。实时检测时用imgsz320推理这个尺寸对YOLOv8s来说精度下降有限但速度翻倍画面流畅度比细框重要得多。6. 答辩展示与验证技巧光有训练曲线远远不够答辩现场评委最烦的事是学生对着训练曲线念参数没有实际展示环节。我的习惯是提前准备一个演示脚本包含三类输入一组静态图片、一段拍好的短视频、实时摄像头。静态图片展示模型精度短视频展示连续性摄像头是加分项但不是必选项。# 图片批量检测 yolo detect predict \ modelruns/garbage_train/exp1/weights/best.pt \ sourcetest_imgs/ \ conf0.45 \ saveTrue \ projectresults # 视频检测 yolo detect predict \ modelruns/garbage_train/exp1/weights/best.pt \ sourcetest_videos/demo.mp4 \ conf0.45 \ saveTrue答辩时不要只说“准确率多少”而是拿同一张图切换两个置信度阈值展示框的变化讲清楚置信度是过滤低质量预测的阀门。评委问到“为什么这个目标没检测出来”能回答“目标尺寸太小加上背景干扰可以通过降低置信度或提高分辨率缓解但也会引入更多误检需要在具体场景里做权衡”这个答案比“模型精度还不够”成熟得多。另外毕业设计答辩PPT里要有一页专门讲失败案例。因为所有检测模型都有边界主动展示它的失败场景远比被评委现场问穿要好。我当时展示了一张阳光直射下塑料瓶被漏检的照片解释这是曝光过强导致目标特征被破坏后续考虑了加图像增强预处理。这个思路那里比较受认可说明你能区分“模型没收敛”和“任务本身的难点”这两种情况。这套流程做完后你的项目里会有一套完整可复现的数据、代码、权重和演示脚本。按这个方向做下来对“深度学习目标检测”这条链路会建立起全局的认识——数据是上游模型是中间层演示是出口哪一边断了都会导致整体失败。希望帮到你。本文还有配套的精品资源点击获取