ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于Django与YOLOv5的交通标志识别系统:从环境搭建到特殊天气检测

基于Django与YOLOv5的交通标志识别系统:从环境搭建到特殊天气检测 简介这份资源是面向高校学生与Python开发者的毕业设计/课程设计完整项目包主题为基于深度学习的交通标志识别系统。项目采用YOLOv5完成模型训练前端界面使用Python编写后端基于Django框架数据库为MySQL 5.7整体代码结构简洁、界面美观适合作为毕业设计或课程设计参考。功能上支持实景图片检测、笔记本摄像头实时检测并能在小窗口显示交通标志类型同时针对低像素模糊、远距离、雾霾、雨天、黑夜等特殊场景做了检测适配检测结果可保存另存。资源包共570个文件包含47个py源码、62个js脚本、31个css样式、151个gif与107个png界面素材、2个pth模型权重及sql数据库文件等压缩包约578.97MB目录清晰便于二次开发。目前已有66人学习下载可帮助读者快速获取完整前后端方案、模型训练思路与界面实现参考。1. 从一张雾天路牌说起这套 Django YOLOv5 交通标志识别源码到底能跑出什么去年帮一个学弟看毕设他发来一张自己拍的图傍晚六点半路灯还没完全亮前车尾灯糊成一片路边一块限速 40 的圆牌在画面里只占几十个像素边缘还带着雨滴反光。他问我这种图丢进模型里能不能认出来。这个问题其实正好戳中交通标志识别最真实的痛点——不是实验室里那种裁剪得干干净净、正对镜头的标准图而是实景、低像素、远距离、雾霾、雨天、黑夜这些非理想条件。这套基于深度学习的交通标志识别系统源码就是围绕这个场景做的前端 Django 页面负责上传图片、调摄像头、展示分类结果后端用 YOLOv5 做检测和分类MySQL 存检测记录检测后的图像支持另存。它适合正在做 python 毕业设计、课程设计的人也适合想找一个前后端 模型 数据库完整闭环练手的开发者。整套东西不追求算法上的花活追求的是能跑通、能演示、能讲清楚。2. 环境与依赖Python 3.6.8 MySQL 5.7 这套老组合怎么装才不翻车这套源码的环境说明写得很明确Python 3.6.8、MySQL 5.7、Navicat11、PyCharm。看到 Python 3.6.8 这个版本号熟手心里应该有数了——这是个偏老的版本很多新库的默认安装会直接报错。所以第一步不是急着 pip install而是先把版本对齐。2.1 为什么锁定 Python 3.6.8 而不是直接上 3.10YOLOv5 早期版本对 Python 版本比较敏感torch 的某些版本在 3.6 上编译好的 wheel 更全尤其在 Windows 上。如果你用 3.10 去装老版本 torch很可能遇到找不到对应 wheel、只能源码编译的情况编译又要 Visual Studio Build Tools一圈下来半天没了。常见做法是直接用 conda 建一个 3.6.8 的独立环境和系统 Python 隔离避免污染。# 创建独立环境避免和系统 Python 冲突 conda create -n traffic_sign python3.6.8 conda activate traffic_sign # 验证版本必须是 3.6.8 python --version逻辑说明conda create -n的-n后面跟环境名这里叫 traffic_sign方便识别。参数python3.6.8强制指定小版本conda 会去拉对应的解释器。激活后python --version是唯一可信的验证方式别信 IDE 里显示的IDE 经常记着旧配置。2.2 依赖安装顺序先 torch 再 requirements很多人拿到源码直接pip install -r requirements.txt然后卡在 torch 上。正确顺序是先单独装 torch 和 torchvision再装其余依赖。因为 requirements 里如果写了 torch 但没锁版本pip 会去拉最新版最新版早就不支持 3.6 了。# 先装 torch指定支持 py3.6 的版本 pip install torch1.7.1 torchvision0.8.2 -f https://download.pytorch.org/whl/torch_stable.html # 再装项目其余依赖 pip install -r requirements.txt # Django 单独确认一下版本 pip show django逻辑说明-f参数指定 wheel 的下载源torch_stable.html是官方维护的历史版本索引页能保证 1.7.1 这个版本在 py3.6 下有对应 wheel。pip show django用来确认 Django 版本这套源码一般配 Django 2.x 或 3.0如果装成了 4.x很多老写法会直接报ImportError。2.3 MySQL 5.7 建库与 Django 连接配置数据库这块MySQL 5.7 的安装本身不难坑在于字符集和 Django 的连接驱动。建库时字符集一定要用 utf8mb4否则存中文路径或备注会乱码。-- 建库字符集用 utf8mb4 CREATE DATABASE traffic_sign_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 建一个专用账号别用 root 跑应用 CREATE USER ts_userlocalhost IDENTIFIED BY your_password; GRANT ALL PRIVILEGES ON traffic_sign_db.* TO ts_userlocalhost; FLUSH PRIVILEGES;逻辑说明utf8mb4比utf8多支持 emoji 和部分生僻字虽然交通标志场景用不上 emoji但养成习惯没坏处。单独建账号是为了权限隔离GRANT只给这一个库的权限FLUSH PRIVILEGES让权限立即生效。Django 的settings.py里数据库配置对应改成DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: traffic_sign_db, USER: ts_user, PASSWORD: your_password, HOST: 127.0.0.1, PORT: 3306, OPTIONS: {charset: utf8mb4}, } }参数说明ENGINE固定用 mysql 后端OPTIONS里的 charset 要和建库时一致否则连接层和存储层字符集不匹配中文会变成问号。改完执行python manage.py migrate生成表结构这一步报错八成是驱动没装pip install mysqlclient即可Windows 上如果编译失败换pymysql并在__init__.py里打补丁。3. YOLOv5 训练与推理从数据集标注到小窗口显示分类结果模型这块是整套系统的核心。摘要里说得很清楚模型只需要用 YOLOv5 训练系统界面用 Python 写。所以这一章的重点是数据怎么准备、模型怎么训、训完怎么在 Django 里调起来并把结果画到小窗口上。3.1 数据集准备与 YOLO 格式标注交通标志的公开数据集常见的有 GTSRB、TT100K 等但毕设场景下很多人会自己拍一批图补充特殊天气样本。标注工具常见用 labelImg导出 YOLO 格式每张图对应一个 txt每行是类别 中心x 中心y 宽 高坐标都是归一化到 0~1 的值。# 目录结构建议这样组织 datasets/ images/ train/ val/ labels/ train/ val/ data.yamldata.yaml内容train: datasets/images/train val: datasets/images/val nc: 4 names: [speed_limit, no_entry, warning, direction]参数说明nc是类别数这里举例 4 类实际按你的标注来。names的顺序必须和标注时类别 id 对应id 0 对应 names 里第一个错一个位置整个训练就废了。这是血泪经验标注时类别顺序一旦定了就别改。3.2 训练命令与关键参数怎么调YOLOv5 的训练入口是train.py核心参数不多但每个都影响结果。python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data datasets/data.yaml \ --weights yolov5s.pt \ --project runs/train \ --name traffic_sign_v1逻辑说明--img 640是输入分辨率交通标志在画面里往往很小分辨率太低会直接丢特征640 是平衡速度和精度的常见选择。--batch 16是批大小显存不够就降到 8 或 4。--epochs 100是训练轮数小数据集 100 轮通常够收敛看results.png里的 mAP 曲线如果还在涨就加。--weights yolov5s.pt用预训练权重做迁移学习比从零训快得多小数据集上效果也更稳。--name给这次训练起个名方便在 runs 目录里区分多次实验。训练过程中重点看三个指标mAP0.5、precision、recall。交通标志场景下 recall 比 precision 更值得关注因为漏检一个标志比误检更危险。如果 recall 偏低优先加数据、加分辨率而不是盲目调学习率。3.3 在 Django 里加载模型并推理训练完得到best.pt把它放到 Django 项目的某个目录下比如models/best.pt。推理代码封装成一个函数视图里调用。import torch import cv2 import numpy as np # 全局加载一次别每次请求都加载 model torch.hub.load(ultralytics/yolov5, custom, pathmodels/best.pt, force_reloadFalse) def detect_image(img_path): # 读取图片cv2 默认 BGR img cv2.imread(img_path) # 推理 results model(img) # 拿到检测框、类别、置信度 detections results.pandas().xyxy[0] boxes [] for _, row in detections.iterrows(): if row[confidence] 0.4: continue boxes.append({ label: row[name], conf: round(float(row[confidence]), 2), bbox: [int(row[xmin]), int(row[ymin]), int(row[xmax]), int(row[ymax])] }) return boxes逻辑说明torch.hub.load第一次会去拉 yolov5 仓库代码force_reloadFalse表示缓存后不再重复拉。模型对象放在模块级全局Django 启动时加载一次别写在视图函数里否则每个请求都重新加载慢到怀疑人生。results.pandas().xyxy[0]把结果转成 DataFramexyxy表示坐标格式是左上右下。置信度阈值 0.4 是经验值低于这个数的框大多是噪声可以按实际效果调。3.4 小窗口显示分类结果与图像另存摘要里特别提到能够在一个小窗口显示是什么交通标志这个用 OpenCV 的imshow或者在前端页面上叠加一个 div 都能做。如果走 Django 前端常见做法是把检测结果画到图上再返回给页面。def draw_and_save(img_path, boxes, save_path): img cv2.imread(img_path) for b in boxes: x1, y1, x2, y2 b[bbox] cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) # 在框上方写类别和置信度 text f{b[label]} {b[conf]} cv2.putText(img, text, (x1, y1 - 8), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imwrite(save_path, img) return save_path参数说明cv2.rectangle的线宽 2 和颜色(0,255,0)是 BGR 顺序的绿色。cv2.putText的(x1, y1-8)让文字在框上方0.6是字体缩放2是线宽。cv2.imwrite保存到指定路径这个路径可以存到 MySQL 的记录表里方便历史查询。注意 OpenCV 的imwrite对中文路径支持不好保存路径尽量用英文或数字否则会静默失败——这是典型的玄学问题图没存上还不报错。4. 摄像头实时检测与特殊天气场景从笔记本摄像头到雾天黑夜的应对摘要里第二条和第三条分别提到摄像头检测和特殊天气检测。这两块其实是同一个技术链路的不同输入源摄像头是实时流特殊天气是图像质量退化。分开讲清楚。4.1 笔记本摄像头实时检测链路摄像头检测用 OpenCV 的VideoCapture逐帧读、逐帧推理。但这里有个性能问题YOLOv5 在 CPU 上跑一帧可能要几百毫秒直接逐帧推理会卡成幻灯片。常见做法是抽帧比如每 5 帧推理一次中间帧复用上一次的结果。import cv2 import torch model torch.hub.load(ultralytics/yolov5, custom, pathmodels/best.pt, force_reloadFalse) cap cv2.VideoCapture(0) # 0 表示默认摄像头 frame_count 0 last_boxes [] while True: ret, frame cap.read() if not ret: break frame_count 1 # 每 5 帧推理一次 if frame_count % 5 0: results model(frame) last_boxes results.pandas().xyxy[0] # 用上一次结果画框 for _, row in last_boxes.iterrows(): if row[confidence] 0.4: continue cv2.rectangle(frame, (int(row[xmin]), int(row[ymin])), (int(row[xmax]), int(row[ymax])), (0, 255, 0), 2) cv2.imshow(Traffic Sign Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()逻辑说明VideoCapture(0)的 0 是摄像头索引外接摄像头可能是 1。frame_count % 5控制推理频率5 是经验值机器好可以降到 3机器差就升到 10。last_boxes缓存上一次结果保证画面上的框不会闪。cv2.waitKey(1)里的 1 是等待毫秒数配合ord(q)实现按 q 退出。这套逻辑在 Django 里要改成把帧编码成字节流返回给前端或者用 WebSocket 推但核心抽帧思路一样。4.2 特殊天气与低质量图像的应对策略雾霾、雨天、黑夜、远距离、低像素这些场景的共同点是图像对比度低、细节丢失。模型层面能做的有限更多要在预处理和数据增强上下功夫。常见做法有三条一是训练时做数据增强YOLOv5 自带 HSV 增强、马赛克增强可以额外加雾化、加噪声、调亮度二是推理前做图像增强比如 CLAHE 自适应直方图均衡化能明显改善雾天和黑夜的对比度三是针对远距离小目标提高输入分辨率或改用更大的模型yolov5m/l。import cv2 def enhance_low_quality(img): # 转 LAB 空间只对 L 通道做 CLAHE lab cv2.cvtColor(img, cv2.COLOR_BGR2LAB) l, a, b cv2.split(lab) clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8, 8)) l clahe.apply(l) lab cv2.merge((l, a, b)) return cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)参数说明clipLimit2.0控制对比度增强的强度太大噪声会被放大太小没效果2.0 是常用起点。tileGridSize(8,8)是分块大小块越小局部增强越明显但计算量也越大。转 LAB 空间是因为 L 通道是亮度单独增强亮度不会影响颜色比直接在 BGR 上做均衡化更自然。提示CLAHE 对雾天和黑夜有效但对运动模糊基本没用。运动模糊要靠提高快门速度或后期去模糊模型层面解决不了。4.3 检测结果入库与历史查询每次检测完把图片路径、检测到的类别、置信度、时间戳存进 MySQL前端就能做一个历史记录页。Django 的 ORM 写起来很直接。from django.db import models class DetectionRecord(models.Model): image_path models.CharField(max_length255) label models.CharField(max_length64) confidence models.FloatField() created_at models.DateTimeField(auto_now_addTrue) class Meta: db_table detection_record参数说明auto_now_addTrue让创建时间自动写入不用手动传。db_table指定表名不写的话 Django 会用app名_模型名的默认格式。存的时候一条检测记录一行如果一张图有多个标志就存多行查询时按image_path聚合即可。5. 避坑与排查这套源码跑不起来时先看这几条这套源码的坑大多集中在环境版本、路径、模型加载和中文处理上。下面几条是我实际遇到过、也见过别人反复踩的。5.1 现象pip install -r requirements.txt卡在 torch 下载原因requirements 里没锁 torch 版本pip 去拉最新版最新版不支持 Python 3.6于是反复重试或直接超时。解决先单独装 torch 1.7.1 和 torchvision 0.8.2用官方 wheel 索引再装其余依赖。命令见 2.2 节。5.2 现象Django 启动报No module named MySQLdb原因Django 的 mysql 后端默认用 MySQLdb也就是 mysqlclientWindows 上编译这个包需要 C 编译器很多人装不上。解决两条路。一是装 mysqlclient 的预编译 wheelpip install mysqlclient在部分版本上能直接成功二是改用 pymysql在项目__init__.py里加import pymysql pymysql.install_as_MySQLdb()这样 Django 会把 pymysql 当成 MySQLdb 用纯 Python 实现不需要编译。5.3 现象检测结果的中文类别名显示成方块原因OpenCV 的putText不支持中文字体里没有中文字形画出来就是方块或问号。解决要么类别名用英文要么用 PIL 的ImageDraw配合中文字体文件来画。毕设演示场景下类别名用英文最省事前端页面上再用中文映射表显示。5.4 现象摄像头能打开但画面全黑或卡死原因摄像头被其他程序占用或者VideoCapture的索引不对或者驱动问题。解决先确认没有其他程序比如微信、钉钉、Zoom占着摄像头。然后换索引试0 不行试 1、2。Windows 上如果还不行在VideoCapture后加cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)和cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)强制设分辨率有些摄像头默认分辨率不被支持就会黑屏。5.5 现象模型推理报CUDA out of memory原因显存不够batch 太大或图片分辨率太高。解决推理时把--img降到 416 或 320或者强制用 CPUmodel.to(cpu)。毕设演示对速度要求不高的话CPU 推理完全够用只是慢一点。6. 进阶技巧把检测结果做成可复现的验证流程到这一步系统基本能跑了。但毕设答辩或者课程设计验收时光能跑不够还得能证明跑得对。我一般会做一套固定的验证流程把结果量化出来这样答辩时心里有底。第一步是准备一个固定的小测试集从验证集里抽 50 到 100 张覆盖正常、雾天、黑夜、远距离几类场景每类至少 10 张。这个测试集不要参与训练专门用来验证。第二步是写一个批量推理脚本把测试集跑一遍输出每张图的检测结果和真实标注的对比。import os import cv2 import torch model torch.hub.load(ultralytics/yolov5, custom, pathmodels/best.pt, force_reloadFalse) test_dir test_images result_lines [] for fname in os.listdir(test_dir): if not fname.lower().endswith((.jpg, .png)): continue path os.path.join(test_dir, fname) img cv2.imread(path) results model(img) dets results.pandas().xyxy[0] # 只保留置信度大于 0.4 的 dets dets[dets[confidence] 0.4] labels dets[name].tolist() result_lines.append(f{fname}: {labels}) with open(test_result.txt, w, encodingutf-8) as f: f.write(\n.join(result_lines))逻辑说明这段脚本遍历测试目录逐张推理把文件名和检测到的类别写进文本文件。dets[confidence] 0.4是过滤低置信度框和推理时保持一致。输出用 utf-8 编码避免中文类别名写文件时报错。第三步是人工核对test_result.txt统计漏检和误检。漏检就是真实有标志但没检测出来误检就是检测出了不存在的标志。交通标志场景下漏检的代价更大所以如果漏检多优先加数据、加分辨率如果误检多提高置信度阈值。第四步是把这套流程固化成一个脚本每次改了模型或参数就重跑一遍对比前后结果。这样你能清楚知道每次改动是变好了还是变差了而不是凭感觉。注意验证集和测试集一定要分开。我见过有人拿训练集当测试集mAP 高得离谱一上真实场景就原形毕露。这是最典型的自欺欺人。从那以后我每次改完模型参数都强制走一遍这套批量验证流程哪怕只是调了个置信度阈值。因为模型这东西你不量化它它就跟你玩玄学。希望这套源码和上面的流程能帮你把毕设稳稳当当地做完。本文还有配套的精品资源点击获取
返回列表