title: Why does "face_recognition" package in seperate thread slow down the UI thread?
body: <p>I'm trying to develop a Pyqt application with face recognition. For the face recognition I use the python package <a href="https://github.com/ageitgey/face_recognition" rel="nofollow noreferrer">face_recognition</a>. To keep the UI responsive, I did move a worker with the face recognition to another QThread. However, the UI is still extremly sluggish and lagging.
  To check, whether I made a mistake implementing multithreading, I did then replace the face recognition part with a long active waiting loop, like this:</p>
  
  <p>Original face recognition code:</p>
  
  <pre><code>face_recognition.face_locations(frame, model="hog")
  </code></pre>
  
  <p>Replaced with active waiting loop:</p>
  
  <pre><code>for x in range(59999999):
      pass
  </code></pre>
  
  <p>However in this case, the UI was very responsive. So the relevant part is indeed on another thread. But why is the UI thread lagging when I replace it with the face recognition?</p>
  
  <p>I also did try to set the priority of the UI thread to <code>QThread.TimeCriticalPriority</code> (highest) and the priority of the worker to <code>QThread.IdlePriority</code> (lowest) but this did not really have an effect.</p>
  
  <h2>EDIT:</h2>
  
  <p>Here is a minimal example where I also can observe this behavior. While, the lagging is not as much as in my real application, it's still noticeable here when resizing the window. However, I had to add specific QWidgets like ScrollArea or LineEdit to the UI. Otherwise (e.g. only showing a label) the resizing was smooth.</p>
  
  <pre><code>#!/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())
  </code></pre>
  
  <p><strong>Note:</strong> Make sure to install all dependencies: OpenCV, PyQt5, face-recognition. For the last one, you likely have to compile dlib in advance (follow <a href="https://stackoverflow.com/a/49538054/10264920">these instructions</a>). Then start the application, use any video file which is used as input for the face_recognition and resize the window (it's lagging a bit for me). Then you can edit the <code>work</code> method and use the active waiting loop instead of the face_recognition line. When executing the application now, resizing is very responsive.</p>