我正在使用Python构建一个面部考勤应用程序。我使用PyQt5
构建UI(在下面的代码中,PyQt5
和PyQt6
共享相同的语法),OpenCV (cv2)
获取网络摄像头帧,face_recognition
库编码和识别面部。为了保持GUI的响应性,我确实将一个具有面部识别功能的工人移动到另一个QThread
。
这是一个示例代码,可以解决我的问题:
WebcamThread
使用cv2.VideoCapture()
获取网络摄像头帧,并向主线程发出一些信号:ndarray_frame_signal
:返回numpy.ndarray
帧,由face_recognition
库处理,qimage_frame_signal
:返回QtGui.QImage
帧以显示在PyQt
GUI上。EncodeFaceThread
从队列中获取帧,并使用face_recognition
库执行一些任务。
from queue import Queue
from sys import argv
from cv2 import COLOR_BGR2RGB, VideoCapture, cvtColor
from face_recognition import compare_faces, face_encodings, face_locations
from numpy import ndarray
from time import sleep
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow
class WebcamThread(QThread):
ndarray_frame_signal = pyqtSignal(ndarray)
qimage_frame_signal = pyqtSignal(QImage)
def __init__(self):
super().__init__()
self.cap = VideoCapture(0)
def run(self):
while self.isRunning():
# Get current webcam frame and convert it to RGB
frame = cvtColor(self.cap.read()[1], COLOR_BGR2RGB)
self.ndarray_frame_signal.emit(frame)
# Convert `ndarray` frame to `QImage` frame
# and emit it to `qimage_frame_signal`
h, w, _ = frame.shape
qimage_frame = QImage(frame.data, w, h, QImage.Format.Format_RGB888)
self.qimage_frame_signal.emit(qimage_frame)
class EncodeFaceThread(QThread):
def __init__(self):
super().__init__()
self.known_encodings = []
self.queue = Queue()
def run(self):
while self.isRunning():
frame = self.queue.get()
f_locations = face_locations(frame)
# Only accept one face in a frame
if len(f_locations) != 1:
continue
f_encoding = face_encodings(frame, f_locations)[0]
# If this face encoding doesn't match any known encoding, add it
if not any(compare_faces(self.known_encodings, f_encoding)):
self.known_encodings.append(f_encoding)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# Setup UI (don't care about it)
self.setMinimumSize(660, 500)
self.image_display = QLabel(self)
self.image_display.setGeometry(10, 10, 640, 480)
# Initialize threads
self.webcam_thread = WebcamThread()
self.webcam_thread.ndarray_frame_signal.connect(self.push_in_queue)
self.webcam_thread.qimage_frame_signal.connect(self.display)
self.webcam_thread.start()
self.encode_face_thread = EncodeFaceThread()
self.encode_face_thread.start()
@pyqtSlot(ndarray)
def push_in_queue(self, frame):
self.encode_face_thread.queue.put(frame)
@pyqtSlot(QImage)
def display(self, frame):
qpixmap_frame = QPixmap.fromImage(frame)
self.image_display.setPixmap(qpixmap_frame)
app = QApplication(argv)
window = MainWindow()
window.show()
app.exec()
但是,由于EncodeFaceThread()
中face_recognition
库的处理,UI仍然缓慢和滞后。确实,当我像这样重写EncodeFaceThread
时,网络摄像头显示不再滞后。
class EncodeFaceThread(QThread):
def __init__(self):
super().__init__()
def run(self):
while self.isRunning():
# Do some long-running task
sleep(10)
那么,如何正确实现这个EncodeFaceThread
呢?
1条答案
按热度按时间kyvafyod1#
当然,下面是如何使用
face_recognition
库修改所提供的框架代码以包含face_locations
和face_encodings
任务:在此修改版本中,
EncodeFaceThread
接收QImage帧,将其转换为numpy数组,然后使用face_recognition
库执行face_locations
和face_encodings
任务。请记住,根据您的应用需求处理检测和识别结果。此外,QTimer
用于控制线程的处理频率,以避免消耗过多的CPU资源。