【YOLOV5 入门】——Pyside6/PyQt5可视化UI界面后端逻辑

声明:笔记是做项目时根据B站博主视频学习时自己编写,请勿随意转载!


一、环境安装

VScode/Pycharm终端进入虚拟环境后,输入下面代码安装pyside6,若用的Pycharm作为集成开发环境,也下载个pyqt5

pip install pyside6
pip install pyqt5

安装完pyside6时其实一并安装了qtdesigner,这个工具可让我们以拖拽的方式设计界面,按下面方法找到这个工具放在桌面以便后续使用:

终端输入:

where python

现在用的虚拟环境是第二个,找到找到虚拟环境path/lib/site-packages/Pyside6/designer.exe

右键创建桌面快捷方式并打开,界面如下:

注意:这个工具生成的文件为.ui文件,不是.py文件,还需要一个编译器编译为.py文件,若用的VScode,在左侧扩展中安装插件qt for python即可;若用的Pycharm,ui文件转换为py可参考这篇博客(记得先安装pip install pyqt5):

Pycharm的QT Designer的.ui转.py文件icon-default.png?t=N7T8http://t.csdnimg.cn/M8TlS


二、QT Designer进行UI设计

①创建一个Main Window

②利用左侧的Label,创建两个图片显示框,一个显示原图片/视频,另一个显示检测结果

③按钮选择是检测图片还是视频,用到左侧的Push Button

 布局如下,文字位置等可在右侧属性编辑器中更改居中,图片和检测结果框需选中scaledContents勾选,因为实际图片的尺寸是不确定的。

为了区分名称可以在右侧对象框中,根据实际作用更改名称原始图片Label命名为input,检测结果Label命名为output,按钮分别是det_imagedet_video

如此UI设计结束,将其保存在我们的yolov5-7.0文件夹中,.ui文件命名为main_window: 


三、后端逻辑设计

首先利用上面提供的方法将.ui文件转换为.py文件,同名放在了文件夹如下图:

在yolov5-7.0文件夹中创建一个名为base_ui.py的文件用于编写我们的后端逻辑,先写个框架:

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication  #注:如果用的VScode就是from Pyside6
from main_window import Ui_MainWindow

class MainWindow(QMainWindow, Ui_MainWindow):  #新建一个MainWindow类,继承了两个类(一个导入的QMainWindow,另一个是main_window.py文件里的Ui_MainWindow)
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)  #调用setupUi(),它是main_window.py文件里的Ui_MainWindow类里的函数


if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = MainWindow()
    window.show()
    app.exec_()

点击运行即可加载出刚才设计的UI界面:

然后在代码框架中逐个定义需要的逻辑或者说函数。功能按钮的编写关键在于绑定信号与槽(bind_slots),即为每个按钮绑定触发事件。

import sys
import cv2
import torch
from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog  #注:如果用的VScode就是from Pyside6
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import QTimer  #解决视频检测时阻塞问题,循环不用while True用timer
from main_window import Ui_MainWindow

def convert2QImage(img):  #将array转换为UI Label可以显示的格式
    height, width, channel= img.shape
    return QImage(img, width, height, width*channel, QImage.Format_RGB888)

class MainWindow(QMainWindow, Ui_MainWindow):  #新建一个MainWindow类,继承了两个类(一个导入的QMainWindow,另一个是main_window.py文件里的Ui_MainWindow)
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)  #调用setupUi(),它是main_window.py文件里的Ui_MainWindow类里的函数
        # Model 使用torch.hub.load()函数加载YOLOv5目标检测模型
        self.model = torch.hub.load("./", "custom", "runs/train/exp9/weights/best", source="local")  #参照hub_detect代码加载模型
        self.timer = QTimer() #解决视频检测时阻塞问题,循环不用while True用timer
        self.timer.setInterval(100) #计时间隔ms
        self.video = None
        self.bind_slots()

    def image_pred(self, file_path):
        # 使用加载的模型对指定的图像进行目标检测。
        # model()方法接受一个图像路径作为输入,并返回检测结果。检测结果包含了检测框的坐标、类别标签和置信度等信息。
        results = self.model(file_path)
        image = results.render()[0]  #检测结果图片的array数组,但没法直接显示在ui的Label,需要上面编写的转换函数convert2QImage
        return convert2QImage(image)

    def open_image(self):
        #print("检测图片")
        file_path = QFileDialog.getOpenFileName(self, "选择图片", "./datasets/images/train", "Images (*.jpg *.png *.jpeg)")  #第一个参数是弹出框的名字,第二个参数是默认跳转路径,第三个参数过滤只显示某些文件格式的文件
        #file_path返回一个元组,('.../datasets/images/train/30.jpg', 'Images (*.jpg *.png *.jpeg)'),
        # 我们只需要第一个元素file_path[0]。不选路径元组为空
        if file_path[0]:
            file_path = file_path[0]
            qimage = self.image_pred(file_path)
            self.input.setPixmap(QPixmap(file_path))  #依据选择路径传入图片文件并显示
            self.output.setPixmap(QPixmap.fromImage(qimage))  #显示检测结果
        #print(file_path)

    def video_pred(self):
        ret, frame = self.video.read()  # 抽取一帧放在frame
        if not ret:
            self.timer.stop()
        else:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)  # 将这一帧frame转换为常规的RGB格式
            self.input.setPixmap(QPixmap.fromImage(convert2QImage(frame)))  # 依据选择路径传入图片文件并显示
            # 使用加载的模型对指定的图像进行目标检测。
            # model()方法接受一个图像路径作为输入,并返回检测结果。检测结果包含了检测框的坐标、类别标签和置信度等信息。
            results = self.model(frame)
            image = results.render()[0]  #检测结果图片的array数组,但没法直接显示在ui的Label,需要上面编写的转换函数convert2QImage
            self.output.setPixmap(QPixmap.fromImage(convert2QImage(image)))  # 显示检测结果

    def open_video(self):  #抽帧+单个图片检测+显示
        print("检测视频")
        file_path = QFileDialog.getOpenFileName(self, "选择图片", "./datasets", "Images (*.mp4)")
        if file_path[0]:
            file_path = file_path[0]
            self.video = cv2.VideoCapture(file_path)
            self.timer.start()


    def bind_slots(self):
        self.det_image.clicked.connect(self.open_image)  #当det_image按钮点击时(链接)执行open_image函数
        self.det_video.clicked.connect(self.open_video)
        self.timer.timeout.connect(self.video_pred)

if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = MainWindow()
    window.show()
    app.exec_()

上面是最终更改好的代码。函数逻辑按钮bind_slots函数里面套了open_image函数和open_video函数(绑定槽) ;然后open_image函数和open_video函数里面分别套了image_pred函数和video_pred函数,使得选好图片/视频路径后自动开始检测并显示

其中原本视频检测用的是抽帧和while true循环检测并显示的逻辑,但在前端中经常会遇到时间步长不合适出现阻塞问题,后来跟着博主用了qtimer计数器的方法,更改过程的视频如下:

YOLOv5检测UI可视化:timer时间步长更改

最终效果演示如下:

YOLOv5检测可视化界面效果演示

如果嫌显示的视频太卡顿,可在代码中更改时间步长:

self.timer.setInterval(100) #计时间隔ms,可以把100改的更小

小BUG

检测视频时,切换图片检测输入图片后一闪即逝,还在检测刚才的视频。这是由于计时器timer一直在运行,需要在open_image()函数中加一句,打开图片时关闭timer即可:

 def open_image(self):
        #print("检测图片")
        self.timer.stop()
        .....

 往期精彩

STM32专栏(付费9.9)icon-default.png?t=N7T8http://t.csdnimg.cn/E2F88

OpenCV-Python专栏(付费9.9)icon-default.png?t=N7T8http://t.csdnimg.cn/zK1jV

AI底层逻辑专栏(付费9.9)icon-default.png?t=N7T8http://t.csdnimg.cn/zic0f

机器学习专栏(免费)icon-default.png?t=N7T8http://t.csdnimg.cn/FaXzAFreeRTOS专栏(免费)icon-default.png?t=N7T8http://t.csdnimg.cn/SjIqU电机控制专栏(免费)icon-default.png?t=N7T8http://t.csdnimg.cn/FNWM7

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

移动Web学习07-适配单位vw/vh哔哩哔哩移动端vw单位适配案例

1.1、VW相对单位 前面我们已经学习了rem单位 &#xff0c;他是一个相对单位、相对于HTML表格字号大小 VW/VH也是一个相对单位&#xff0c;他是相对于视口的尺寸计算结果 VW&#xff1a;viewport width VH: viewport height <meta name"viewport" content"…

C语言之探秘:访问结构体空指针与结构体空指针的地址的区别(九十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

华为HarmonyOS 4.2公测升级计划扩展至15款新机型

华为近日宣布&#xff0c;HarmonyOS 4.2操作系统的公测升级计划将扩展到包括华为P50系列在内的15款设备。这一更新旨在为用户提供更优化的系统性能和增强的功能。 参与此次公测的机型包括华为P50、华为P50 Pro及其典藏版、华为P50E、华为P50 Pocket及其艺术定制版、华为nova系…

学习STM32第十四天

软件SPI读写W25Q64 一、简介 对W25Q64模块进行读写操作时&#xff0c;输出引脚配置为推挽输出&#xff0c;输入引脚配置为浮空或上拉输入。时钟、主机输出和片选都是输出引脚&#xff0c;主机输入是输入引脚。SPI协议是通过命令和数据进行通信&#xff0c;在硬件中使用移位寄…

将自己的项目上传至Git

一、安装Git 官网:Git (git-scm.com) 二、注册gitee 官网:工作台 - Gitee.com 进入“我的”出现以下界面 三、创建仓库 点击加号&#xff0c;新建仓库 根据自己的需求取名&#xff0c;描述仓库&#xff0c;开源还是私有&#xff0c;点击创建即可&#xff0c;点击我的即可…

每日一题 — 找到字符串中所有字母异位词

解法一&#xff1a;暴力枚举 解法二&#xff1a;滑动窗口hash表优化 定义left和right为起始坐标0&#xff0c;right向后遍历&#xff0c;并加入到哈希表中&#xff0c;然后也要记录下来每次进入哈希表的有效字符&#xff08;与目标字符串中相同的字符&#xff09;的个数且这个滑…

C++修炼之路之list模拟实现--C++中的双向循环链表

目录 引言 一&#xff1a;STL源代码中关于list的成员变量的介绍 二&#xff1a;模拟实现list 1.基本结构 2.普通迭代器 const迭代器的结合 3.构造拷贝构造析构赋值重载 清空 4.inserterase头尾插入删除 5.打印不同数据类型的数据《使用模板加容器来完成》 三&#xf…

SQLite、MySQL 和 PostgreSQL 数据库速度比较(本文阐述时间很早比较,不具有最新参考性)(二十五)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;用于 SQLite 的异步 I/O 模块&#xff08;二十四&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 注意&#xff1a;本文档非常非常旧。它描述了速度比较 SQLite、MySQL 和 PostgreSQL 的古老版本。 这里…

学习一门语言的方法和套路(B站转述)

视频链接 up虽然长相英(ping)俊(ping)&#xff0c;但是讲的干活&#xff0c;没恰饭。 学习流程&#xff1a; 1.快速阅读&#xff0c;掌握概况 2.深入细节内容 例如&#xff1a;java (JDBC)、html 、netty 不管三七二十一&#xff0c;先了解套路&#xff0c;再深入研究。 高…

安装CUDNN详细过程

cuDNN&#xff08;CUDA Deep Neural Network library&#xff09;是由NVIDIA开发的深度学习GPU加速库。 cuDNN包含了许多针对神经网络操作进行高度优化的函数&#xff0c;旨在使深度学习框架能够在NVIDIA的GPU上实现最佳性能&#xff0c;这个库提供了高效计算和加速&#xff0c…

牛客网刷题 :BC50 你是天才吗

描述 据说智商140以上者称为天才&#xff0c;KiKi想知道他自己是不是天才&#xff0c;请帮他编程判断。输入一个整数表示一个人的智商&#xff0c;如果大于等于140&#xff0c;则表明他是一个天才&#xff0c;输出“Genius”。 输入描述&#xff1a; 多组输入&#xff0c;每…

在 PyCharm 中使用系统安装的 Python 和 Anaconda 的 Python什么区别

virtualenv environment &#xff1a; virtualenv 是一个用于创建独立 Python 环境的工具。它可以在同一个系统上创建多个相互独立的 Python 环境&#xff0c;每个环境都有自己的 Python 解释器和包库&#xff0c;从而可以实现不同项目之间的依赖隔离和版本控制。coda environm…

vue快速入门(二十五)本地存储与初始化使用

注释很详细&#xff0c;直接上代码 上一篇 新增内容 本地获取数据数据存储到本地 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial…

2024蓝桥杯——宝石问题

先展示题目 声明 以下代码仅是我的个人看法&#xff0c;在自己考试过程中的优化版&#xff0c;本人考试就踩了很多坑&#xff0c;我会—一列举出来。代码可能很多&#xff0c;但是总体时间复杂度不高只有0(N) 函数里面的动态数组我没有写开辟判断和free&#xff0c;这里我忽略…

频率域滤波基础(离散傅里叶变换使用填充的缺陷)

本来是个很简单的问题&#xff0c;作者硬是写的这么复杂&#xff0c;翻译还搞错了。重点是我发现作者真正有用的东西没讲到&#xff0c;比如相位和谱如何影响图像。连个转换公式都没有&#xff0c;我只能说作者是在混字数。 首先看关于中心对称是什么意思&#xff1f;我木太明白…

MySql 视图 存储过程 触发器

文章目录 视图数据库对象视图的理解创建、查看、更新、删除 存储过程和存储函数概述分类存储过程的创建和调用存储函数的创建和调用存储过程和存储函数的对比存储过程和存储函数的查看、修改、删除 变量GLOBAL 与 SESSION 变量的使用会话用户变量和局部变量的使用 定义条件与处…

【机器学习300问】70、向量化技术来计算神经网络时维度如何确保正确?

一、向量化技术在进行神经网络计算时的优势 向量化是一种优化技术&#xff0c;通过使用数组操作代替for循环&#xff0c;可以大大提高代码的性能和效率。在深度学习中尤其明显&#xff0c;可以提高计算效率、简化代码、优化内存使用。 二、如何确保计算时维度是正确的&#xf…

中标了,Trojan/Hijack.v木马病毒怎么解决?

火绒只是提示有病毒木马&#xff0c;并未解决。 经过不断尝试.。。。。。。 往下拉找到 Internet选项 连接 – 局域网设置 把前面的勾选取消 发现以上办法网络上出现的搜索注册表关键字等办法都无法解决。。。 解决方法一&#xff1a; 电脑进入安全模式&#xff0c;然后进…

【vue】v-model 双向数据绑定

:value&#xff1a;单向数据绑定v-model&#xff1a;双向数据绑定 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

STM32 MPU配置参数

TXE LEVEL一般只用MPU_TEX_LEVEL0 1 - 1 - 1 -0性能最强&#xff08;TEX - C - B- S&#xff09;. #define MPU_TEX_LEVEL0 ((uint8_t)0x00) #define MPU_TEX_LEVEL1 ((uint8_t)0x01) #define MPU_TEX_LEVEL2 ((uint8_t)0x02) 基于上表进行常用配置 &#xff…