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

news2024/9/8 23:49:25

声明:笔记是做项目时根据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

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

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

相关文章

mysql 查询实战3-解答

对mysql 查询实战3-题目,进行一个解答 11、查询每⽉产品交易与退款情况 目标:查询每⽉产品交易(交易总额,交易数)与退款情况(退款总额,退款数) 1,先把日期格式化 使用 E…

npm配置阿里镜像库

1、配置阿里云镜像源 #查看当前使用的镜像地址命令 npm config get registry#设置阿里镜像源 npm config set registry http://registry.npmmirror.com 这里要注意下,之前的镜像源地址 https://registry.npm.taobao.org/ 已经不能用了,这里要更改为新…

科大讯飞星火开源大模型iFlytekSpark-13B GPU版部署方法

星火大模型的主页:iFlytekSpark-13B: 讯飞星火开源-13B(iFlytekSpark-13B)拥有130亿参数,新一代认知大模型,一经发布,众多科研院所和高校便期待科大讯飞能够开源。 为了让大家使用的更加方便,科…

李沐37_微调——自学笔记

标注数据集很贵 网络架构 1.一般神经网络分为两块,一是特征抽取原始像素变成容易线性分割的特征,二是线性分类器来做分类 微调 1.原数据集不能直接使用,因为标号发生改变,通过微调可以仍然对我数据集做特征提取 2.pre-train源…

SQL12 获取每个部门中当前员工薪水最高的相关信息

题目:获取每个部门中当前员工薪水最高的相关信息 注意了,这道题目,分组函数只能查出来:每个部门的最高薪水,group by dept_no ,根据部门分组,绝对不能group by dept_no,emp_no,不能…

el-tree如何修改节点点击颜色

el-tree修改点击节点颜色三大步 使用elementui库时,有时候我们会对里面提供的组件做一些样式修改。如果我们想要修改el-tree组件点击节点时的颜色,可以使用下面这种方式实现:

C++ | Leetcode C++题解之第29题两数相除

题目: 题解: class Solution { public:int divide(int dividend, int divisor) {// 考虑被除数为最小值的情况if (dividend INT_MIN) {if (divisor 1) {return INT_MIN;}if (divisor -1) {return INT_MAX;}}// 考虑除数为最小值的情况if (divisor I…

密码学基础 -- 走进RSA(2)(放弃数学原理版)

目录 1.概述 2. RSA测试 2.1 加解密实验 2.2 签名验签测试 3. RSA原理简介 4.小结 1.概述 从上面密码学基础 -- 走进RSA(1)(放弃数学原理版)-CSDN博客我们知道了非对称算法的密钥对使用时机,那么接下里我们继续讲解RSA,我们分别从RSA加解密、签名验…

【Unity】RPG小游戏创建游戏中的交互

RPG小游戏创建游戏中的交互 创建可交互的物体的公共的父类(Interactable)InteractableObject 类NPCObject 类PickableObject 类 创建可交互的物体的公共的父类(Interactable) InteractableObject 类 using System.Collections; u…

数字乡村创新实践推动农业现代化发展:科技赋能农业产业升级、提升农民收入水平与乡村治理效能

随着信息技术的迅猛发展和数字化转型的深入推进,数字乡村创新实践已成为推动农业现代化发展的重要引擎。数字技术的广泛应用不仅提升了农业生产的智能化水平,也带动了农民收入的增加和乡村治理的现代化。本文旨在探讨数字乡村创新实践如何科技赋能农业产…

61、ARM/串口通信相关学习20240415

一、串口通信:实现PC端串口助手与开发板的字符串通信。 代码: main: #include "uart4.h"int main(){uart4_config();//char a;char s[64];while (1){//a getchar();//putchar(a1);gets(s);puts(s);}return 0;}usrt4.c&#xff…

供应链投毒预警 | 开源供应链投毒202403月报发布啦!(含投毒案例分析)

悬镜供应链安全情报中心通过持续监测全网主流开源软件仓库,结合程序动静态分析方式对潜在风险的开源组件包进行动态跟踪和捕获,能够第一时间捕获开源组件仓库中的恶意投毒攻击。在2024年3月份,悬镜供应链安全情报中心在NPM官方仓库&#xff0…

golang 迷宫回溯算法(递归)

// Author sunwenbo // 2024/4/14 20:13 package mainimport "fmt"// 编程一个函数,完成老鼠找出路 // myMap *[8][7]int 地图,保证是同一个地图,因此是引用类型 // i,j表示对地图的哪个点进行测试 func SetWay(myMap *[8][7]int, …

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

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

【华为】Telnet实验配置

【华为】Telnet 实验配置 应用场景三种认证方式配置注意事项拓扑无认证(None)交换机配置顺序Telnet ServerTelnet Client测试 密码认证(Password)配置顺序Telnet ServerTelnet Client测试 AAA认证(scheme)配…

密码学 | 椭圆曲线 ECC 密码学入门(四)

目录 正文 1 曲线方程 2 点的运算 3 求解过程 4 补充:有限域 ⚠️ 知乎:【密码专栏】动手计算双线性对(中) - 知乎 ⚠️ 写在前面:本文属搬运博客,自己留着学习。注意,这篇博客与前三…

验证ElasticSearch 分词的BUG

验证ElasticSearch 分词的BUG 环境介绍 ElasticSearch 版本号: 6.7.0 BUG 重现 创建测试案例索引 PUT test_2022 {"settings": {"analysis": {"filter": {"pinyin_filter": {"type": "pinyin"}},"analy…

万界星空科技商业开源MES+项目合作+低代码平台

今天我想和大家分享的是一套商业开源的 MES制造执行管理系统。对于制造业而言,MES 是一个至关重要的系统,它可以帮助企业提高生产效率、优化资源利用、提高产品质量,从而增强市场竞争力。什么是 MES? MES 是指通过计算机技术、自动…

uniapp开发 如何获取IP地址?

一、需求 使用uniapp开发小程序时,需要调取【记录日活动统计】的接口,而这个接口需要传递一个ip给后台, 那么前端如何获取ip呢?下面代码里可以实现 二、代码实现 1.在项目的manifest.json中配置一下网络权限: &quo…

企业网络日益突出的难题与SD-WAN解决方案

随着企业规模的迅速扩张和数字化转型的深入推进,企业在全球范围内需要实现总部、分支机构、门店、数据中心、云等地点的网络互联、数据传输和应用加速。SD-WAN作为当今主流解决方案,在网络效率、传输质量、灵活性和成本等方面远远超越传统的互联网、专线…