为什么单独线程中的“ face_recognition”包会减慢UI线程的速度?

问题描述 投票:0回答:1

我正在尝试开发具有面部识别功能的Pyqt应用程序。对于人脸识别,我使用python软件包face_recognition。为了使UI保持响应,我确实将具有面部识别功能的工作人员移动到了另一个QThread。但是,UI仍然非常呆滞和落后。为了检查是否在实现多线程过程中出错,我确实用一个长的活动等待循环替换了面部识别部分,如下所示:

原始人脸识别代码:

face_recognition.face_locations(frame, model="hog")

已替换为活动的等待循环:

for x in range(59999999):
    pass

但是,在这种情况下,用户界面反应非常快。因此相关部分确实在另一个线程上。但是,当我将其替换为面部识别时,为什么UI线程会滞后?

[我也曾尝试将UI线程的优先级设置为QThread.TimeCriticalPriority(最高),将工作线程的优先级设置为QThread.IdlePriority(最低),但这实际上没有效果。

编辑:

这里是一个最小的示例,在这里我也可以观察到这种行为。虽然滞后不如我的实际应用程序那么大,但在调整窗口大小时仍然很明显。但是,我必须将特定的QWidget(例如ScrollArea或LineEdit)添加到UI。否则(例如仅显示标签)调整大小是平滑的。

#!/usr/bin/env python3

import sys, cv2, face_recognition
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog
from PyQt5.QtCore import QThread, QObject, pyqtSlot

class MainWindow(QMainWindow):
  def __init__(self):
    super().__init__()
    self.setup_test_ui()
    self.open_file()
    # QThread.currentThread().setPriority(QThread.TimeCriticalPriority)

  def setup_test_ui(self):
    self.centralwidget = QtWidgets.QWidget(self)
    self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget)
    self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
    self.scrollArea.setWidgetResizable(True)
    self.lineEdit = QtWidgets.QLineEdit(self.scrollArea)
    self.scrollArea.setWidget(self.lineEdit)
    self.verticalLayout_2.addWidget(self.scrollArea)
    self.setCentralWidget(self.centralwidget)

  def open_file(self):
    file_name, _ = QFileDialog.getOpenFileName(self, "Open video", "", "All Files (*);;Movie Files (*.mp4 *.avi)")
    if (file_name):
      self.setup_worker(file_name)

  def setup_worker(self, *args, **kwargs):
    worker = Worker(*args, **kwargs)
    thread = QThread()
    self.worker = (worker, thread)
    worker.moveToThread(thread)
    thread.started.connect(worker.work)

    thread.start()
    # thread.start(QThread.IdlePriority) 

class Worker(QObject):
  def __init__(self, video_source=0, *args, **kwargs):
    super().__init__(*args, **kwargs)

    self.vid = cv2.VideoCapture(video_source)
    if not self.vid.isOpened():
      raise ValueError("Unable to open video source", video_source)

  @pyqtSlot()
  def work(self):
    while (True):
      ret, frame = self.vid.read()
      if ret:
        # for x in range(59999999):
        #   pass
        face_locations = face_recognition.face_locations(frame, model="hog")

app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())

注意:确保安装所有依赖项:OpenCV,PyQt5,人脸识别。对于最后一个,您可能必须提前编译dlib(遵循these instructions)。然后启动应用程序,使用任何视频文件作为face_recognition的输入并调整窗口大小(这对我来说有点滞后)。然后,您可以编辑work方法,并使用活动的等待循环代替face_recognition行。现在执行应用程序时,调整大小非常敏感。

python multithreading pyqt pyqt5
1个回答
0
投票

因此,在尝试了一些东西之后,看来问题确实出在Pythons GIL上。使用单独的进程而不是线程,程序可以按预期工作,并且UI保持响应。

© www.soinside.com 2019 - 2024. All rights reserved.