YOLOX+PyQt5交通路口智能监测平台设计与实现

1.概述

交通要道的路口上人车穿行,特别是上下班早高峰,且时常发生交通事故。因此对交通路口的车流量和人流量的监测必不可少。

2.检测模型

使用的检测模型为YOLOX模型,模型权重为训练VOC数据集得来,其中包括了二十个类别,但我们主要针对地面交通路口进行监测,选择了最关键的三个监测要素作为监测目标,分别为人、汽车和自行车。YOLOX神经网络模型介绍如下:
YOLOX模型由旷世科技提出,模型结构如下图所示。
在这里插入图片描述

主要分为两大部分,分别为主干特征提取网络和多尺度特征金字塔融合结构。

2.1 主干特征提取网络

主干特征提取网络由4个ResBlock堆叠组成,以对输入的图像进行多尺度特征提取,在这里会输出3个最终的有效特征层到特征金字塔融合结构中。

class YOLOPAFPN(nn.Module):def __init__(self, depth=1.0, width=1.0, in_features=("dark3", "dark4", "dark5"), in_channels=[256, 512, 1024],depthwise=False, act="silu"):super().__init__()Conv = DWConv if depthwise else BaseConvself.backbone = CSPDarknet(depth, width, depthwise=depthwise, act=act)self.in_features = in_featuresself.upsample = nn.Upsample(scale_factor=2, mode="nearest")# -------------------------------------------##   20, 20, 1024 -> 20, 20, 512# -------------------------------------------#self.lateral_conv0 = BaseConv(int(in_channels[2] * width), int(in_channels[1] * width), 1, 1, act=act)# -------------------------------------------##   40, 40, 1024 -> 40, 40, 512# -------------------------------------------#self.C3_p4 = CSPLayer(int(2 * in_channels[1] * width),int(in_channels[1] * width),round(3 * depth),False,depthwise=depthwise,act=act,)# -------------------------------------------##   40, 40, 512 -> 40, 40, 256# -------------------------------------------#self.reduce_conv1 = BaseConv(int(in_channels[1] * width), int(in_channels[0] * width), 1, 1, act=act)# -------------------------------------------##   80, 80, 512 -> 80, 80, 256# -------------------------------------------#self.C3_p3 = CSPLayer(int(2 * in_channels[0] * width),int(in_channels[0] * width),round(3 * depth),False,depthwise=depthwise,act=act,)# -------------------------------------------##   80, 80, 256 -> 40, 40, 256# -------------------------------------------#self.bu_conv2 = Conv(int(in_channels[0] * width), int(in_channels[0] * width), 3, 2, act=act)# -------------------------------------------##   40, 40, 256 -> 40, 40, 512# -------------------------------------------#self.C3_n3 = CSPLayer(int(2 * in_channels[0] * width),int(in_channels[1] * width),round(3 * depth),False,depthwise=depthwise,act=act,)# -------------------------------------------##   40, 40, 512 -> 20, 20, 512# -------------------------------------------#self.bu_conv1 = Conv(int(in_channels[1] * width), int(in_channels[1] * width), 3, 2, act=act)# -------------------------------------------##   20, 20, 1024 -> 20, 20, 1024# -------------------------------------------#self.C3_n4 = CSPLayer(int(2 * in_channels[1] * width),int(in_channels[2] * width),round(3 * depth),False,depthwise=depthwise,act=act,)def forward(self, input):out_features = self.backbone.forward(input)[feat1, feat2, feat3] = [out_features[f] for f in self.in_features]P5 = self.lateral_conv0(feat3)P5_upsample = self.upsample(P5)P5_upsample = torch.cat([P5_upsample, feat2], 1)P5_upsample = self.C3_p4(P5_upsample)P4 = self.reduce_conv1(P5_upsample)P4_upsample = self.upsample(P4)P4_upsample = torch.cat([P4_upsample, feat1], 1)P3_out = self.C3_p3(P4_upsample)P3_downsample = self.bu_conv2(P3_out)P3_downsample = torch.cat([P3_downsample, P4], 1)P4_out = self.C3_n3(P3_downsample)P4_downsample = self.bu_conv1(P4_out)P4_downsample = torch.cat([P4_downsample, P5], 1)P5_out = self.C3_n4(P4_downsample)return (P3_out, P4_out, P5_out)

return (P3_out,P4_out,P5_out)表示主干特征提取网络输出的3个最终特征层。

2.2 多尺度特征金字塔融合结构

在特征金字塔结构中,来自主干特征提取网络的3个有效特征层会进行多尺度的特征融合。因为在高分辨率的特征层具有的细节信息较多,而低分辨率的特征层具有的语义信息较多。首先会通过对低分辨率特征层P5_out进行上采样操作,以便能够和P4_out进行拼接融合。经过多尺度特征金字塔融合结构输出的特征层有三个,以能够实现不同尺寸目标的检测。
多尺度特征金子塔融合结构的代码如下:

class YOLOXHead(nn.Module):def __init__(self, num_classes, width=1.0, in_channels=[256, 512, 1024], act="silu", depthwise=False, ):super().__init__()Conv = DWConv if depthwise else BaseConvself.cls_convs = nn.ModuleList()self.reg_convs = nn.ModuleList()self.cls_preds = nn.ModuleList()self.reg_preds = nn.ModuleList()self.obj_preds = nn.ModuleList()self.stems = nn.ModuleList()for i in range(len(in_channels)):self.stems.append(BaseConv(in_channels=int(in_channels[i] * width), out_channels=int(256 * width), ksize=1, stride=1,act=act))self.cls_convs.append(nn.Sequential(*[Conv(in_channels=int(256 * width), out_channels=int(256 * width), ksize=3, stride=1, act=act),Conv(in_channels=int(256 * width), out_channels=int(256 * width), ksize=3, stride=1, act=act),]))self.cls_preds.append(nn.Conv2d(in_channels=int(256 * width), out_channels=num_classes, kernel_size=1, stride=1, padding=0))self.reg_convs.append(nn.Sequential(*[Conv(in_channels=int(256 * width), out_channels=int(256 * width), ksize=3, stride=1, act=act),Conv(in_channels=int(256 * width), out_channels=int(256 * width), ksize=3, stride=1, act=act)]))self.reg_preds.append(nn.Conv2d(in_channels=int(256 * width), out_channels=4, kernel_size=1, stride=1, padding=0))self.obj_preds.append(nn.Conv2d(in_channels=int(256 * width), out_channels=1, kernel_size=1, stride=1, padding=0))def forward(self, inputs):outputs = []for k, x in enumerate(inputs):x = self.stems[k](x)cls_feat = self.cls_convs[k](x)cls_output = self.cls_preds[k](cls_feat)reg_feat = self.reg_convs[k](x)reg_output = self.reg_preds[k](reg_feat)obj_output = self.obj_preds[k](reg_feat)output = torch.cat([reg_output, obj_output, cls_output], 1)outputs.append(output)return outputs

这里return返回的outputs是一个列表,长度为3,为多尺度特征金字塔融合结构的输出结果。

3.系统可视化

系统使用了PyQt5作为可视化工具,PyQt和C++中的qt类似,具有良好的交互性,包含了日常开发常用的控件,像显示提示控件QLabel,按钮QPushbotton,输入框控件TextBrowser等,并且实现了信号槽机制,能够简单快速的获取页面控件和响应事件。系统整体效果如下:
在这里插入图片描述

系统整体布局为线性垂直布局,从上至下依次为系统标题、功能区和显示区。显示区为监测的实时画面显示,这里通过QLabel控件来作为一个容器,来接受opencv库中的视频流。
系统实现了实时摄像头监测功能和上传视频监测功能,

3.1 打开摄像头

当用户点击打开摄像头后,系统将打开电脑的默认摄像头进行画面获取,并将获取的画面进行监测,这里最重要的代码就是定时器函数,因为用户点击打开摄像头后,只是一个瞬间事件,而系统需要将摄像头拍摄的画面进行实时检测,这是一个连续性事件,而下面这两行代码很重要

self.timer_camera = QtCore.QTimer()
self.timer_camera.timeout.connect(self.show_camera)  # 将timeout绑定槽函数show_camera

self.timer_camera = QtCore.QTimer()定义了定时器,并通过信号槽self.timer_camera.timeout.connect(self.show_camera)进行了检测事件绑定。

打开摄像头按钮代码如下:

    def open_camera_btn(self):if not self.timer_camera.isActive():  # 定时器未启动flag = self.cap.open(self.CAM_NUM)if flag == False:msg = QtWidgets.QMessageBox.warning(self.window, '警告!', "请检查摄像头是否连接正确",buttons=QtWidgets.QMessageBox.Ok)else:self.timer_camera.start()  # 设置30毫秒后,定时器将每隔30毫秒调用timeout函数self.open_camera.setText('关闭监测')# 关闭检测按钮事件else:self.timer_camera.stop()self.cap.release()self.label_show_camera.clear()  # 清空视频显示区域self.open_camera.setText('开始监测')

这里就比较简单了,只需判断当前定时器是否被打开,如果没有就去打开摄像头,并启动定时器,再把摄像头的提示文字修改一下,改为“关闭摄像头”,当用户再次点击按钮时,就可以关闭摄像头,并将定时器暂定,一个按钮实现启动和关闭功能。

3.2 上传视频监测

上传视频监测按钮整体功能与打开摄像头类似,只需要将视频流进行更改,这里通过QFileDialog.getOpenFileName()函数来实现打开资源文件窗口进行视频选择,并将选择的视频文件的绝对路径进行返回,这样就能将视频的绝对路径传给opencv进行视频流读取:

上传视频文件监测按钮代码如下:

    def video_detect_btn(self):fileUrl, _ = QFileDialog.getOpenFileName(self, "Open Video File", QDir.currentPath(),"Video Files (*.mp4 *.avi *.mov *.wmv);;")# 视频选择成功if fileUrl:print(fileUrl)self.label_video_url.setText(fileUrl)if not self.timer_camera.isActive():  # 定时器未启动flag = self.cap.open(fileUrl)if flag == False:msg = QtWidgets.QMessageBox.warning(self.window, '警告!', "请检查摄像头是否连接正确",buttons=QtWidgets.QMessageBox.Ok)else:self.timer_camera.start()  # 设置30毫秒后,定时器将每隔30毫秒调用timeout函数

点击上传监测视频后,将打开资源文件窗口进行视频文件选择,效果如下:
在这里插入图片描述

用户选择完成后,将开始逐帧检测。

3.3 统计结果显示

页面中的结果显示也采用了垂直线性布局的方式,效果如下:
在这里插入图片描述

目标种类和统计结果两个垂直线性布局包裹在一个QWidget控件中,QWidget控件使用水平线性布局的方式。行人、汽车和自行车统计结果在show_res_num()中实现,dict是一个字典类型的变量,key为目标类型,value为目标类别对应的个数。
代码为:

        label_list = [*dict]all = 0# for i in label_list:#     all = all + int(dict.get(i))# self.all_result.setText(str(all))if 'person' in label_list:self.person_num.setText(str(dict['person']))all += int(dict['person'])else:self.person_num.setText('0')if 'car' in label_list:self.car_num.setText(str(dict['car']))all += int(dict['car'])else:self.car_num.setText('0')if 'bicycle' in label_list:self.light_num.setText(str(dict['bicycle']))all += int(dict['bicycle'])else:self.light_num.setText('0')self.all_result.setText(str(all))

4.效果

在这里插入图片描述

5.总结

这里的监测模型使用的是旷视科技提出的YOLOX检测模型,并且权重文件也使用的是官方提供的s版,能够检测的类别有二十种,这里只选取了三种监测模型进行了统计结果显示。程序的入口为main函数,并提供了源码。并且较容易对源码进行修改,以训练自己的数据集,针对自己的应用领域。
YOLOX模型github地址:https://github.com/Megvii-BaseDetection/YOLOX
VOC2012数据集地址:https://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar 官方工具文档:http://host.robots.ox.ac.uk/pascal/VOC/voc2012/htmldoc/index.html

6.环境和exe文件运行说明

6.1 源码运行的python环境

python == 3.8
PyQt5 == 5.15.2
torch == 1.9.1+cu111

6.2 exe文件运行说明

在这里插入图片描述
在这里插入图片描述

main.exe可执行文件较大,因为其中包含了torch库文件,main.py文件下载链接:main.exe下载地址
提取码:8cfk
将main.py文件下载后需要放到output文件夹中,output文件下还有两个文件夹分别为ui和model_data。其中ui文件夹中包含了系统运行所需的页面ui文件;model_data文件夹中包含了检测模型的权重文件和类别文件。双击main.exe文件运行时,可能需要等待一点时间等待系统启动。
参考文章: https://blog.csdn.net/weixin_44791964/article/details/120476949

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/875956.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3二次封装axios

官网: https://www.axios-http.cn/docs/interceptors steps1: 安装 npm install axios -ssteps2: /src/api/request.js 文件 >>> 拦截器 import axios from axios // 如果没用element-plus就不引入 import { ElMessage } from element-plusconst service axios.cre…

【区块链+绿色低碳】基于区块链的双碳能源纳管平台 | FISCO BCOS应用案例

在双碳战略的指导下,南京区块链产业应用协会牵头研发的双碳能源纳管平台,依托区块链、人工智能、云计算、 物联网、大数据、工业互联网与边缘计算等技术,对绿电追溯、需求侧响应、能源微网、源网荷储、隔墙用电、 碳排放权认证、额度计量、预…

循环队列的实现【C语言】

用数组实现循环队列 题目:622. 设计循环队列 - 力扣(LeetCode) 分析 循环队列,队列满则不能再插入数据,队列为空则不能再出数据。 多开一个空间方便区分队列为空和队列为满的情况。 如果要存K个数据只开K个空间&a…

【在排序数组中查找元素的第一个和最后一个位置】python刷题记录

R2-分治 有点easy的感觉,感觉能用哈希表 class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:nlen(nums)dictdefaultdict(list)#初始赋值哈希表,记录出现次数for num in nums:if not dict[num]:dict[num]1else:dict[…

【C++】C++应用案例-翻转数组

翻转数组,就是要把数组中元素的顺序全部反过来。比如一个数组{1,2,3,4,5,6,7,8},翻转之后就是{8,7,6,5,4,3,2,1}。 (1)另外创建数组,反向填入元素 数组是将元素按照顺序依次存放的,长度固定。所以如果想要…

基因组挖掘指导天然药物分子的发现-文献精读34

基因组挖掘指导天然药物分子的发现 摘要 天然产物是临床药物的主要来源,也是新药研发过程中先导化合物结构设计和优化的灵感源泉。但传统策略天然药源分子的发现却遭遇了瓶颈,新颖天然产物的数量逐渐无法满足现代药物开发的需求和应对全球多药耐药的威胁…

【每日刷题】Day86

【每日刷题】Day86 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 118. 杨辉三角 - 力扣(LeetCode) 2. 数组中出现次数超过一半的数字_牛客题霸…

Java之 jvm

jvm之管理内存 程序计数器:当前线程所执行的字节码的行号指示器。程序计数器是唯一一个不会出现 OutOfMemoryError 的内存区域,它的生命周期随着线程的创建而创建,随着线程的结束而死亡。Java虚拟机栈 方法调用 一个方法调用都会有对应的栈帧…

加速下载,揭秘Internet Download Manager2024下载器的威力!

1. Internet Download Manager(IDM)是一款广受欢迎的下载管理软件,以其强大的下载加速功能和用户友好的界面著称。 IDM马丁正版下载如下: https://wm.makeding.com/iclk/?zoneid34275 idm最新绿色版一键安装包链接:抓紧保存以…

ISP 代理提供商:互联网安全的关键参与者

简介:互联网安全的演变态势 互联网改变了我们互动、工作和开展业务的方式,但也带来了与安全性和可访问性相关的重大挑战。在这个数字时代,互联网服务提供商 (ISP) 代理提供商在解决这些问题方面发挥着关键作用。他们提供的基本服务不仅可以增…

网络安全常见错误及解决办法(更新中)

# 开启代理,无法连接网络 把代理关掉 # 上一秒还在安装tree,下一秒xshell就连接不上了 —》sshd服务的key这个文件权限过高,跟装tree没有关系,装一个epel 源,epel-release​ 部分命令:chmod 600 /etc/ssh…

google、windows自带语音识别中英文等实时字幕使用

2、自带实时字幕 1)google浏览器自带 实时字幕 设置里可以设置: 有视频声音播放会弹出黑色文本框 下载其他语言包-比如中文: 测试 2)windows11 辅助功能 实时字幕 (直接快捷键打开:Win Ctrl L&#…

C# 实现条件变量

C# 进程通信系列 第一章 共享内存 第二章 条件变量(本章) 第三章 消息队列 文章目录 C# 进程通信系列前言一、关键实现1、用到的主要对象2、初始化区分创建和打开3、变量放到共享内存4、等待和释放逻辑 二、完整代码三、使用示例1、线程同步控制2、进程…

ROS配置并同时驱动多个UVC相机(含功能包)

配置并同时驱动多个UVC相机,并将数据保存为ROS话题形式的bag文件。 ROS可以同时驱动多个UVC相机。要实现这个目标并将数据保存成ROS话题的形式,再保存为bag文件,可以按照以下步骤操作: 1. 安装必要的包 sudo apt-get update sud…

MySQL零散拾遗(四)--- 使用聚合函数时需要注意的点点滴滴

聚合函数 聚合函数作用于一组数据,并对一组数据返回一个值。 常见的聚合函数:SUM()、MAX()、MIN()、AVG()、COUNT() 对COUNT()聚合函数的更深一层理解 COUNT函数的作用:计算指定字段在查询结果中出现的个数(不包含NULL值&#…

ElMessage自动引入,样式缺失和ts esline 报错问题解决

一. 环境 "unplugin-auto-import": "^0.17.6", "vue": "^3.3.8", "vite": "^5.0.0", "typescript": "^5.2.2",二. ElMessage样式缺失问题. 以下有两种解决方法 方法一: 配置了自动引用后…

Oracle集群RAC磁盘管理命令asmcmd的使用

文章目录 ASM磁盘共享简介ASM磁盘共享的优势ASM磁盘组成ASM磁盘共享的应用场景Asmcmd简介Asmcmd的功能Asmcmd的命令Asmcmd的使用注意事项Asmcmd运行模式交互模式运行非交互模式运行ASMCMD命令分类实例管理命令:文件管理命令:磁盘组管理命令:模板管理命令:文件访问管理命令:…

Python文献调研(一)环境搭建

一、安装Python版本 1.点击进入Python官网 Download Python | Python.org 2.根据自己的需求选择python的版本,点击【Download】 3.自定义安装路径,记得勾选Add Python xxx to PATH 这步是自动配置环境变量的,如果忘记勾选,建议…

VirtualBox 安装Centos 7 避坑指南 SSH连不上 镜像失效 静态网络配置等

背景 几乎每次安装Centos 7 时,都会遇到各种各样的问题,毕竟每次安装动辄就是半年几年,几乎都是在换工作时,有了新机器才会倒腾一次,时间久远,就会忘记一些细节,这次整理一下,避免以…

如何定位线上OOM

造成OOM的原因 1一次性申请太多对象。如:从数据库获取大量数据。 解决方法:更改申请对象的数量。如:做个分页。 2内存资源使用完未释放。如:太多线程建立数据库连接而未释放。 解决方法:使用线程池。 3本身资源不够…