当前位置:   article > 正文

PyQt5搭建YOLOv5可视化界面_pyqt5 yolov5

pyqt5 yolov5

这里跟随博主学习开发利用PyQT5搭建YOLOv5可视化界面,并打包成exe程序。

博主原文:【目标检测】利用PyQT5搭建YOLOv5可视化界面_return _vf.meshgrid(tensors, **kwargs) # type: ign_zstar-_的博客-CSDN博客

(一)相关准备

这里要用到yolov5的模型和权重,如下图

这些文件夹直接从配置好的yolov5中复制过来

下面解释一下各文件夹的用途

models:存放模型构建相关程序

utils:存放绘图、数据加载等相关工具,直接从yolov5-5.0版本中clone过来

UI:存放软件图标

result:存放预测之后的图片或视频

weights:模型权重,默认使用YOLOv5官方提供的yolov5s.pt

(二)核心代码

  1. import os
  2. import sys
  3. import cv2
  4. import random
  5. import torch
  6. import numpy as np
  7. import torch.backends.cudnn as cudnn
  8. import qdarkstyle
  9. from PyQt5 import QtCore, QtGui, QtWidgets
  10. from PyQt5.QtGui import QIcon, QPixmap
  11. from models.experimental import attempt_load
  12. from utils.general import check_img_size, non_max_suppression, scale_coords
  13. from utils.datasets import letterbox
  14. from utils.plots import plot_one_box
  15. class Ui_MainWindow(QtWidgets.QMainWindow):
  16. def __init__(self, parent=None):
  17. super(Ui_MainWindow, self).__init__(parent)
  18. self.timer_video = QtCore.QTimer()
  19. self.setupUi(self)
  20. self.init_logo()
  21. self.init_slots()
  22. self.cap = cv2.VideoCapture()
  23. self.out = None
  24. self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  25. self.half = self.device.type != 'cpu' # half precision only supported on CUDA
  26. cudnn.benchmark = True
  27. weights = 'D:\Qt\QtData\PyQt\YOLOv5_visualization_interface\weights\yolov5s.pt' # 模型加载路径
  28. imgsz = 640 # 预测图尺寸大小
  29. self.conf_thres = 0.25 # NMS置信度
  30. self.iou_thres = 0.45 # IOU阈值
  31. # 载入模型
  32. self.model = attempt_load(weights, map_location=self.device)
  33. stride = int(self.model.stride.max())
  34. self.imgsz = check_img_size(imgsz, s=stride)
  35. if self.half:
  36. self.model.half() # to FP16
  37. # 从模型中获取各类别名称
  38. self.names = self.model.module.names if hasattr(self.model, 'module') else self.model.names
  39. # 给每一个类别初始化颜色
  40. self.colors = [[random.randint(0, 255) for _ in range(3)] for _ in self.names]
  41. def setupUi(self, MainWindow):
  42. MainWindow.setObjectName("MainWindow")
  43. MainWindow.resize(900, 600)
  44. # MainWindow.setStyleSheet("")
  45. self.centralwidget = QtWidgets.QWidget(MainWindow)
  46. self.centralwidget.setObjectName("centralwidget")
  47. # self.centralwidget.setStyleSheet("border: 1px solid white;")
  48. self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
  49. self.horizontalLayout_2.setObjectName("horizontalLayout_2")
  50. self.horizontalLayout = QtWidgets.QHBoxLayout()
  51. self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint)
  52. self.horizontalLayout.setObjectName("horizontalLayout")
  53. self.verticalLayout = QtWidgets.QVBoxLayout()
  54. self.verticalLayout.setContentsMargins(0, 0, 0, 0) # 布局的左、上、右、下到窗体边缘的距离
  55. # self.verticalLayout.setSpacing(0)
  56. self.verticalLayout.setObjectName("verticalLayout")
  57. # 打开图片按钮
  58. self.pushButton_img = QtWidgets.QPushButton(self.centralwidget)
  59. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.MinimumExpanding)
  60. sizePolicy.setHorizontalStretch(0)
  61. sizePolicy.setVerticalStretch(0)
  62. sizePolicy.setHeightForWidth(self.pushButton_img.sizePolicy().hasHeightForWidth())
  63. self.pushButton_img.setSizePolicy(sizePolicy)
  64. self.pushButton_img.setMinimumSize(QtCore.QSize(150, 40))
  65. self.pushButton_img.setMaximumSize(QtCore.QSize(150, 40))
  66. font = QtGui.QFont()
  67. font.setFamily("Agency FB")
  68. font.setPointSize(12)
  69. self.pushButton_img.setFont(font)
  70. self.pushButton_img.setObjectName("pushButton_img")
  71. self.verticalLayout.addWidget(self.pushButton_img, 0, QtCore.Qt.AlignHCenter)
  72. self.verticalLayout.addStretch(5) # 增加垂直盒子内部对象间距
  73. # 打开摄像头按钮
  74. self.pushButton_camera = QtWidgets.QPushButton(self.centralwidget)
  75. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
  76. sizePolicy.setHorizontalStretch(0)
  77. sizePolicy.setVerticalStretch(0)
  78. sizePolicy.setHeightForWidth(self.pushButton_camera.sizePolicy().hasHeightForWidth())
  79. self.pushButton_camera.setSizePolicy(sizePolicy)
  80. self.pushButton_camera.setMinimumSize(QtCore.QSize(150, 40))
  81. self.pushButton_camera.setMaximumSize(QtCore.QSize(150, 40))
  82. self.pushButton_camera.setFont(font)
  83. self.pushButton_camera.setObjectName("pushButton_camera")
  84. self.verticalLayout.addWidget(self.pushButton_camera, 0, QtCore.Qt.AlignHCenter)
  85. self.verticalLayout.addStretch(5)
  86. # 打开视频按钮
  87. self.pushButton_video = QtWidgets.QPushButton(self.centralwidget)
  88. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
  89. sizePolicy.setHorizontalStretch(0)
  90. sizePolicy.setVerticalStretch(0)
  91. sizePolicy.setHeightForWidth(self.pushButton_video.sizePolicy().hasHeightForWidth())
  92. self.pushButton_video.setSizePolicy(sizePolicy)
  93. self.pushButton_video.setMinimumSize(QtCore.QSize(150, 40))
  94. self.pushButton_video.setMaximumSize(QtCore.QSize(150, 40))
  95. self.pushButton_video.setFont(font)
  96. self.pushButton_video.setObjectName("pushButton_video")
  97. self.verticalLayout.addWidget(self.pushButton_video, 0, QtCore.Qt.AlignHCenter)
  98. self.verticalLayout.addStretch(50)
  99. # 显示导出文件夹按钮
  100. self.pushButton_showdir = QtWidgets.QPushButton(self.centralwidget)
  101. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
  102. sizePolicy.setHorizontalStretch(0)
  103. sizePolicy.setVerticalStretch(0)
  104. sizePolicy.setHeightForWidth(self.pushButton_showdir.sizePolicy().hasHeightForWidth())
  105. self.pushButton_showdir.setSizePolicy(sizePolicy)
  106. self.pushButton_showdir.setMinimumSize(QtCore.QSize(150, 50))
  107. self.pushButton_showdir.setMaximumSize(QtCore.QSize(150, 50))
  108. self.pushButton_showdir.setFont(font)
  109. self.pushButton_showdir.setObjectName("pushButton_showdir")
  110. self.verticalLayout.addWidget(self.pushButton_showdir, 0, QtCore.Qt.AlignHCenter)
  111. # 右侧图片/视频填充区域
  112. self.verticalLayout.setStretch(2, 1)
  113. self.horizontalLayout.addLayout(self.verticalLayout)
  114. self.label = QtWidgets.QLabel(self.centralwidget)
  115. self.label.setObjectName("label")
  116. self.horizontalLayout.addWidget(self.label)
  117. self.horizontalLayout.setStretch(0, 1)
  118. self.horizontalLayout.setStretch(1, 3)
  119. self.horizontalLayout_2.addLayout(self.horizontalLayout)
  120. self.label.setStyleSheet("border: 1px solid white;") # 添加显示区域边框
  121. # 底部美化导航条
  122. MainWindow.setCentralWidget(self.centralwidget)
  123. self.menubar = QtWidgets.QMenuBar(MainWindow)
  124. self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
  125. self.menubar.setObjectName("menubar")
  126. MainWindow.setMenuBar(self.menubar)
  127. self.statusbar = QtWidgets.QStatusBar(MainWindow)
  128. self.statusbar.setObjectName("statusbar")
  129. MainWindow.setStatusBar(self.statusbar)
  130. self.retranslateUi(MainWindow)
  131. QtCore.QMetaObject.connectSlotsByName(MainWindow)
  132. def retranslateUi(self, MainWindow):
  133. _translate = QtCore.QCoreApplication.translate
  134. MainWindow.setWindowTitle(_translate("MainWindow", "YOLOv5目标检测平台"))
  135. self.pushButton_img.setText(_translate("MainWindow", "图片检测"))
  136. self.pushButton_camera.setText(_translate("MainWindow", "摄像头检测"))
  137. self.pushButton_video.setText(_translate("MainWindow", "视频检测"))
  138. self.pushButton_showdir.setText(_translate("MainWindow", "打开输出文件夹"))
  139. self.label.setText(_translate("MainWindow", "TextLabel"))
  140. def init_slots(self):
  141. self.pushButton_img.clicked.connect(self.button_image_open)
  142. self.pushButton_video.clicked.connect(self.button_video_open)
  143. self.pushButton_camera.clicked.connect(self.button_camera_open)
  144. self.pushButton_showdir.clicked.connect(self.button_show_dir)
  145. self.timer_video.timeout.connect(self.show_video_frame)
  146. def init_logo(self):
  147. pix = QtGui.QPixmap('') # 绘制初始化图片
  148. self.label.setScaledContents(True)
  149. self.label.setPixmap(pix)
  150. def button_image_open(self):
  151. print('打开图片')
  152. name_list = []
  153. img_name, _ = QtWidgets.QFileDialog.getOpenFileName(
  154. self, "打开图片", "", "*.jpg;;*.png;;All Files(*)")
  155. if not img_name:
  156. return
  157. img = cv2.imread(img_name)
  158. print(img_name)
  159. showimg = img
  160. with torch.no_grad():
  161. img = letterbox(img, new_shape=self.imgsz)[0]
  162. # Convert
  163. # BGR to RGB, to 3x416x416
  164. img = img[:, :, ::-1].transpose(2, 0, 1)
  165. img = np.ascontiguousarray(img)
  166. img = torch.from_numpy(img).to(self.device)
  167. img = img.half() if self.half else img.float() # uint8 to fp16/32
  168. img /= 255.0 # 0 - 255 to 0.0 - 1.0
  169. if img.ndimension() == 3:
  170. img = img.unsqueeze(0)
  171. # Inference
  172. pred = self.model(img)[0]
  173. # Apply NMS
  174. pred = non_max_suppression(pred, self.conf_thres, self.iou_thres)
  175. # Process detections
  176. for i, det in enumerate(pred):
  177. if det is not None and len(det):
  178. # Rescale boxes from img_size to im0 size
  179. det[:, :4] = scale_coords(
  180. img.shape[2:], det[:, :4], showimg.shape).round()
  181. for *xyxy, conf, cls in reversed(det):
  182. label = '%s %.2f' % (self.names[int(cls)], conf)
  183. # print(label.split()[0]) # 打印各目标名称
  184. name_list.append(self.names[int(cls)])
  185. plot_one_box(xyxy, showimg, label=label,
  186. color=self.colors[int(cls)], line_thickness=2)
  187. cv2.imwrite('result/prediction.jpg', showimg)
  188. self.result = cv2.cvtColor(showimg, cv2.COLOR_BGR2BGRA)
  189. self.result = cv2.resize(self.result, (640, 480), interpolation=cv2.INTER_AREA)
  190. self.QtImg = QtGui.QImage(self.result.data, self.result.shape[1], self.result.shape[0], QtGui.QImage.Format_RGB32)
  191. self.label.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
  192. def button_video_open(self):
  193. video_name, _ = QtWidgets.QFileDialog.getOpenFileName(
  194. self, "打开视频", "", "*.mp4;;*.avi;;All Files(*)")
  195. if not video_name:
  196. return
  197. flag = self.cap.open(video_name)
  198. if flag == False:
  199. QtWidgets.QMessageBox.warning(
  200. self, u"Warning", u"打开视频失败", buttons=QtWidgets.QMessageBox.Ok, defaultButton=QtWidgets.QMessageBox.Ok)
  201. else:
  202. self.out = cv2.VideoWriter('result/vedio_prediction.avi', cv2.VideoWriter_fourcc(
  203. *'MJPG'), 20, (int(self.cap.get(3)), int(self.cap.get(4))))
  204. self.timer_video.start(30)
  205. self.pushButton_video.setDisabled(True)
  206. self.pushButton_img.setDisabled(True)
  207. self.pushButton_camera.setDisabled(True)
  208. def button_camera_open(self):
  209. if not self.timer_video.isActive():
  210. # 默认使用第一个本地camera
  211. flag = self.cap.open(0)
  212. if flag == False:
  213. QtWidgets.QMessageBox.warning(
  214. self, u"Warning", u"打开摄像头失败", buttons=QtWidgets.QMessageBox.Ok, defaultButton=QtWidgets.QMessageBox.Ok)
  215. else:
  216. self.out = cv2.VideoWriter('result/camera_prediction.avi', cv2.VideoWriter_fourcc(
  217. *'MJPG'), 20, (int(self.cap.get(3)), int(self.cap.get(4))))
  218. self.timer_video.start(30)
  219. self.pushButton_video.setDisabled(True)
  220. self.pushButton_img.setDisabled(True)
  221. self.pushButton_camera.setText(u"关闭摄像头")
  222. else:
  223. self.timer_video.stop()
  224. self.cap.release()
  225. self.out.release()
  226. self.label.clear()
  227. self.init_logo()
  228. self.pushButton_video.setDisabled(False)
  229. self.pushButton_img.setDisabled(False)
  230. self.pushButton_camera.setText(u"摄像头检测")
  231. def show_video_frame(self):
  232. name_list = []
  233. flag, img = self.cap.read()
  234. if img is not None:
  235. showimg = img
  236. with torch.no_grad():
  237. img = letterbox(img, new_shape=self.imgsz)[0]
  238. # Convert
  239. # BGR to RGB, to 3x416x416
  240. img = img[:, :, ::-1].transpose(2, 0, 1)
  241. img = np.ascontiguousarray(img)
  242. img = torch.from_numpy(img).to(self.device)
  243. img = img.half() if self.half else img.float() # uint8 to fp16/32
  244. img /= 255.0 # 0 - 255 to 0.0 - 1.0
  245. if img.ndimension() == 3:
  246. img = img.unsqueeze(0)
  247. # Inference
  248. pred = self.model(img)[0]
  249. # Apply NMS
  250. pred = non_max_suppression(pred, self.conf_thres, self.iou_thres)
  251. # Process detections
  252. for i, det in enumerate(pred): # detections per image
  253. if det is not None and len(det):
  254. # Rescale boxes from img_size to im0 size
  255. det[:, :4] = scale_coords(
  256. img.shape[2:], det[:, :4], showimg.shape).round()
  257. # Write results
  258. for *xyxy, conf, cls in reversed(det):
  259. label = '%s %.2f' % (self.names[int(cls)], conf)
  260. name_list.append(self.names[int(cls)])
  261. # print(label) # 打印各目标+置信度
  262. plot_one_box(
  263. xyxy, showimg, label=label, color=self.colors[int(cls)], line_thickness=2)
  264. self.out.write(showimg)
  265. show = cv2.resize(showimg, (640, 480))
  266. self.result = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)
  267. showImage = QtGui.QImage(self.result.data, self.result.shape[1], self.result.shape[0],
  268. QtGui.QImage.Format_RGB888)
  269. self.label.setPixmap(QtGui.QPixmap.fromImage(showImage))
  270. else:
  271. self.timer_video.stop()
  272. self.cap.release()
  273. self.out.release()
  274. self.label.clear()
  275. self.pushButton_video.setDisabled(False)
  276. self.pushButton_img.setDisabled(False)
  277. self.pushButton_camera.setDisabled(False)
  278. self.init_logo()
  279. def button_show_dir(self):
  280. path = os.getcwd() + '\\' + 'result'
  281. os.system(f"start explorer {path}")
  282. if __name__ == '__main__':
  283. app = QtWidgets.QApplication(sys.argv)
  284. app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
  285. ui = Ui_MainWindow()
  286. # 设置窗口透明度
  287. # ui.setWindowOpacity(0.93)
  288. # 去除顶部边框
  289. # ui.setWindowFlags(Qt.FramelessWindowHint)
  290. # 设置窗口图标
  291. icon = QIcon()
  292. icon.addPixmap(QPixmap("./UI/icon.ico"), QIcon.Normal, QIcon.Off)
  293. ui.setWindowIcon(icon)
  294. ui.show()
  295. sys.exit(app.exec_())

(三)打包exe

打包通常采用的是Pyinstaller这个工具库,本次打包使用一个新的工具叫Auto Py to Exe,该工具仍是调用Pyinstaller进行打包,不过对选项进行了可视化,操作更加便捷。

git clone https://github.com/brentvollebregt/auto-py-to-exe.git
python setup.py install 

1)git clone用法

1.这里有git clone用法,需要安装git,安装教程见本人图文安装教程

Git 安装图文教程_机械刘怀洋的博客-CSDN博客

2.进入项目文件夹,cmd打开终端输入上述命令

git clone GitHub - brentvollebregt/auto-py-to-exe: Converts .py to .exe using a simple graphical interface

3.安装好Auto Py to Exe后文件夹中出现setup.py

cmd进入文件夹后执行命令

python setup.py install

4.安装好之后,在终端输入auto-py-to-exe,报错没有No module named 'bottle'

安装缺失的包

再来一次,又报错

再次安装缺失的包,注意geventwebsocket库要这么安装

再来一次这次成了

脚本位置选择main.py,选择单目录模式,隐藏控制台,并选择图标和输出路径,然后就可以一键进行打包

这里提供一个下载.ico文件的网站

Free RemixIcon icons - Iconfinder

5.开始输出

点击convert开始输出,这需要一段时间

完成后会出现如下提示

6.可视化界面

输出的main文件中会出现一个main.exe,如下图

双击main.exe,发现报错,找不到权重文件

原来是在运行这个程序之前要先把下面这些文件夹丢进去

再次运行,已经成功

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/274703
推荐阅读
相关标签
  

闽ICP备14008679号