• 作者:老汪软件技巧
  • 发表时间:2024-10-09 11:02
  • 浏览量:

本文所涉及所有资源均在传知代码平台可获取。

1.概述

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

2.工程文件简介

2.1 工程文件结构

这是pycharm打开的工程文件,其中主要有存在权重文件、目标类别的文件夹,YOLOX模型的文件夹还有打包会输出的output文件夹,exe文件存在在这里面。

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

YOLOX模型由旷世科技提出,模型结构如下图所示。

主要分为两大部分,分别为主干特征提取网络和多尺度特征金字塔融合结构。主干特征提取网络由4个ResBlock堆叠组成,以对输入的图像进行多尺度特征提取,在这里会输出3个最终的有效特征层到特征金字塔融合结构中。在特征金字塔结构中,来自主干特征提取网络的3个有效特征层会进行多尺度的特征融合。因为在高分辨率的特征层具有的细节信息较多,而低分辨率的特征层具有的语义信息较多。首先会通过对低分辨率特征层P5_out进行上采样操作,以便能够和P4_out进行拼接融合。经过多尺度特征金字塔融合结构输出的特征层有三个,以能够实现不同尺寸目标的检测。

2.2 训练检测模型2.2.1 准备数据集

要在自己的数据集上训练YOLOX模型,首先我们需要根据VOC数据集的格式准备自己的数据集,并将数据集存放在VOCdevkit文件夹中。准备完数据集后,需要运行voc_annotation。py文件随机按比例为1:9生成模型可用的数据集标签,只需要运行voc_annotaion.py就行。

数据集准备完成后,我们就来到了train.py文件,这是训练YOLOX模型用的,重要的参数在代码中有注释

2.2.2 训练自己的权重文件

我们只需要修改voc_classes.txt文件中的内容,因为这是告诉模型我们数据集中一共有多少个类别;model_pate参数为模型的预训练权重文件,在我们自己数据集上训练时,使用官方提供的预训练权重文件,可以大大提高模型的精准率;训练轮数这设置的是100轮,相当于让模型在数据集上对每个图片学习100遍,训练的工程会生成模型的权重文件,存放在log文件夹中,权重文件我们会在检测的时候使用。

2.2.3 使用自己的权重文件

在模型训练完成后,我们只需要修改yolo.py文件中的几个地方,就能用我们自己训练的模型了。

一是修改权重文件的路径,我们训练得到的权重文件,训练的权重文件默认存放在log文件夹中,我们需要从中里面选一个loss损失值最低的作为检测时的权重文件。二是将classes_path修改成我们自己数据集的类型文件。这样检测模型就配置完成了。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函数,并提供了源码。并且较容易对源码进行修改,以训练自己的数据集,针对自己的应用领域。训练自己数据集请看文章的第二部分。

6.训练环境、VOC数据集和exe文件运行说明

训练环境配置和VOC数据集的链接存放在README.MD文件中。

6.1 exe文件运行说明

如果要想自己数据集上训练的系统能够以exe文件方式运行,我们需要将项目进行打包,这里我们推荐使用auto-py-to-exe打包工具,先要进行安装,安装命令

pip install auto-py-to-exe

安装完成后,在我们工程文件夹目录中进入cmd命令框,输入auto-py-to-exe.exe启动打包工具,启动完成后,脚本位置选择工程文件中的main.py文件,之后选择单文件,基于窗口的。之后就可点击转化。

main.exe可执行文件较大,因为其中包含了torch库文件,这里在VOC数据上训练的main.exe文件下载链接也存放在README.MD文件中。将main.exe文件下载后需要放到output文件夹中,output文件下还有两个文件夹分别为ui和model_data。其中ui文件夹中包含了系统运行所需的页面ui文件;model_data文件夹中包含了检测模型的权重文件和类别文件。双击main.exe文件运行时,可能需要等待一点时间等待系统启动。

感觉不错,点击我,立即使用