资讯详情

基于YOLOv8的垃圾桶满溢检测:从数据标注到部署的完整落地路径

📅 2026/10/1 9:27:40 | 华诺云谱 👁 阅读
基于YOLOv8的垃圾桶满溢检测:从数据标注到部署的完整落地路径
简介基于YOLOv8的智能垃圾桶满溢检测项目面向计算机视觉、深度学习相关专业的毕业设计或课程设计场景内置完整源码、可视化界面、配套数据集与部署说明可直接运行适合需要快速落地项目的学生或开发者。压缩包共八个文件包含三个Python脚本覆盖界面展示、视频检测、训练入口、三个模型权重文件预训练权重与训练所得权重以及两个说明文档整体约15.91MB结构紧凑便于下载后快速上手。目前已吸引44人浏览学习。项目代码经过完整测试运行后可输出核心指标曲线、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果及标签分布图覆盖模型训练到评估的主要环节答辩展示时能提供扎实的过程证据适合直接作为课题交付或在基础上扩展功能。1. 用YOLOv8做垃圾桶满溢检测一份能拿去当毕设的完整落地路径拿到《基于YOLOv8的智能垃圾桶满溢检测》这个题目很多同学的第一反应是解压压缩包直接看源码但最划得来的打开方式其实是先想清楚一件事满溢检测本质上是在监控画面里判断垃圾桶的垃圾堆积程度是否已经触发清运需求。它解决的是人工巡检成本高、反馈不及时的问题这也是它适合毕设的原因——目标检测、数据集制作、可视化界面、部署演示四条线全都能覆盖。这篇文章不猜源码里写了什么只按常规毕设的完整技术闭环讲透选型理由、数据准备、训练参数、常见坑和演示方法新手能照着复现熟手能查缺补漏。2. 满溢检测为什么锁死YOLOv8场景约束、模型选型与标签设计2.1 垃圾桶场景为什么不是分类而是检测问题先看一个容易走偏的选题点垃圾桶满溢检测到底该用分类模型还是检测模型很多人第一反应是这不就是判断满没满于是直接上ResNet做二分类。真实场景里这套做法会很快翻车原因在摄像头视角。常见部署位置有两个一个是垃圾桶正上方俯拍另一个是侧面斜下方拍摄。无论哪种角度画面里通常不止一个垃圾桶而且桶的位置在画面里是固定的变化的只有垃圾的高度、颜色和轮廓。分类模型能回答这张图里有没有满溢但它回答不了哪个桶满了。起步可以不管一旦现场有三个并排桶方案就立不住了。检测模型能同时给出位置框和类别后续界面展示、联动告警、按桶编号输出记录全部依赖这个位置信息。另一个原因是鲁棒性。垃圾桶外有行人、车辆、树木穿过分类模型会把整张图的全局特征拿来判断很容易被干扰检测模型只对目标区域内的特征做判定背景干扰的影响天然更小。所以这个选题的正确起点是目标检测不是图像分类。2.2 YOLOv8对比YOLOv5和SSD毕设怎么选回本的模型确定要用检测模型后候选就是SSD、YOLOv5、YOLOv8这几套。SSD是经典但吃亏在要手动调anchor它把anchor的宽高比、尺度当成超参暴露给你实际调起来非常玄学不同数据集要重新试毕设周期根本耗不起。YOLOv5和YOLOv8之间能力差距不是质变的但对毕设来说YOLOv8有几个细节更省事网络结构上v8把C3模块换成了C2f梯度回传路径更丰富小目标特征保留更好检测头改成anchor-free的decoupled head分类和回归分支分开收敛更快标签分配用的是TaskAlignedAssigner不需要你手动指定anchor尺寸。从硬件角度算一笔账。毕设实验室常见的是GTX 1660 Ti这种6GB显存卡YOLOv8s在这个卡上跑batch为8、imgsz为640是能稳定落地的如果只有CPUYOLOv8s在Ubuntu 20.04上搭CPU环境也能训练只是慢但推理做演示完全够用。相比之下SSD的精度撑不起满溢这种垃圾边缘不规则的检测目标。还有一个网络结构上的得分点答辩时被问到为什么选YOLOv8你至少能说出C2f、decoupled head、anchor-free这三个词背后的设计动机而不是只会说精度高。2.3 标签怎么定一个框解决还是两段式检测标签体系是这个项目里最容易被低估的设计决策。常见做法有三种思路只检测垃圾堆、检测垃圾桶垃圾堆、先检测桶再判断填充高度。只检测垃圾堆的问题在于垃圾桶本身没有参与模型逻辑一旦桶被移走或者视角换了模型不知道桶在哪误报率很高先检测桶再做高度判断听起来严谨但实现里要额外维护一个视野映射关系毕设工作量直接翻倍。我一般推荐做两个类别bin垃圾桶和overflow满溢垃圾。overflow框选的是桶内垃圾堆积超出正常水平、明显溢出桶口的区域模型只要在画面里同时检出bin和overflow就判定为满溢。这个定义让标注直观、指标可解释答辩时也说得清。data.yaml 的常规写法path: data train: images/train val: images/val names: 0: bin 1: overflow注意path建议写成绝对路径否则换机器跑的时候相对路径找不到数据会直接报AssertionError: train dataset not found。names的编号必须和标注文件里的类别编号一致这是训练环节最常出问题的地方。3. 解压数据集后的第一件事标注自查与最小环境搭建3.1 数据集五步自查先别急着开训拿到一份现成数据集直接扔进 YOLOv8 开训是风险最高的操作。别人的标注规范和你以为的很可能不是一回事。我每次拿到新数据都会先做五件事全做完再碰训练命令。第一步统计样本总量和类别分布。用 Python 快速扫一遍import os from collections import Counter labels_dir data/labels/train counter Counter() total_boxes 0 for fname in os.listdir(labels_dir): if not fname.endswith(.txt): continue with open(os.path.join(labels_dir, fname), r, encodingutf-8) as f: for line in f: cls int(line.strip().split()[0]) counter[cls] 1 total_boxes 1 print(样本文件数:, len([f for f in os.listdir(labels_dir) if f.endswith(.txt)])) print(各类别框数:, dict(counter)) print(总框数:, total_boxes)这个脚本的作用是确认类别编号是从 0 开始、没有出现cls超出names范围的情况。常见问题是类别编号从 1 开始或者标注文件里混了-1之类的占位符号。顺手统计 box 总数如果overflow的框数连bin的十分之一都不到后面训练基本可以预见满溢类别会漏检。第二步把标注画到图上肉眼抽查。这一步能发现很多统计看不出来的问题框是不是把整只垃圾桶都框进去了、垃圾堆框是不是标到了桶外、有没有框完全偏离目标。画一张抽查图不复杂用 OpenCV 读图、画矩形、保存即可抽查 20-30 张就够了。第三步检查标签格式。YOLO 的 txt 格式是class x_center y_center width height四个数值都是归一化到 0-1 之间的浮点数。如果看到的坐标是整数大概率是 Pascal VOC 或 COCO 转出来的中间格式必须转。第四步看图像尺寸分布。有些数据集混着 1920x1080 和 640x480 的图YOLOv8 训练时会做 letterbox 缩放短边被严重拉伸会影响小目标检测。要么统一分辨率要么训练时把imgsz调到和主流尺寸接近。第五步检查 train/val 划分方式。如果数据集是从监控视频抽帧来的必须确认同一段视频的连续帧没有被同时分进 train 和 val。这个泄漏导致的假象非常隐蔽后面避坑章专门讲。3.2 环境组合Ubuntu 20.04 CPU 版和 GPU 版的差异环境搭建是老生常谈但对这个项目版本组合直接决定后续三天是顺利还是折腾。很多人在 Ubuntu 20.04 上搭 YOLOv8 的 CPU 环境时照着网上的教程装了个完整的 CUDA toolkit其实 CPU 推理完全不需要 CUDA装了反而可能和驱动冲突。可靠的做法是直接用 conda 建独立环境按需选择 torch 版本conda create -n yolo python3.9 -y conda activate yolo pip install ultralytics # CPU 版本 pip install torch2.0.1 torchvision0.15.2 # GPU 版本先确认驱动支持的 CUDA 版本 pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118CPU 版和 GPU 版最大的差别就在torch的安装来源。CPU 版下载体积小、不会报CUDA error: no kernel imageGPU 版要先看nvidia-smi里 Driver 版本支持的 CUDA 版本号。GTX 1660 Ti 装 CUDA 11.8 的 torch 是常规操作太新的 cu121 也能用但没必要。还有一个坑不要直接pip install -r requirements.txt覆盖 torch。项目里给的 requirements.txt 往往锁的是作者本机的版本你一旦装了torch 可能被降级或升级到和你显卡不匹配的版本。正确顺序是先把 torch 装好再装 ultralytics最后才考虑 requirements 里剩余的辅助包。3.3 labelme标注转YOLO格式那段转换脚本要注意的边界不少数据集是用 labelme 标注的导出的是 JSON 文件里面存的是多边形点坐标。YOLO 需要的是归一化中心点和宽高。转换脚本的逻辑不难边界情况却很磨人。import json import os import glob CLASS_MAP {bin: 0, overflow: 1} def convert_labelme_to_yolo(json_path, out_dir, image_size): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_w, img_h image_size lines [] for shape in data[shapes]: label shape[label] if label not in CLASS_MAP: continue points shape[points] # [[x1,y1],[x2,y2],...] xs [p[0] for p in points] ys [p[1] for p in points] xmin, xmax min(xs), max(xs) ymin, ymax min(ys), max(ys) # 归一化到 [0,1] x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{CLASS_MAP[label]} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) out_path os.path.join(out_dir, os.path.basename(json_path).replace(.json, .txt)) with open(out_path, w, encodingutf-8) as f: f.write(\n.join(lines)) # 调用示例注意 image_size 要和原图一致否则坐标全偏 for jp in glob.glob(labelme_data/*.json): convert_labelme_to_yolo(jp, yolo_labels, image_size(1920, 1080))这个脚本有三个边界必须检查一是image_size必须和原图真实尺寸一致很多 JSON 里不存尺寸你得从原图读否则 x_center 会算错二是points里如果只有一个点有些 labelme 版本支持单点标注min(xs)和max(xs)相等width 算出来是 0这种样本必须跳过三是类别编号 0 在 YOLO 里的含义是第一类如果你的 CLASS_MAP 把空标签设成 0会出现所有框都变成背景。转完之后随机抽几个 txt人工对照原图确认坐标没有整体偏移。4. 训练命令与参数从跑通到能用还差哪三步4.1 一行训练命令和参数调法的含义数据集自查完、环境装好后训练只是命令的问题。但能跑和能用是两回事。最小可用的训练命令是这一行yolo detect train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch8 device0拆开看每个参数的取舍。modelyolov8s.pt表示加载 COCO 预训练权重对毕设来说这个选择比从头训练划算得多收敛快、mAP 高而且yolov8s是体积和精度平衡点。epochs100是常见区间60 轮基本能看出模型行不行但满溢检测这种目标外观差异不大、同一个桶在一天不同光照下长相差很多的任务100 轮更稳。imgsz640是默认值如果你的数据集里有大量小目标可以试 960但 GTX 1660 Ti 上显存会吃紧训练时间也变长。batch8是 6GB 显存的常见上限显存报错CUDA out of memory时先减到 4这是最直接的解决方式。device 参数要注意只有一块 GPU 时写device0没有 GPU 时删除该参数或写devicecpu。CPU 训练不是不能跑只是 100 轮可能要好几个小时建议先用epochs10验证数据加载和 loss 计算没有报错再开长训练。训练结束后weights 目录下会有best.pt和last.pt评测和导出一律用best.pt。看训练是否正常不要只看终端输出的那个 mAP 数字要进入下一个环节看曲线和混淆矩阵。4.2 判断训练成果的量化指标loss曲线、mAP50、混淆矩阵很多同学训练完只盯着一张results.png其实 YOLOv8 训练过程会自动保存results.csv里面有每一轮的 train loss、val loss、mAP50、mAP50-95 等完整记录。你可以直接用 pandas 画出 loss 曲线这是毕设报告里最有说服力的素材之一。import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) # 列名可以打印 df.columns 确认ulogic 版本不同列名略有差异 plt.figure(figsize(10, 6)) for col in [train/box_loss, val/box_loss]: plt.plot(df[epoch], df[col], labelcol) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.grid(True) plt.savefig(loss_curve.png, dpi150)判断标准很简单val loss 在下降说明模型在学val loss 先降后升而 train loss 一直降是过拟合的信号这时候要么加数据增强、要么提前停。看 mAP50 时垃圾桶满溢检测的 mAP50 到 0.85 以上才算基本可用低于 0.7 说明数据或标签有问题调参救不回来。混淆矩阵同样重要YOLOv8 会在results/confusion_matrix.png里输出归一化混淆矩阵。重点看overflow类别是不是大量被预测成bin如果是说明两个类别的形态学区分度不足需要在标注阶段把 overflow 框选得更严格让正负样本边界清晰。4.3 可视化界面拆解视频流、推理、结果展示之间的结构给项目加可视化界面最常见的路线是 PyQt5、Tkinter 或者 Flask Web 页面。不管用哪种好的结构都是三层视频流读取、模型推理、结果渲染。如果源码自带的界面把这三层写在一个文件里建议你拆开这样后续换模型、加功能都好改。我一般习惯保存一个独立的推理脚本界面直接调用它这样界面调试和模型调试互不干扰import cv2 from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) cap cv2.VideoCapture(test_video.mp4) # 换成 0 可以读取摄像头 while cap.isOpened(): ret, frame cap.read() if not ret: break results model.predict(frame, conf0.5, imgsz640, verboseFalse) for r in results: boxes r.boxes for box in boxes: cls int(box.cls[0]) conf float(box.conf[0]) x1, y1, x2, y2 map(int, box.xyxy[0]) label f{model.names[cls]} {conf:.2f} cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255) if cls 1 else (0, 255, 0), 2) cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255) if cls 1 else (0, 255, 0), 2) cv2.imshow(YOLOv8 Trash Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段代码的关键是model.predict的conf参数。满溢检测场景下conf0.5是常见起点如果漏检明显就降到 0.3如果现场误报太多就调高到 0.6。分类别调阈值是更精细的做法bin用 0.5overflow用 0.3因为漏掉一个满溢桶比错报一个空桶代价更大。界面上建议把满溢状态额外弹窗或者置红色高亮仅仅画一个框在毕设答辩现场不够直观。5. 避坑数据集与部署阶段最常翻车的5个问题5.1 现象一训练 loss 直接 NaN现象训练刚开始几轮终端输出里box_loss变成nan之后一直不恢复模型权重直接报废。原因最常出在数据标注上。某个标注文件里出现了width或height为 0或者归一化坐标超出 0-1 范围导致 loss 计算出现无穷值。另一个可能是学习率设得过大用了项目里改过的lr00.1之类激进参数。解决先跑一个数据清洗脚本扫描所有 txt 里坐标数值把width0或height0或坐标不在[0,1]区间的文件挑出来。学习率方面把lr0改回默认的0.01。如果还无法恢复尝试降低 batch 大小某些显卡驱动下 batch 过大也会触发数值溢出。5.2 现象二训练 loss 正常下降但 mAP50 不到 0.5现象train loss 一直在降val loss 也在降模型训练过程看起来一切正常可验证集 mAP50 始终上不去。原因最大的嫌疑是 train/val 划分泄漏。如果数据集来自同一段监控视频按帧抽取相邻帧几乎一样模型在训练帧上已经见过验证帧的内容但对象遮挡、光照变化仍然让它泛化不了。另一种原因是标注框本身就画错了模型终究没法学到正确的目标定义。解决按时间序列划分数据取前 80% 的帧做 train、后 20% 做 val绝不随机打乱。重新检查标注框是否贴住目标边缘尤其注意垃圾堆的框是否把大量背景墙划进了正样本。5.3 现象三满溢目标几乎全部漏检现象模型能很好检测垃圾桶但满溢类别基本不打框偶尔出的框置信度也极低。原因类别不平衡。overflow样本数量远小于bin模型学习到的先验偏向多数类。这是垃圾满溢场景的通病——满溢状态持续时间短采集到有效样本本身就难。解决优先补数据把满溢样本增加上来这是最有效的。如果时间不允许可以给overflow类别设更高的 loss 权重YOLOv8 里可以用cls参数调分类 loss 比重。还有一个低成本的土办法把满溢判定阈值降低、在接口逻辑里要求检测到 bin 的同时检测到 overflow 才触发告警这样类别没被模型漏掉误报也能被抑制。5.4 现象四CPU 环境推理太慢界面卡成 PPT现象模型训练完在 CPU 机器上跑可视化界面推理一帧要几百毫秒视频根本带不动。原因YOLOv8 自带 PyTorch 推理在 CPU 上效率不高且大尺寸输入会显著放大耗时。很多人直接把 1920x1080 的原图送进模型imgsz 没限制耗时自然爆炸。解决推理时把 imgsz 固定为 640模型内部会做 letterbox输入尺寸降下来速度提升明显。如果还是慢把模型导出成 ONNX 用 ONNX Runtime 跑 CPU 推理通常能快 2-3 倍。界面设置里加一个推理分辨率选项默认 640答辩现场可以根据电脑性能实时调整。5.5 现象五可视化界面显示的框和视频画面明显错位现象摄像头画面里垃圾桶在左上角但模型画出来的框标在画面中央目标位置完全对不上。原因YOLOv8 的 letterbox 预处理会在输入图片四周填充灰边模型输出的检测框是基于填充后的坐标系的。界面代码如果直接拿这个坐标往原始画面上画就会整体偏移填充越多偏得越狠。解决推理时拿到结果后用results[0].plot()让模型自己把框画在 letterbox 处理后的图上再裁剪掉灰边输出给界面。或者严格记录 letterbox 的填充参数反向换算到原图坐标。最容易踩坑的是在窗口里显示时画面又做了一次缩放坐标还要再乘一个缩放系数才匹配。6. 把模型装进现场导出、ROI与演示视频的验证法6.1 导出ONNX一行命令和省掉环境问题的收益训练完best.pt只是第一步答辩现场最怕的不是模型不准而是演示机器上没有安装正确版本的 PyTorch 和 CUDA。导出 ONNX 是最稳妥的后悔药yolo export modelruns/detect/train/weights/best.pt formatonnx imgsz640导出后用 ONNX Runtime 做推理只需要pip install onnxruntime连显卡都不需要。导出后务必检查输出的 batch 维度默认导出的模型可能固定 batch 为 1界面里如果用了 batch 推理会报错。验证导出的模型精度和原版是否一致用同一张测试图对比两次推理的框坐标偏差小于 0.02 就算正常。6.2 ROI遮罩让满溢检测只发生在摄像头画面里指定的区域现场演示时画面角落往往会混入不属于任务目标的杂物。一个高价值的技巧是给检测区域加 ROI 遮罩让模型只关注画面中真正的垃圾桶区域。方法是预设一个多边形掩码推理前把掩码外的像素置黑import cv2 import numpy as np roi_points np.array([(100, 200), (500, 200), (500, 700), (100, 700)], dtypenp.int32) mask np.zeros(frame.shape[:2], dtypenp.uint8) cv2.fillPoly(mask, [roi_points], 255) def apply_roi(frame): masked frame.copy() masked[mask 0] 0 return masked这个做法的价值不只是提升精度更重要的是演示可控性摄像头抖动、行人路过、光照突变都不会在画面外区域产生误报。答辩时展示这一层的设计能直接说明你理解模型能力只是系统的一部分约束条件才是工程落地。我自己的习惯是拿到任何别人给的模型第一件事不是看指标而是重新标注 20-30 张自己拍的现场照片去测它只有跑通这一步这个压缩包里的东西才算真正属于你。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑