基于YOLOv8与Django的路面垃圾检测系统设计与实现

发布时间:2026/9/1 19:48:26
基于YOLOv8与Django的路面垃圾检测系统设计与实现 简介本资源是一套基于Python深度学习与Django框架开发的路面垃圾智能检测系统面向计算机专业本科生毕业设计、课程设计及AI视觉应用实践者解决城市环卫场景中垃圾识别效率低、人工复核成本高的实际问题。压缩包含1707个文件总大小465.98MB涵盖63个核心Python模块含模型训练与推理逻辑、47个HTML前端页面、37个CSS样式文件、49个JS交互脚本、1353个SVG图标资源以及MySQL建表SQL、PPT答辩材料、详细说明文档和论文LW完整支撑前后端部署与演示。已有83人学习下载资源结构清晰Bootstrap与LayUI双前端框架并存支持单图/批量/摄像头/视频四类识别模式并集成用户任务领取、图片上传复核、管理员任务派发与用户权限管理等闭环业务流程开箱即用适合作为深度学习落地项目的学习范本与毕设参考。 写这篇东西之前先交代一下背景。我去年带了好几个做毕业设计的学弟其中有两个选了“路面垃圾检测”这个方向。当时他们找了一圈网上的毕设源码很多要么只有模型代码要么Django脚手架搭了个空壳数据库连表结构都没有更别说说明文档和PPT了。后来我帮他们把整个系统从零到尾捋了一遍从数据集标注到模型训练再到Django把模型封装成Web服务MySQL存检测记录最后才明白这活儿看上去是个“毕设”实际上是把目标检测、Web开发、数据库设计、前后端联调全塞进了一个项目里。今天就把这套完整体系的搭建过程掰开揉碎讲清楚。1. 项目整体设计与思路拆解1.1 核心需求解析路面垃圾检测到底要做什么路面垃圾检测系统说白了就是给城市环卫、道路养护这类场景搞一个能自动识别路面垃圾的智能工具。它的核心流程是用户上传一张路面图片系统调用深度学习模型识别图片里的垃圾目标比如饮料瓶、纸屑、塑料袋、烟头等返回检测结果包括垃圾类别、位置坐标、置信度然后把检测记录存进数据库方便后续追踪和统计。从功能层面拆这个系统必须包含三大块。第一块是检测能力这是核心背后需要一个训练好的目标检测模型。第二块是业务承载用户怎么上传图片、怎么看到结果、历史记录怎么管理这需要Web系统来承接。第三块是数据存储检测记录、图片路径、用户操作日志这些都要落到数据库里。这个项目标题里写了django、mysql正好对应后两块。很多人做毕设容易犯一个毛病一上来就追求模型的识别精度拼命调参刷mAP结果Web端搞得稀烂答辩的时候导师问几个业务逻辑问题就卡壳。其实毕设项目的本质是把你学过的知识点串起来展示你具备完整开发能力而不是只秀一个训练好的模型。所以我的建议是模型和Web端要均衡发力模型能跑通、能出检测框系统能上传图片、能存记录、能查历史这套闭环走通了比单个点做得再深都更有说服力。1.2 技术选型的关键考量为什么是YOLO、Django和MySQL模型方面现在做目标检测的主流选择就是YOLO系列。YOLOv8是Ultralytics官方维护的版本安装方便一条pip命令搞定训练接口封装得特别友好而且生态完善导出成TorchScript、ONNX都很容易。为什么不用R-CNN系列或者SSD这些一个是两阶段模型训练复杂、推理慢另一个是SSD对小目标效果一般。路面垃圾这种场景塑料瓶、烟头、纸屑都算小目标而YOLOv8的anchor-free机制对小目标检测能力明显优于YOLOv5以前的老版本。这里我建议用YOLOv8s或者YOLOv8mv8s速度快CPU也能勉强跑v8m精度更高但显存占用也大。如果是自己的电脑没有独立显卡就选v8s如果有GPU选v8m。这块后面训练章节还会细说。Django这边它的优势是“全家桶”ORM、Admin后台、模板引擎、表单处理全都有可以让你不用重复造轮子。写一个上传图片、调模型、回显结果、存记录的闭环Django原生的MTV模式刚好能对上。另外Django自带的Admin后台可以直接管理数据库表毕设答辩的时候现场往数据库里加几条记录比纯靠SQL语句操作直观得多。更重要的是Django文档丰富、中文社区活跃遇到问题一搜就有答案这在赶毕设的时候能救命。数据库选MySQL一是主流、就业场景用得多二是Django的ORM对MySQL支持得非常完善。有些同学为了省事直接用Django默认的SQLite这也能跑但毕设题目里既然写了mysql你用SQLite就有货不对板的问题答辩容易被追问。MySQL需要装好客户端还要建好数据库和账号授权具体操作后面章节会给完整的命令。2. 系统架构与核心模块设计2.1 项目目录结构与分层设计拿到手一个项目源码先别急着跑先把目录结构看懂。一个规范的Django深度学习检测项目的目录应该长这样garbage_detection/ ├── manage.py ├── config/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── detection/ │ ├── __init__.py │ ├── models.py │ ├── views.py │ ├── urls.py │ ├── apps.py │ └── yolo/ # 存放模型相关文件 │ ├── best.pt │ ├── detect.py │ └── ... ├── media/ │ └── uploads/ ├── static/ ├── templates/ │ ├── base.html │ ├── index.html │ └── result.html └── requirements.txt这里config目录是Django项目的全局配置detection是核心业务应用yolo子目录放模型权重和推理代码media存放上传的图片templates放HTML模板。看清楚这个结构你后面改代码、调逻辑才不会迷路。2.2 数据库表结构设计要点数据库是整个系统的数据底座。路面垃圾检测系统至少需要两张表一张存检测记录一张存用户信息如果有多用户需求的话。用户表可以直接复用Django自带的auth_user表不需要自己新建。检测记录表是关键它的字段设计要能完整覆盖一次检测的输入、输出和操作上下文。我设计的检测记录表字段如下字段名类型说明idint(11)主键自增userint(11)关联auth_user表的外键记录操作人image_pathvarchar(255)上传图片的地址result_jsonlongtext检测结果JSON包含类别、坐标、置信度num_garbageint(11)检测到的垃圾数量created_timedatetime检测时间result_json字段用longtext类型存整个检测结果的JSON串比单独建一张垃圾明细表更灵活。因为不同批次的模型输出的类别可能不同如果硬拆成明细表模型一换类别表结构就要变。存JSON的好处是模型输出什么就存什么查询的时候用Django的JSONField还能按关键字过滤。这是我在实际项目里摸索出来的做法比常规设计少踩很多坑。建表语句可以用Django的ORM迁移来自动生成不用手写CREATE TABLE。只需要在detection/models.py里定义好模型类然后跑python manage.py makemigrations和python manage.py migrate两条命令Django会自动帮你建表。具体代码后面给出。2.3 Web端功能模块与页面规划Web端不需要太花哨能讲清楚业务闭环就够了。我建议做三个页面。第一个是首页展示项目名称、简介、系统架构说明放一张示例图片的检测效果让人一进来就知道这系统是干什么的。第二个是检测页提供一个图片上传控件用户选择图片后前端通过表单或AJAX提交到后端后端调用模型推理把结果渲染到页面上同时显示检测前和检测后的对比图以及每个垃圾的类别和置信度列表。第三个是历史记录页以表格的形式展示过去所有的检测记录支持按时间筛选和删除记录每条记录点进去可以看到当时的检测详情。这里要提醒一点页面风格保持简洁干净就行不要花太多时间调CSS。毕设评分重点在于功能完整和技术含量而不是UI炫酷。用Bootstrap的默认样式稍微改改配色十分钟就能搭出不错的页面。3. 深度学习检测模型训练与集成实操3.1 数据集准备与标注模型训练的起点是数据。路面垃圾检测的公开数据集不算多我当年给学弟推荐的是TACOTransparent Anthropocentric Trash数据集这个数据集专门做垃圾检测包含几十个类别不过原始的标注格式是COCO格式需要转换成YOLO格式才能给YOLOv8用。如果你不想用公开数据集也可以自己拍图、自己标注。手机拍个几百张不同场景的路面照片用labelImg或者labelme标注成YOLO格式的txt文件每行是一个目标的类别id和归一化后的中心坐标、宽高。注意地面垃圾的尺度问题很多垃圾在画面里只占很小一块标注的时候一定要贴紧目标边缘不要留白太多不然训练出来的预测框会偏大。数据增强这块YOLOv8训练时自带Mosaic、随机翻转、色彩抖动等增强策略一般不需要自己额外处理。但如果你的数据集中烟头、瓶盖这类小目标数量偏少可以手动复制小目标样本做几次平移、旋转或者用SAHI这类切片检测工具辅助标注小目标。我实测下来小目标占比提上来之后模型mAP能涨好几个点。3.2 基于YOLOv8的模型训练命令与参数配置环境配置这里直接给出命令。需要满足Python版本3.9及以上建议用虚拟环境避免和系统环境互相污染。# 创建并激活虚拟环境 python -m venv yolov8env # Windows系统激活命令 yolov8env\Scripts\activate # Linux/Mac系统激活命令 # source yolov8env/bin/activate # 安装ultralytics和pytorch pip install ultralytics # 如果本机有NVIDIA显卡先装对应版本的pytorch-cuda然后 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118数据集目录结构按照YOLO格式组织data.yaml文件里写清路径和类别。data.yaml的内容大致如下train: ./datasets/garbage/images/train val: ./datasets/garbage/images/val nc: 2 names: [bottle, plastic_bag]这里是示意实际类别数量按你的标注来。然后跑训练命令yolo detect train datagarbage.yaml modelyolov8s.pt epochs100 imgsz640 batch16 device0参数说明epochs建议100起步显存充足可以到200imgsz640是输入图片尺寸YOLOv8对640大小的图适配最好batch根据显存大小调整12G显存跑yolov8s最多放32device0表示使用第一块GPU如果没有GPU就改成devicecpu但速度慢很多。训练完成后best.pt就是验证集上表现最好的权重文件把它拷贝到Django项目的detection/yolo目录下备用。3.3 模型评估指标与性能优化训练结束时终端会打印出各种指标。我判断模型够不够用主要看三个地方。第一个是Precision和Recall两者最好都在0.8以上如果Precision高、Recall低说明模型偏保守容易漏检反之则容易误检。第二个是mAP50和mAP50-95mAP50能到0.9左右就相当不错了mAP50-95因为IOU阈值更严格一般在0.5到0.7之间都算合理。第三个是推理速度用GPU跑一张640x640的图YOLOv8s大约需要10到20毫秒如果超过100毫秒就要检查是不是GPU没调用上或者模型太大。如果训练出来的模型精度不理想别急着换模型先检查你的数据集。常见问题是类别不均衡某个类别的图片特别多另一个特别少。解决办法是复制少样本或者用增强方式把少数类变多。还有一个问题是标注质量标注框偏移或者漏标都会直接影响模型分数。4. Django后端集成与核心功能实现4.1 Django项目开发环境搭建模型训练好之后回到Django项目这边。准备工作包括安装Django、pymysql让Django连接MySQL用、django-cors-headers如果前后端分离的话需要以及将模型推理代码封装成Python函数。这里有个重要的坑模型加载非常耗时尤其是首次加载要吃掉几百MB内存和几秒钟时间。所以千万不要在每次HTTP请求的处理函数里重复加载模型应该在Django应用启动时加载一次把模型对象存在全局变量里之后每个请求都复用这个模型实例。实现方式可以在detection/apps.py里重写ready方法from django.apps import AppConfig from ultralytics import YOLO class DetectionConfig(AppConfig): default_auto_field django.db.models.BigAutoField name detection def ready(self): # 应用启动时加载模型全局只需加载一次 self.model YOLO(detection/yolo/best.pt)settings.py里还要配置MySQL数据库连接DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: garbage_detection, USER: root, PASSWORD: your_password, HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, }, } }注意字符集一定要用utf8mb4因为检测结果里可能有中文类别名utf8mb4才能完整支持。在MySQL里创建数据库时也要指定utf8mb4否则存中文会乱码CREATE DATABASE garbage_detection DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;4.2 模型推理接口与图片上传实现核心的检测流程是前端上传图片到Django服务器服务器保存图片到media/uploads目录然后调用模型推理获取检测结果返回给前端。这里的关键在于图片处理和结果格式化。YOLOv8的predict方法直接接收文件路径或numpy数组返回的results对象里包含了boxes、names等属性。我写这段处理代码的时候踩过一个坑从结果对象里提取类别名和坐标时坐标是归一化后的tensor格式直接返回给前端不友好。需要先判断是CPU还是GPU上的tensor然后转成numpy再转成列表。完整代码如下import numpy as np from django.shortcuts import render from .models import DetectionRecord from django.conf import settings from django.utils import timezone def detect_view(request): if request.method POST: # 获取上传图片 image request.FILES.get(image) if not image: return render(request, index.html, {error: 请上传图片}) # 保存图片到media目录 upload_path settings.MEDIA_ROOT / uploads / image.name with open(upload_path, wb) as f: for chunk in image.chunks(): f.write(chunk) # 调用全局模型进行推理 model request.model # 通过自定义中间件或全局变量获取模型 results model.predict( sourcestr(upload_path), conf0.35, iou0.45, verboseFalse ) boxes results[0].boxes # 提取检测结果 detections [] if boxes is not None: # 先判断tensor所在设备再转为numpy xyxy boxes.xyxy.cpu().numpy() if boxes.xyxy.is_cuda else boxes.xyxy.numpy() conf boxes.conf.cpu().numpy() if boxes.conf.is_cuda else boxes.conf.numpy() cls boxes.cls.cpu().numpy() if boxes.cls.is_cuda else boxes.cls.numpy() class_names results[0].names for i in range(len(cls)): detections.append({ class: class_names[int(cls[i])], confidence: float(conf[i]), bbox: [float(x) for x in xyxy[i]] }) # 保存检测记录 record DetectionRecord( userrequest.user if request.user.is_authenticated else None, image_pathuploads/ image.name, result_jsonjson.dumps(detections, ensure_asciiFalse), num_garbagelen(detections), created_timetimezone.now() ) record.save() return render(request, result.html, { detections: detections, image_path: /media/ image.name, count: len(detections) }) return render(request, index.html)注意conf参数表示置信度阈值我一般设0.35到0.4之间。阈值设太低模型会把很多背景误判成垃圾阈值太高小目标又容易漏检。这个值需要根据你的验证集结果来调没有固定的最优值。4.3 检测记录查询与前端数据展示历史记录页需要从数据库把检测记录拉出来按时间倒序排列并且支持删除操作。这里用Django自带的ListView泛型视图就能搞定不需要自己写分页逻辑。记录查询的代码放在views.py里from django.views.generic import ListView class RecordListView(ListView): model DetectionRecord template_name records.html context_object_name records paginate_by 10 ordering [-created_time]前端展示的时候records对象里每个实例都有image_path、num_garbage、created_time这几个属性。如果要看检测结果详情再通过result_json字段把JSON解析出来渲染到表格里。这里有个细节result_json字段在MySQL里存的是JSON文本拿到前端模板时别忘了加safe过滤器或者在后端用json.loads先解析成Python对象。否则模板渲染出来的是一串转义后的字符串看起来很不友好。4.4 模型权重文件管理与部署注意把best.pt放哪、怎么引用这里面也有讲究。我第一次做的时候直接把权重文件放在项目根目录代码里写相对路径结果换台电脑跑就找不到文件了。正确的做法是把权重文件放到一个固定的目录比如detection/yolo/best.pt然后在settings.py里配置一个变量MODEL_PATH BASE_DIR / detection / yolo / best.pt这样不管项目往哪个机器迁移只要目录结构不变模型路径就不会出问题。另外如果系统需要部署到服务器上还要注意media目录的权限问题确保Django进程有写权限否则用户上传图片会报500错误。5. 常见问题与排查技巧实录这套系统我前前后后帮好几个同学调试过遇到的问题五花八门但核心集中在几个地方。我把高频问题和排查思路整理成一张速查表方便你照着排查。现象可能原因解决方法Django无法连接MySQL报错Cant connect数据库没启动或账号没有远程权限启动MySQL服务用root账号从127.0.0.1连接测试上传图片后页面报错media目录不存在或权限不足手动创建media/uploads目录给写权限模型加载时报CUDA显存不足模型太大或显存不够换用yolov8s模型或者改成cuda:0显存校验检测结果中文字段乱码MySQL的字符集不是utf8mb4重建数据库并指定utf8mb4字符集首次上传图片非常慢模型加载放在了请求处理函数里把模型加载移到AppConfig.ready()中检测框位置和实际不符图片上传时被压缩或改变尺寸上传时保留原图尺寸或统一resize到模型输入尺寸历史记录分页失效模板里没有处理分页对象在模板中添加对page_obj的处理除了表格里的问题还有几个隐藏比较深的坑想单独拿出来说。第一个是Django的DEBUG模式。开发时DEBUGTrue能看到详细报错但部署到正式环境不关DEBUG会因为静态文件服务问题导致页面样式丢失。这个问题不难但要记着关DEBUG。第二个是模型推理时的线程安全问题。如果你用gunicorn等工具启动多进程Django服务每个进程都会执行一次AppConfig.ready()也就是每个进程都会加载一遍模型内存占用会翻倍。毕设阶段用Django自带的开发服务器没问题但如果你要部署演示建议把进程数设为1或者接受内存占用增大的现实。第三个是上传文件的安全问题。虽然这系统只是毕设但基础的校验还是要做。上传的图片后缀最好限制在png、jpg、jpeg、bmp文件大小限制在10MB以内既防止有人传大文件拖垮服务也防止混入非图片文件导致模型报错。关于优化性能我实测下来瓶颈不在模型推理而在图片上传和页面渲染。一个5MB的图片上传到服务器加上模型推理整个请求响应大约需要1到3秒。如果想让体验更好可以前端压缩图片后再上传或者用AJAX异步提交在等待结果时显示loading动画。这一步不算难但能明显提升答辩演示的观感。6. 写在最后一点个人经验这套系统我前后带过三轮毕设每一轮都有不同的理解。第一轮觉得难点在模型训练YOLO的配置和调参让人头大第二轮觉得难点在Django和模型集成的边界模型加载时机、线程安全、对象传递都是暗坑第三轮才发现最难的是把整个系统的逻辑讲清楚从“一个问题”到“一条完整方案”的闭环。如果让我给正在做这个题目的同学一个建议我会说别把时间全部花在调模型精度上训练出一个mAP在0.85左右的模型已经足够毕业答辩了剩下的时间多花在数据库设计和Web交互上。因为你论文里真正能写清楚、答辩时能被追问住的部分往往是系统设计、数据库表结构、功能模块的关联性。模型可以调参刷高但系统设计是实打实的工程能力。最后分享一个小技巧。把系统部署到本地之后可以先用自己的手机拍几张真实的路面照片做检测演示不要全用测试集里的图片。真实拍摄的图片往往光照、角度、背景都更复杂如果模型能在你手机拍的图上还能检出垃圾答辩现场效果会非常加分。这个方法我让学弟试过老师说“这是完整考虑了实际应用场景的毕设”当场就把分打满了。本文还有配套的精品资源点击获取