欢迎访问我的网站,希望内容对您有用,感兴趣的可以加入我们的社群。

当YOLOv5碰上PyQt5

YOLO 迷途小书童 3年前 (2021-06-30) 32304次浏览 17个评论

环境

  • windows 10 64位
  • gtx 1050Ti
  • yolov5 5.0 + pytorch1.7 + cu110
  • pyqt5

前言

有小伙伴在问,能不能给 yolov5 做个 GUI 界面,比如使用 pyqt5 框架? 本篇,我们就来实现一下,废话不多说,先看看效果图

yolov5 pyqt5

界面元素非常简单,2个功能按钮,对应的是图片和视频检测,1个图片显示区域,显示图片或视频目标检测后的结果

yolov5 pyqt5

当YOLOv5碰上PyQt5

基础环境安装

这里我们使用 yolov5 的最新发布版本5.0,依赖库的安装本篇就不再讲述了,可以参考 YOLOv5发布5.0版本

接下来安装 pyqt5,使用如下命令

pip install pyqt5 pyqt5-tools

UI界面设计

界面部分的设计,使用 pyqt5 自带的图形化设计工具 designer,好处是简单易用,所见即所得。设计完成后生成的 ui 文件,只需要执行一条命令就可以轻松转换成 python 代码。

首先打开 designer.exe,创建 Main Window

yolov5 pyqt5

界面上有2个按钮和一个文本框(使用文本框来显示图片),对应到 pyqt5 中是 push buttonlabel,从左侧的 widget box 中搜索并拖入到中间的工作区中,元素的属性可以在右侧修改

2个按钮,使用垂直布局排列

yolov5 pyqt5

按钮布局和文本框,使用水平布局

yolov5 pyqt5

为了自适应布局,也就是当放大、缩小窗口大小时,仍保持界面元素的比例,可以在空白位置,点击鼠标右键,选择 布局 –> 水平布局

yolov5 pyqt5

yolov5 pyqt5

布局的属性,同样的进行适当修改

yolov5 pyqt5

调整后的界面

yolov5 pyqt5

最后保存下,生成一个 .ui 的文件,然后,通过 pyqt5 提供的转换工具,将 ui 文件转换成 python 的代码,如下

pyuic5.bat -o main.py untitled.ui

生成的代码 main.py 是这样的

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '.\untitled.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setContentsMargins(-1, -1, 0, -1)
        self.verticalLayout.setSpacing(80)
        self.verticalLayout.setObjectName("verticalLayout")
        self.pushButton_img = QtWidgets.QPushButton(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.MinimumExpanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton_img.sizePolicy().hasHeightForWidth())
        self.pushButton_img.setSizePolicy(sizePolicy)
        self.pushButton_img.setMinimumSize(QtCore.QSize(150, 100))
        self.pushButton_img.setMaximumSize(QtCore.QSize(150, 100))
        font = QtGui.QFont()
        font.setFamily("Agency FB")
        font.setPointSize(12)
        self.pushButton_img.setFont(font)
        self.pushButton_img.setObjectName("pushButton_img")
        self.verticalLayout.addWidget(self.pushButton_img, 0, QtCore.Qt.AlignHCenter)
        self.pushButton_video = QtWidgets.QPushButton(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton_video.sizePolicy().hasHeightForWidth())
        self.pushButton_video.setSizePolicy(sizePolicy)
        self.pushButton_video.setMinimumSize(QtCore.QSize(150, 100))
        self.pushButton_video.setMaximumSize(QtCore.QSize(150, 100))
        font = QtGui.QFont()
        font.setFamily("Agency FB")
        font.setPointSize(12)
        self.pushButton_video.setFont(font)
        self.pushButton_video.setObjectName("pushButton_video")
        self.verticalLayout.addWidget(self.pushButton_video, 0, QtCore.Qt.AlignHCenter)
        self.verticalLayout.setStretch(0, 1)
        self.verticalLayout.setStretch(1, 1)
        self.horizontalLayout.addLayout(self.verticalLayout)
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.horizontalLayout.setStretch(0, 1)
        self.horizontalLayout.setStretch(1, 3)
        self.horizontalLayout_2.addLayout(self.horizontalLayout)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "PyQt5+YOLOv5示例"))
        self.pushButton_img.setText(_translate("MainWindow", "图片检测"))
        self.pushButton_video.setText(_translate("MainWindow", "视频检测"))
        self.label.setText(_translate("MainWindow", "TextLabel"))

整合YOLOv5和PyQt5

有了上面的 main.py 界面代码,我们就可以在它的基础上加入 yolov5 检测的代码了。说白了,就是将 yolov5 中的 detect.py 中相应的代码移植过来。

  1. 加个程序入口

    PyQt5 的惯用写法

    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        ui = Ui_MainWindow()
        ui.show()
        sys.exit(app.exec_())
  2. Ui_MainWindow 类中添加构造函数 __init__

    这里主要是几个方法的调用,包括界面的搭建、槽函数的初始化、定时器的初始化、模型的初始化

  3. 图片检测

    图片的选择与 yolov5 的检测,放在了一个方法中,检测结束后,将带有检测框的图片显示在文本框中

  4. 视频检测

    视频选择与视频检测,在2个方法(都是 slot )中处理,当选中了某个视频,定时器开启,然后视频检测的方法启动

代码下载

把工程已经放在了 github 上,https://github.com/xugaoxiang/yolov5-pyqt5,觉得有用,请给个 star

参考资料

喜欢 (12)

您必须 登录 才能发表评论!

(17)个小伙伴在吐槽
  1. 为什么看不到图片?
    匿名2022-02-26 02:26
  2. 请问博主,有没有办法可以做到视频不要逐帧检测,而是抽帧检测,保持视频原来的速度
    匿名2022-01-15 12:02
  3. 请问博主,有没有办法可以做到视频不要逐帧检测,而是抽帧检测,保持视频原来的速度,感觉在datasets.py里,但是改不出来,求教!
    匿名2022-01-15 12:01
    • 迷途小书童
      这个你在读取视频帧的时候处理一下就好了,第一帧处理,第二帧丢弃,依次循环
  4. 请问博主,有没有办法可以做到视频不要逐帧检测,而是抽帧检测,感觉在datasets.py里,但是改不出来,请教博主!
    匿名2022-01-15 11:57
  5. 一个界面可以整合多个代码吗?比如https://xugaoxiang.com/2021/07/15/yolov5-deepsort-fastreid/这一期里面包含了行人检测、跟踪和重试别。
    匿名2021-10-28 15:06
  6. 有人會媽
    匿名2021-10-23 14:37
  7. 能讲解一下yolo和pyqt对接部分代码的解释吗
    匿名2021-07-23 16:35
  8. 能出一期视频讲解一下yolo和pyqt对接部分代码的解释吗
    匿名2021-07-23 16:34
  9. 能出一期视频嘛?
    匿名2021-06-30 22:27