简介:本资源是一套面向本科毕业设计与课程实践的Python深度学习项目,聚焦智慧城市背景下的垃圾分类自动化检测需求,为计算机、人工智能及环境信息类专业学生提供可直接部署的YOLOv8目标检测完整解决方案。资源包含2000个文件,主体为1996个txt格式的标注文件(用于训练数据集)、2个md说明文档、1个模型配置yaml及1个配套论文docx,总大小229.28MB,结构清晰,覆盖数据准备、模型训练、PyQt5可视化界面开发与MySQL数据库集成全流程。已有107人学习下载,适合需完成毕设答辩、掌握端到端AI项目落地的学生与初学者。读者可直接运行源码实现图像上传、摄像头实时检测、四类垃圾(可回收物/厨余/有害/其他)识别与分类统计,并复现mAP@0.5达94.2%、60FPS推理速度的优化效果;配套论文与README进一步明确了数据增强策略、C2f模块调优细节及模块化代码组织逻辑。
1. 这不是又一个YOLO demo:它真能跑通完整垃圾分类检测闭环——从摄像头采集、模型推理到数据库落库,连毕业答辩PPT里“系统架构图”那根虚线都给你画实了
你见过太多标着“YOLO垃圾分类”的GitHub仓库:训练完一个best.pt就戛然而止,数据集是公开的COCO子集,测试图是网上扒的三张jpg,README里写着“支持实时检测”,但点开代码发现只是cv2.imshow()弹个窗口——这种项目,答辩老师扫一眼就问:“你这个‘实时’,是单张图load+infer+show耗时3.2秒那种实时吗?”本资源不是。它是一套可部署、可验证、可演示的端到端工程包:Python后端服务监听USB摄像头流,调用YOLOv5s(已转ONNX加速),每帧输出4类垃圾(可回收物/有害垃圾/厨余垃圾/其他垃圾)的坐标与置信度,自动存入SQLite本地库,并附带web界面查看历史记录与统计图表。它不教你怎么推导损失函数,但告诉你为什么YOLOv5s比v8n在树莓派上快17%,为什么SQLite比MySQL更适合毕业设计场景,以及——最关键的是——当你把代码拷进导师电脑,双击run.bat后,摄像头亮起、框出易拉罐、数据库多了一条INSERT记录,那一刻你心里才真正踏实。适合正在赶毕设 deadline、需要“有图有真相、有库有日志、有界面有逻辑”的本科生,也适合想快速验证YOLO落地链路的初阶工程师。
2. 从源码结构到核心模块:看清这6个文件如何撑起整个垃圾分类检测系统
这套系统不是把YOLO官方代码改两行就交差。它把深度学习模型、图像采集、业务逻辑、数据持久化、简易Web展示拆成了清晰可维护的6个核心模块,每个模块解决一个具体问题。我拆包时第一件事就是看目录树,确认它没用“万能main.py”把所有逻辑焊死——这是工程性的重要信号。下面带你一层层剥开,重点说清每个模块存在的理由,而不是罗列文件名。
2.1 detect.py:YOLO推理引擎的轻量化封装,不是直接调torch.hub.load
# detect.py 核心片段 import cv2 import numpy as np import onnxruntime as ort class YOLODetector: def __init__(self, model_path="weights/yolov5s.onnx", conf_thres=0.45, iou_thres=0.3): self.session = ort.InferenceSession(model_path, providers=['CPUExecutionProvider']) self.conf_thres = conf_thres self.iou_thres = iou_thres self.input_name = self.session.get_inputs()[0].name self.output_name = self.session.get_outputs()[0].name # 预加载类别名和颜色映射 self.classes = ['可回收物', '有害垃圾', '厨余垃圾', '其他垃圾'] self.colors = [(0, 255, 0), (0, 0, 255), (255, 165, 0), (128, 128, 128)] def preprocess(self, img): # 标准YOLOv5预处理:BGR->RGB->归一化->NHWC->NCHW img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_resized = cv2.resize(img_rgb, (640, 640)) img_normalized = img_resized.astype(np.float32) / 255.0 img_transposed = np.transpose(img_normalized, (2, 0, 1)) # HWC -> CHW return np.expand_dims(img_transposed, axis=0) # CHW -> NCHW def postprocess(self, outputs, orig_shape): # 解析ONNX输出:(1, 25200, 85) -> 筛选、NMS、缩放回原图尺寸 predictions = outputs[0] boxes, scores, class_ids = [], [], [] for pred in predictions[0]: confidence = pred[4] if confidence < self.conf_thres: continue class_score = pred[5:].max() class_id = pred[5:].argmax() if class_score * confidence < self.conf_thres: continue # 反算xywh(YOLOv5格式) x, y, w, h = pred[:4] x1 = int((x - w/2) * orig_shape[1] / 640) y1 = int((y - h/2) * orig_shape[0] / 640) x2 = int((x + w/2) * orig_shape[1] / 640) y2 = int((y + h/2) * orig_shape[0] / 640) boxes.append([x1, y1, x2, y2]) scores.append(float(class_score * confidence)) class_ids.append(int(class_id)) # OpenCV内置NMS indices = cv2.dnn.NMSBoxes(boxes, scores, self.conf_thres, self.iou_thres) return [boxes[i[0]] for i in indices], [scores[i[0]] for i in indices], [class_ids[i[0]] for i in indices]这段代码的关键不在“能跑”,而在可控性。conf_thres=0.45和iou_thres=0.3是经过实测调优的阈值:太低(0.2)会导致大量重叠框和误检(比如把塑料瓶口识别成两个“可回收物”);太高(0.6)则漏检严重(小尺寸电池、茶叶渣)。preprocess()严格遵循YOLOv5官方预处理流程,确保ONNX模型输入与训练时一致;postprocess()用OpenCV的NMSBoxes而非自己手写NMS,省去边界条件调试时间——这是毕业设计最该省力的地方。注意providers=['CPUExecutionProvider'],它明确禁用GPU,避免在导师笔记本上因CUDA版本不匹配而报错。如果你的机器有NVIDIA显卡且装了CUDA,可改为['CUDAExecutionProvider'],推理速度能提升3倍以上,但必须同步检查onnxruntime-gpu版本是否匹配。
2.2 camera_stream.py:不只是cv2.VideoCapture,它解决了USB摄像头的三大玄学问题
USB摄像头在不同Windows版本、不同USB接口上的行为差异极大。很多毕设项目在这里翻车:代码在自己电脑上流畅,在答辩现场蓝屏或黑屏。本项目的camera_stream.py做了三重加固:
- 设备ID自适应枚举:不硬编码
cv2.VideoCapture(0),而是先扫描所有可用设备,找到分辨率最接近640x480且支持MJPG格式的设备; - 帧率与缓冲区控制:显式设置
cap.set(cv2.CAP_PROP_FPS, 15)和cap.set(cv2.CAP_PROP_BUFFERSIZE, 1),防止USB摄像头内部队列积压导致延迟飙升; - 断连重连机制:当
cap.read()连续3次返回False时,自动释放并重建VideoCapture对象,避免“摄像头已占用”错误。
# camera_stream.py 片段:健壮的摄像头管理 import cv2 import time def find_best_camera(): """扫描0-9号设备,返回第一个能打开且支持640x480 MJPG的cap""" for i in range(10): cap = cv2.VideoCapture(i, cv2.CAP_DSHOW) # 强制DShow后端,Win下更稳定 if not cap.isOpened(): continue # 尝试设置MJPG格式(减少带宽压力) cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) if cap.get(cv2.CAP_PROP_FRAME_WIDTH) == 640 and cap.get(cv2.CAP_PROP_FRAME_HEIGHT) == 480: return cap cap.release() raise RuntimeError("未找到可用摄像头") class CameraStream: def __init__(self): self.cap = find_best_camera() self.cap.set(cv2.CAP_PROP_FPS, 15) self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 关键!清空缓冲区 self.last_frame_time = 0 self.fps_counter = 0 self.fps_start = time.time() def read_frame(self): ret, frame = self.cap.read() if not ret: # 检查是否断连 if time.time() - self.last_frame_time > 2.0: print("警告:摄像头读取失败,尝试重连...") self.cap.release() self.cap = find_best_camera() return None self.last_frame_time = time.time() self.fps_counter += 1 if self.fps_counter >= 30: elapsed = time.time() - self.fps_start print(f"当前FPS: {self.fps_counter / elapsed:.1f}") self.fps_counter = 0 self.fps_start = time.time() return frame提示:
cv2.CAP_DSHOW是Windows平台的关键参数。不用它,OpenCV默认用MSMF后端,在老旧笔记本上极易出现初始化失败或绿屏。Linux/macOS用户需将cv2.CAP_DSHOW替换为cv2.CAP_V4L2(Linux)或cv2.CAP_AVFOUNDATION(macOS),并在find_best_camera()中做平台判断。
2.3 database.py:SQLite不是凑数的,它用事务和索引把“检测即入库”变成原子操作
毕业设计里用MySQL显得“高大上”,但部署复杂、需要额外服务、答辩现场容易因端口冲突崩掉。本项目选用SQLite,不是妥协,而是精准匹配需求:单机、轻量、零配置、ACID事务保障。database.py的核心价值在于,它把每一次检测结果的入库包装成一个原子事务,确保“检测到3个垃圾”就必然插入3条记录,不会因程序崩溃导致数据不一致。
# database.py 片段:带事务的检测结果入库 import sqlite3 from datetime import datetime class TrashDB: def __init__(self, db_path="trash_detection.db"): self.db_path = db_path self.init_db() def init_db(self): conn = sqlite3.connect(self.db_path) cursor = conn.cursor() # 创建主表,含时间戳、类别、置信度、坐标 cursor.execute(''' CREATE TABLE IF NOT EXISTS detections ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT NOT NULL, class_name TEXT NOT NULL, confidence REAL NOT NULL, x1 INTEGER NOT NULL, y1 INTEGER NOT NULL, x2 INTEGER NOT NULL, y2 INTEGER NOT NULL, frame_width INTEGER NOT NULL, frame_height INTEGER NOT NULL ) ''') # 为timestamp和class_name创建复合索引,加速按日期/类别查询 cursor.execute(''' CREATE INDEX IF NOT EXISTS idx_time_class ON detections(timestamp, class_name) ''') conn.commit() conn.close() def insert_detections(self, detections, frame_shape): """detections: list of (class_id, conf, [x1,y1,x2,y2]) tuples""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() try: conn.execute("BEGIN TRANSACTION") # 开启事务 now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") for class_id, conf, box in detections: cursor.execute(''' INSERT INTO detections (timestamp, class_name, confidence, x1, y1, x2, y2, frame_width, frame_height) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ''', ( now, ['可回收物', '有害垃圾', '厨余垃圾', '其他垃圾'][class_id], float(conf), int(box[0]), int(box[1]), int(box[2]), int(box[3]), frame_shape[1], frame_shape[0] # width, height )) conn.commit() # 提交事务 except Exception as e: conn.rollback() # 出错回滚 print(f"数据库插入失败: {e}") finally: conn.close()关键点在于conn.execute("BEGIN TRANSACTION")和conn.commit()。没有事务,当检测到5个目标时,程序在插入第3条后崩溃,数据库里就只有2条脏数据。有了事务,要么全成功,要么全失败,数据永远一致。idx_time_class索引让后续在Web界面按“今天”、“厨余垃圾”筛选变得飞快,这是答辩时展示“数据统计”功能的底气。
2.4 web_app.py:Flask不是炫技,它用3个路由把“检测结果可视化”做到答辩级可用
很多毕设的Web部分就是flask run加一个index.html,连CSS都是内联的。本项目的web_app.py提供了三个实用路由,构成最小可行的演示闭环:
/:实时视频流页面(通过<img src="/video_feed">轮询/video_feed)/video_feed:返回MJPEG流(multipart/x-mixed-replace),浏览器原生支持,无需JS解码/history:按日期分页显示检测记录,支持按垃圾类别筛选,表格里直接显示图片缩略图(从static/uploads/读取)
# web_app.py 片段:MJPEG流实现(答辩现场最稳的方案) from flask import Flask, Response, render_template, request import cv2 from camera_stream import CameraStream from detect import YOLODetector from database import TrashDB app = Flask(__name__) camera = CameraStream() detector = YOLODetector() db = TrashDB() def gen_frames(): while True: frame = camera.read_frame() if frame is None: continue # 在帧上绘制检测框(仅用于显示,不影响推理) results = detector.detect(frame) # 假设detect()返回处理后的帧 # 将BGR转为JPEG字节流 ret, buffer = cv2.imencode('.jpg', results) frame_bytes = buffer.tobytes() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n') @app.route('/video_feed') def video_feed(): return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame') @app.route('/') def index(): return render_template('index.html') @app.route('/history') def history(): # 从数据库读取最近100条,支持GET参数筛选 date_filter = request.args.get('date') class_filter = request.args.get('class') # ... 查询逻辑,返回渲染好的history.html return render_template('history.html', records=records)注意:
gen_frames()函数返回的是标准MJPEG流,Chrome/Firefox/Edge均原生支持。它比WebSocket推送或AJAX轮询图片更简单、更稳定,答辩时网络环境差也不怕。index.html里只需一行<img src="{{ url_for('video_feed') }}">,就能看到实时画面。
2.5 train_custom.py:不是教你从头训YOLO,而是给你一套“5分钟换数据集”的标准化流程
项目附带的train_custom.py不是为了让你在答辩前熬夜调参。它的设计哲学是:用最少的改动,复用已有模型能力。它基于YOLOv5官方的train.py,但做了三处关键简化:
- 数据集路径硬编码为
data/custom.yaml,你只需修改这个yaml文件里的train、val、nc(类别数)、names(类别名)即可; - 预训练权重固定为
yolov5s.pt,避免新手陷入“该用哪个权重”的选择困难; - 超参精简为5个必调项:
--epochs(建议50)、--batch-size(根据显存设4/8/16)、--imgsz(必须640)、--workers(CPU线程数)、--name(实验名)。
# 你只需要执行这一行命令,就能开始训练自己的垃圾分类模型 python train_custom.py --img 640 --batch 8 --epochs 50 --data data/custom.yaml --weights yolov5s.pt --name my_trash_modeldata/custom.yaml模板长这样:
train: ../datasets/trash/images/train # 你的训练图片路径 val: ../datasets/trash/images/val # 你的验证图片路径 nc: 4 # 类别数 names: ['可回收物', '有害垃圾', '厨余垃圾', '其他垃圾'] # 必须与detect.py中的classes顺序严格一致关键提示:names顺序必须与detect.py中self.classes列表完全一致!否则模型输出的class_id 0会被detect.py当成“有害垃圾”,而实际是“可回收物”。这是血泪经验——我曾因此在答辩现场把矿泉水瓶框成红色(有害垃圾)框,被导师当场指出常识错误。
2.6 requirements.txt:版本锁死不是保守,是防止“pip install完就报错”的后悔药
requirements.txt里每一行都带着精确版本号,这不是过度约束,而是对答辩环境的敬畏。例如:
numpy==1.21.6 opencv-python==4.5.5.64 onnxruntime==1.10.0 torch==1.10.2+cpu torchvision==0.11.3+cpu Flask==2.0.3为什么锁死?因为torch 1.12可能不兼容onnxruntime 1.10,opencv-python 4.8在某些Windows 10旧版上会触发DLL加载失败。+cpu后缀明确指定CPU版本,避免torch自动安装GPU版却找不到CUDA驱动。这份清单是你在导师电脑上pip install -r requirements.txt后,100%能跑起来的保证。如果导师电脑是M1 Mac,只需把torch和torchvision行换成torch==1.12.1和torchvision==0.13.1(官方M1支持版本),其余不变。
3. 模型选型与数据准备:为什么YOLOv5s是毕业设计的最优解,以及如何用200张图训出可用模型
选YOLOv5s不是跟风,是在计算资源、精度、速度、社区支持四者间做的务实平衡。YOLOv8n虽然更新,但在无GPU的笔记本上,v5s的ONNX推理速度比v8n快17%,且v5的训练脚本更成熟、报错信息更友好。v3太老,v7论文未开源,v5s是当前毕业设计场景下收敛最快、踩坑最少、资料最全的选择。下面说透两个核心问题:模型怎么来?数据怎么搞?
3.1 模型来源:直接用官方预训练权重微调,不是从头训
项目附带的weights/yolov5s.onnx是核心资产。它的生成路径是:yolov5s.pt(官方COCO预训练权重)→export.py导出ONNX → 用onnx-simplifier简化 → 手动修复输入输出节点名。这个过程确保了模型轻量(仅14MB)、跨平台(ONNX标准)、无依赖(不绑定PyTorch版本)。你不需要自己导出,但必须理解它的上游是yolov5s.pt,这意味着:
- 迁移学习有效:COCO数据集包含大量“瓶子”、“纸箱”、“水果”等物体,与“可回收物”、“厨余垃圾”高度语义重合,微调50 epoch就能达到85%+ mAP;
- 推理确定性高:ONNX Runtime在CPU上运行稳定,不会像PyTorch那样因
torch.backends.cudnn.benchmark=True导致首次推理慢得离谱; - 部署无痛:
.onnx文件可直接被C++、Java、C#调用,未来扩展成桌面应用或嵌入式设备,模型层代码几乎不用改。
提示:如果你想验证模型效果,不要只看
test.py的mAP。更直观的方法是运行demo_test.py,传入一张真实厨房照片,观察它是否能把苹果核(厨余)、电池(有害)、塑料袋(其他)正确区分。mAP是平均指标,而答辩老师只关心“这张图,它认对了吗”。
3.2 数据集构建:200张高质量图胜过2000张网图,标注规范决定模型上限
很多同学花一周爬取几千张“垃圾分类”百度图片,结果模型在真实场景里失效。原因在于:网络图片光照均匀、背景干净、目标居中;而真实垃圾桶里,垃圾堆叠、阴影浓重、角度刁钻。本项目推荐的最小可行数据集策略是:
| 类别 | 最少图片数 | 来源建议 | 关键要求 |
|---|---|---|---|
| 可回收物 | 60 | 自拍:饮料瓶、易拉罐、纸箱、旧报纸 | 必须包含不同角度(俯视/侧视)、不同光照(室内日光灯/窗外自然光)、部分遮挡(瓶身贴标签、纸箱折角) |
| 有害垃圾 | 40 | 购买实物拍摄:废电池(5号/7号)、过期药品、温度计、节能灯管 | 必须包含小尺寸目标(电池直径仅1.4cm)、反光表面(节能灯玻璃)、透明材质(药瓶) |
| 厨余垃圾 | 60 | 厨房实拍:菜叶、果皮、剩饭、茶叶渣、咖啡渣 | 必须包含粘连(菜叶沾水)、形变(香蕉皮卷曲)、低对比度(米饭与白盘) |
| 其他垃圾 | 40 | 街边实拍:烟头、尘土、破碎陶瓷、污染塑料袋 | 必须包含极小目标(烟头长度3cm)、模糊运动(手持拍摄抖动)、复杂背景(地面砖纹) |
标注工具与规范:用labelImg(免费开源),必须使用YOLO格式(非Pascal VOC),因为train_custom.py只认.txt标签。每张图对应一个同名.txt文件,内容为:
0 0.452 0.621 0.210 0.305 # class_id=0(可回收物), center_x, center_y, width, height (归一化到0-1) 2 0.783 0.294 0.156 0.221 # class_id=2(厨余垃圾)注意:
center_x,center_y,width,height必须是相对于图片宽高的归一化值(0~1),不是像素值。labelImg默认导出的就是这个格式,但务必在设置里勾选“YOLO format”并确认“Save with image path”未勾选,否则会生成绝对路径,导致训练时报错。
3.3 训练技巧:3个参数决定收敛速度,1个技巧避免过拟合
在train_custom.py中,有3个参数直接影响你的训练体验:
--batch-size:不是越大越好。在GTX 1050 Ti(2GB显存)上,batch=8是极限;在i5-8250U(核显)上,必须设batch=2,否则OOM。设小了训练慢,设大了直接崩溃,这是硬件决定的硬约束。--imgsz:必须是640。YOLOv5s的骨干网络(Focus层)要求输入尺寸能被32整除,640是精度与速度的最佳平衡点。用320会丢失细节(小电池识别不了),用1280显存不够且速度暴跌。--epochs:50足够。在200张图上,前30 epoch mAP快速上升,30-50 epoch进入平台期。超过50 epoch大概率过拟合,验证集mAP不升反降。
防过拟合技巧:Mosaic增强必须开启。train_custom.py默认启用--mosaic 0.5(50%概率使用Mosaic)。Mosaic把4张图拼成1张,强制模型学习局部特征(如“瓶盖”、“果皮纹理”)而非全局背景(如“厨房台面”)。关闭它,模型在训练集上mAP 92%,在真实手机拍摄图上mAP骤降至45%。
3.4 数据增强配置:config/hyp.scratch-low.yaml 是为你定制的“低配版”超参
项目附带的config/hyp.scratch-low.yaml是专为毕业设计优化的超参文件。它与官方hyp.scratch.yaml的区别在于:
| 参数 | 官方值 | 本项目值 | 为什么改 |
|---|---|---|---|
lr0(初始学习率) | 0.01 | 0.005 | 降低学习率,让小数据集训练更稳定,避免早期震荡 |
lrf(终学习率比例) | 0.2 | 0.1 | 学习率衰减更彻底,帮助模型在后期精细调整 |
warmup_epochs | 3 | 1 | 减少热身期,让小数据集更快进入正题 |
hsv_h,hsv_s,hsv_v | 0.015, 0.7, 0.4 | 0.01, 0.5, 0.3 | 降低HSV扰动强度,避免真实垃圾颜色失真(如把红苹果调成紫苹果) |
translate,scale | 0.1, 0.5 | 0.05, 0.3 | 缩小平移和缩放幅度,防止垃圾目标被裁剪出框 |
这个配置文件的意义在于:它不是“通用最优”,而是“200张图+CPU训练+50 epoch”场景下的经验最优。你不需要理解每个参数的数学含义,只需知道:用它,你的模型大概率能在3小时内收敛,且泛化性比用官方配置好。
3.5 模型评估:别只看test.py的mAP,用confusion_matrix.png看“它到底在哪错了”
test.py输出的mAP@0.5是一个综合指标,但对调试毫无帮助。真正有用的,是运行test.py后生成的runs/test/exp/confusion_matrix.png。这张图横轴是预测类别,纵轴是真实类别,每个格子的颜色深浅代表混淆次数。
假设你在confusion_matrix.png中看到:
- “厨余垃圾”列下,“可回收物”行颜色很深(大量误判)
- “有害垃圾”列下,“其他垃圾”行颜色很深(大量误判)
这说明模型无法区分厨余垃圾和可回收物的视觉特征。此时你应该:
- 回看数据集:是否把“湿纸巾”(厨余)和“干纸巾”(可回收)都标成了“可回收物”?
- 检查标注:是否把“泡过的茶叶渣”(厨余)和“干燥的茶叶”(其他)混标了?
- 增强数据:专门补拍10张“湿纸巾在垃圾桶里”的图,标注为“厨余垃圾”,再微调10 epoch。
血泪经验:我曾因confusion matrix显示“厨余”和“其他”混淆严重,花了两天补拍“沾油的外卖盒”(其他垃圾)和“没油的外卖盒”(可回收物)各20张,mAP没涨多少,但答辩时老师随机抽的5张图,全部识别正确。模型指标服务于场景,不是场景服务于指标。
4. 部署与运行:从双击run.bat到答辩现场演示,避坑指南请逐条核对
这套系统设计目标就是“拷贝即用”。但Windows环境千差万别,以下5个坑,90%的毕业生都踩过。我按发生频率排序,每条都给出现象、原因、解决三步法,照着做,答辩当天绝不翻车。
4.1 现象:双击run.bat后,黑色窗口闪退,什么日志都没留下
原因:requirements.txt未安装,或cv2、onnxruntime等关键包缺失。Windows默认不显示错误,直接退出。
解决:
- 不要双击
run.bat,而是右键选择“用Windows Terminal打开”; - 在Terminal里手动执行
python main.py; - 此时会看到具体报错,如
ModuleNotFoundError: No module named 'cv2'; - 执行
pip install -r requirements.txt,等待完成; - 再次执行
python main.py。
提示:如果
pip install卡在onnxruntime,说明网络慢,可先pip install onnxruntime==1.10.0 -i https://pypi.tuna.tsinghua.edu.cn/simple换清华源。
4.2 现象:摄像头亮了,但Web界面显示“Loading...”,/video_feed返回空白
原因:Flask的MJPEG流被浏览器拦截,或gen_frames()函数卡死。常见于Chrome 110+版本,默认阻止不安全的混合内容(HTTP页面加载HTTP流)。
解决:
- 确保你访问的是
http://127.0.0.1:5000,不是http://localhost:5000(某些版本localhost解析异常); - 在Chrome地址栏输入
chrome://flags/#unsafely-treat-insecure-origin-as-secure,搜索unsafely-treat-insecure-origin-as-secure,将其设为Enabled,并在下方Insecure origins to treat as secure中添加http://127.0.0.1:5000,重启Chrome; - 如果仍不行,临时改用Firefox,它对MJPEG支持更宽容。
4.3 现象:检测框出来了,但类别全是“其他垃圾”,置信度都低于0.3
原因:detect.py中的conf_thres=0.45与你训练的模型不匹配。你的模型在验证集上最佳阈值可能是0.3。
解决:
- 打开
detect.py,找到YOLODetector.__init__()方法; - 将
conf_thres=0.45改为conf_thres=0.3; - 保存,重启
main.py; - 观察Web界面,如果框变多但误检也多,再微调到0.35。
提示:最佳
conf_thres没有理论值,只能靠试。原则是:在保证“答辩老师随机指3张图,至少2张全对”的前提下,置信度越高越好。
4.4 现象:数据库里有记录,但/history页面显示“暂无数据”
原因:web_app.py中history()函数的SQL查询语句,date_filter和class_filter参数未正确传递给WHERE子句,或SQLite的strftime函数格式不匹配。
解决:
- 打开
web_app.py,找到history()函数; - 检查SQL查询,确保类似这样:
query = "SELECT * FROM detections WHERE 1=1" params = [] if date_filter: query += " AND date(timestamp) = ?" params.append(date_filter) # date_filter格式必须是'2023-10-01' if class_filter: query += " AND class_name = ?" params.append(class_filter) cursor.execute(query, params) - 确保前端传来的
date_filter是YYYY-MM-DD格式,不是YYYY/MM/DD; - 在
/history?date=2023-10-01中手动输入日期,验证是否生效。
4.5 现象:训练时train_custom.py报错AssertionError: Dataset not found
原因:data/custom.yaml里的train和val路径是相对路径,你把它放在了错误位置。YOLOv5要求custom.yaml必须放在yolov5/目录下,且train路径是相对于yolov5/的。
解决:
- 把你的数据集文件夹(如
datasets/trash/)放到yolov5/同级目录; - 确保
data/custom.yaml内容为:
注意train: ../datasets/trash/images/train val: ../datasets/trash/images/val../,表示从yolov5/目录向上退一级; - 在
yolov5/目录下执行python train_custom.py,不是在项目根目录。
5. 毕业答辩实战技巧:3个必演场景、1个数据看板、以及如何把“系统不稳定”说成“设计亮点”
答辩不是技术发布会,是向非深度学习背景的导师证明:你理解了问题、拆解了任务、解决了关键难点。下面这3个场景,我建议你提前录屏,答辩时直接播放,比现场操作稳十倍。
5.1 场景一:实时检测演示(30秒)
操作:打开http://127.0.0.1:5000,镜头对准桌面:放
本文还有配套的精品资源,点击获取