简介:这份课程设计资源以YOLOv5为基础,实现垃圾分类识别检测,面向需要完成高质量课程设计或期末大作业的高校学生,也适合入门目标检测的开发者参考。项目已获导师指导并通过,属于97分的高分作品,附带的源码与数据完整可用,下载后无需改动即可运行,能够直接作为项目展示或功能验证的基础。压缩包共1783个文件,大小约1.22MB,其中包含28个Python源文件用于模型训练与推理逻辑,19个YAML配置文件用于网络结构和训练参数设定,另有YOLOv5官方配套的模型标签缓存、Docker部署文件、Jupyter示例教程等,整体结构清晰、便于定位核心代码。目前已有1082人参与学习下载,说明该项目具备一定的参考价值。使用这份资料,可以快速获得一套可复现的垃圾分类检测流程,包括数据组织方式、模型配置文件与训练脚本,适合在短时间内理解YOLOv5在分类任务中的应用细节。
1. 从课程设计到可上手的yolov5垃圾分类识别检测项目
一个能拿97分的课程设计,通常不是一个炫技的demo,而是把数据、训练、评估、推理串成了一条完整链路。这个基于yolov5垃圾分类识别检测的zip包里,除了常规的源码目录,还有labels.cache、tutorial.ipynb以及各类issue模板,说明它不是一次性脚本,而是按开源工程规范整理的可复现项目。对正在做课程设计或准备期末大作业的学生来说,下载后按README跑通训练和推理,就能直接产出报告素材;对有落地需求的技术人员,这套结构同样能作为垃圾分类检测任务的基础骨架。接下来我从数据、训练、部署三条线拆开讲。
2. yolov5垃圾分类识别检测的数据组织与预处理细节
2.1 数据集目录结构与labels.cache的真实作用
标准的yolov5数据集目录通常是images和labels两个平级文件夹,各自再按train/val划分。这个项目里出现的labels.cache文件,是yolov5在第一次加载数据集时自动生成的缓存——它把每张图片对应的标注文件是否存在、类别分布是否一致等信息序列化成了字典。常见做法是,训练前如果改过标注文件,比如重新标注了某个垃圾桶盖,就要删掉labels.cache再重新训练,否则程序会直接读缓存而不会检查更新。
训练入口是train.py,它的数据参数指向一个data.yaml。这个yaml文件决定了类别名和路径映射,是整个垃圾识别任务里最容易被忽视但影响最大的配置文件。下面是一个典型的垃圾分类data.yaml:
train: data/train # 训练集图片目录 val: data/val # 验证集图片目录 nc: 4 # 类别数量 names: ['cardboard', 'plastic', 'glass', 'metal'] # 类别名在yolov5中,nc和names的顺序必须和标注文件里每个目标的class id严格一致。比如第一个类别cardboard对应的类别id就是0,标注文件中的第一个数字就是它。调试时如果发现某一类的识别率特别低,可以先检查这一项的类别索引是不是被整体平移了一位。很多新手直接从网上复制data.yaml,但自己标注时类别顺序不同,结果所有类别全部错位,训练出来的模型表现非常差。
2.1.1 标注文件格式与坐标归一化
yolov5使用YOLO格式的txt标注,每一行是class_id x_center y_center width height,四个坐标都除以图片宽高做了归一化。这个项目里的分类目标是常见生活垃圾,标注时尤其要注意遮挡和重叠目标。人工标注时我看到不少学生把两个重叠的矿泉水瓶标成了一个框,导致训练时梯度被错误引导。正确的做法是每个完整可见的目标单独一个框,哪怕重叠度很高。如果一个小框完全被大框遮住,也不要额外标注,否则会变成噪声样本。
2.2 数据校验:从labels文件到可训练状态
拿到别人的源码包时,第一件事不是直接train,而是先运行项目自带的校验逻辑。yolov5提供了datasets.py中的check_det_dataset函数,它会自动检查路径是否存在、标注文件是否有空文件、以及类别数是否与nc一致。实际命令行中可以这样快速验证:
python train.py --data data.yaml --epochs 0 --weights yolov5s.pt把--epochs设成0,训练循环不会执行,但数据集加载和cache构建会跑完。你能在控制台看到每个类别的实例数量以及是否有标注异常。如果某个类别实例数为0,说明标注文件里缺少这个类别,训练时这个类别永远学不出来。
在垃圾分类识别检测任务里,常见的几个类别和对应的class id可以参考下面这样的映射:
| 类别名 | class id | 常见标注目标 |
|---|---|---|
| cardboard | 0 | 快递纸箱、废旧纸盒 |
| plastic | 1 | 塑料瓶、塑料碗 |
| glass | 2 | 玻璃瓶、碎玻璃片 |
| metal | 3 | 易拉罐、金属零件 |
提示:项目里附带的tutorial.ipynb如果是在云服务上运行,注意路径要改成绝对路径或相对项目根的路径,否则
labels.cache会生成在错误位置。
数据校验通过后,还要关注图片尺寸。yolov5默认会在load阶段做letterbox缩放,把不同尺寸的图片统一到640x640。如果你的数据集图片是手机拍摄的大分辨率照片,建议先用脚本统一压缩到1000px以内再训练,否则缓存和显存压力会明显增大。常见做法是写一个批处理脚本,用opencv的cv2.imwrite把长边压到1280,并同步保留EXIF信息防止旋转。
3. yolov5垃圾分类模型训练的环境搭建与参数调优
3.1 环境依赖:requirements.txt里的坑
yolov5对依赖版本比较敏感,尤其是torch和opencv。这个项目zip里的Dockerfile和.dockerignore说明作者考虑了容器化运行。常见做法是先创建虚拟环境安装CPU版或CUDA版PyTorch。根据项目内的requirements.txt安装比较稳妥:
pip install -r requirements.txt pip install torch==2.0.1 torchvision==0.15.2 --index-url https://download.pytorch.org/whl/cu118第一行按项目锁定的版本安装上游依赖,第二行重装匹配本地显卡驱动的torch。为什么强调顺序?因为requirements.txt里通常只写torch>=1.7.0,直接装可能装到很新的版本,导致训练时CUDA算子不兼容。先跑一遍requirements,再用官方pytorch源覆盖,能减少八成环境问题。如果你只用CPU跑,可以把第二行的index-url换成cpu版本,但训练速度会慢很多,课程设计时间紧张时不建议。
3.2 训练启动命令与超参数含义
垃圾分类检测算目标检测里的中等难度任务,背景干净、目标形状相对规整,用默认的yolov5s权重做迁移学习就够了。启动训练的命令如下:
python train.py \ --data data.yaml \ --weights weights/yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --cache ram \ --project runs/train/waste逐项拆解:--img 640是网络输入分辨率,默认640,垃圾分类目标不算太小,不需要提高到1280,否则显存和推理时间都会翻倍。--batch 16在8GB显存上比较安全,如果你的卡只有6GB,可以减到8。--cache ram把图片一次性预加载到内存中,能显著减少磁盘IO对训练速度的影响,但20GB内存以下建议用--cache disk。
--weights参数用yolov5s.pt是官方在COCO上的预训练权重,它已经把通用的纹理、边缘特征学好了,迁移到垃圾识别只需要在顶层做细调。如果数据集只有几千张,推荐保留80%的预训练层;如果数据量很大,可以去掉迁移权重从头训练。判断标准看loss曲线——前10个epoch如果val loss不降反升,多半是预训练权重被过度冻结,此时应该把--freeze参数去掉,或者减小学习率。
3.3 超参数文件与anchors的调整
项目根目录的data/mydata.yaml只是数据配置,训练超参数在train.py里通过--hyp指定,默认是data/hyps/hyp.scratch-low.yaml。对垃圾分类场景,我一般会在原始基础上改两个关键参数:
lr0: 0.01 # 初始学习率 lrf: 0.01 # 最终学习率衰减比例 mosaic: 1.0 # mosaic增强概率 fliplr: 0.5 # 水平翻转概率lr0过大会导致loss震荡,过小则收敛慢。从0.01起步、配合余弦退火到0.0001是yolov5比较稳定的组合。mosaic是yolov5最依赖的数据增强,它把四张图拼成一张,迫使模型学会遮挡场景下的垃圾目标。注意,如果检测对象特别小,比如识别细碎的塑料碎片,mosaic概率太高反而让目标变得更难学,这时可以降到0.8。fliplr水平翻转对可乐瓶这类对称目标没问题,但如果要识别带有文字标志的垃圾包装,0.3以下更合适。
另一个需要动手改的是anchor。yolov5启动训练时会自动基于训练数据做K-means聚类重新计算anchors,并把结果打印出来。查看runs/train/waste/下的opt.yaml可以确认是否启用了自定义anchors。如果垃圾目标长宽比接近1:1,而原本COCO预训练的anchors偏横向长条,重新聚类会明显提升小目标的召回率。在--hyp指定的yaml里把anchor_t设为4.0,可以放宽anchor匹配阈值,让更多目标参与训练。
3.4 训练中断与断点续训
课程设计时间紧,训练中途断电或显存溢出很常见。yolov5在训练过程中会隔一段时间保存last.pt,恢复训练时直接加参数:
python train.py --data data.yaml --weights runs/train/waste/weights/last.pt --resume--resume会读取上次训练的全部配置,包括epoch、batch、优化器状态。需要说明的是,恢复训练时不要再重复指定--project或--name,否则路径不对会从start epoch重新计算。遇到显存不够,最直接的办法是减小batch并把--cache从ram改为disk,而不是换更大的模型。在8GB显卡上,如果batch=16仍然OOM,可以尝试--workers 4减少数据加载线程的内存占用。
4. 模型评估与推理部署:从mAP到实际识别
4.1 使用val.py评估模型,看懂每项指标
训练结束后,项目里会生成runs/train/waste/weights/best.pt。在它被用到现场之前,需要用验证集跑一次标准评估:
python val.py --data data.yaml --weights runs/train/waste/weights/best.pt --img 640 --conf 0.25 --iou 0.45--conf 0.25是置信度阈值,低于这个值的预测框会被过滤;--iou 0.45是NMS阶段的IoU阈值,控制两个框是否需要合并。输出结果里有mAP@0.5和mAP@0.5:0.95两项。垃圾分类课程设计如果mAP@0.5能到0.92以上,说明基础流程没有大问题;而mAP@0.5:0.95是对框位置精度的更严格考量,这个值通常比前者低十个点。如果这个差距超过15个点,说明边框回归还不够准,应该检查标注框是否贴合目标边缘。
评估完成后,在runs/val/exp下会有混淆矩阵和PR曲线。看混淆矩阵时重点关注易混类,比如玻璃瓶和透明塑料瓶,这两类在光照下视觉特征接近,容易互相误判。如果混淆明显,不要急着调模型,先在数据集层面补充这两类的硬样本。补充样本时要保持背景多样性,否则模型会对特定背景过拟合,换一个场景就失灵。
4.2 推理:图片、视频和摄像头实时识别
yolov5的推理入口是detect.py,它对单张图片、视频文件、摄像头都能直接工作:
python detect.py --weights runs/train/waste/weights/best.pt --source data/test.jpg --conf 0.35 --save-txt --save-conf--source可以指图片路径、视频目录,或者用0表示摄像头。--save-txt会把检测结果以txt形式输出到runs/detect/exp/labels,每行是类别id和框坐标;--save-conf会把置信度追加在行尾。如果你是做课程设计答辩展示,建议用--source 0跑摄像头实时识别,配合一个简单的UI,展示效果比单张图片直观得多。
摄像头场景下有个坑:默认模型推理速度足够,但显示端的延迟往往来自cv2.imshow的绘图循环。常见做法是把帧率统计放到主循环外,并把输入帧和检测帧分离。如果模型跑到30ms一帧,但屏幕显示卡顿,问题通常出在彩色空间转换或窗口渲染上。你可以用cv2.resize先把画面缩到720p再送去检测,这样对垃圾这类大目标几乎不影响精度,但帧率能提升30%以上。
在检测结果里,除了可视化图片,--save-txt输出的txt文件也是答辩报告里常用的定量数据。它的每行格式是class x_center y_center width height conf,与标注文件相比多了最后一列置信度。在换算成像素坐标时,要记得先乘以图片的宽高,这和标注预处理是相反的。很多学生在写报告时把两种坐标混用,导致统计的检测框数量与实际可视化结果对不上。建议在代码里直接用一个换算函数统一处理。
4.3 导出ONNX和TensorRT模型
训练界面之外,部署到边缘设备时一般会先用export.py做模型转换。这个项目在Dockerfile里带了opencv等依赖,说明有跨平台部署意图。导出ONNX的命令:
python export.py --weights runs/train/waste/weights/best.pt --include onnx --opset 11 --imgsz 640--opset 11对应较老和较新推理引擎都能兼容的算子集。导出ONNX后,可以用onnxruntime直接推理,也可以再接TensorRT做半精度优化。对于canmv k230这类带NPU的嵌入式板子,通常流程是先把模型导出为onnx,再用板子的工具链转换为.kmodel。这里要注意,yolov5在detect.py里的后处理代码是基于PyTorch实现的,转换成.kmodel后需要在C代码里重新实现NMS,否则输出结果会是一堆未过滤的原始预测框。另外,TensorRT导出的engine文件与显卡架构强相关,换卡后要重新导出,不要直接拷贝。
5. 垃圾分类检测落地的三个实用技巧
5.1 用自动标注减少人工成本
课程设计里的数据量通常有限,但标数据的时间往往超过训练时间。yolov5自带的模型可以帮你预标注,假设你已经有一个在垃圾瓶上训练好的初版模型:
python detect.py --weights runs/train/waste/weights/best.pt --source ./unlabeled --save-txt --nosave--nosave表示不保存带框的图片,只把txt坐标写到labels文件夹。跑完后用labelImg或labelme打开,逐张确认并修正错误框。这样标注工时大概能减少四五倍,特别适合新增一种垃圾类别时快速采集训练集。注意,预标注的置信度阈值不要设得太低,通常0.5以上,否则会有大量假正例需要手动删除。
5.2 跳帧检测与帧缓冲
摄像头推理时,如果模型单帧推理耗时大于视频帧间隔,可以把检测和取流拆到两个线程,并用一个双缓冲队列避免丢帧。一段简化的实现思路:
import threading import queue def infer_worker(q_in, q_out, model): while True: frame = q_in.get() result = model(frame) q_out.put((frame, result)) q_in = queue.Queue(maxsize=2) q_out = queue.Queue(maxsize=2) threading.Thread(target=infer_worker, args=(q_in, q_out, model), daemon=True).start()q_in长度设为2,这样当模型处理慢于摄像头采集时,新帧会覆盖旧帧而不是无限堆积,视频流的实时性不会因为检测速度而持续恶化。要注意队列的maxsize按实际显存和内存情况设定,过大会导致延迟越来越高,过小则浪费算力。如果检测任务对延迟要求不高,可以改为每隔一帧处理一次,这样推理开销直接减半。
5.3 从课程设计到实际部署的边界
课程设计的验收标准通常只看mAP曲线和几个测试视频。实际部署时还要考虑两个容易忽略的点:一是垃圾桶内目标互相遮挡,二是低光照环境。应对遮挡,可以增加标注框的贴合度;应对暗光,可以在推理前加一次自适应直方图均衡化,代价是每帧多约2ms。如果你的项目里已经有这些处理逻辑,说明它不是简单的demo,而是真正能跑的工程。利用项目里自带的tutorial.ipynb里的分步cell,每次只改一个环节并记录指标变化,是排查模型回归问题最直接的方式。
本文还有配套的精品资源,点击获取