У меня есть проект, в котором мне нужно создать gui
в qt
. Этот дизайн содержит виджет, где live video feed
будет отображаться с веб-камеры USB, используя opencv
. Этот проект обнаружит faces
и также распознает их, что означает, что на каждом кадре будет происходить большая обработка.
Для этого я создал поток, который инициализирует камеру и принимает кадры из него с помощью opencv. Затем он помещает весь кадр в очередь, и эта очередь затем читается функцией update_frame
, которая в основном отображает кадр в виджете qt. Это работает нормально без задержки.
Внутри функции update_frame
я добавил face detection
, из-за чего она работала очень медленно. Поэтому я создал другой поток start_inferencing
, который в основном читает кадр из queue
, и после обнаружения лица он снова помещает кадр в другую очередь q2
, которая затем читается update_frame
, и он отображает, но все еще реагирует очень медленно. Ниже приведен код:
q = queue.Queue()
q2 = queue.Queue()
def grab(cam, qu, width, height):
global running
capture = cv2.VideoCapture(cam)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, width)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
while running:
frame = {}
capture.grab()
ret_val, img = capture.retrieve(0)
frame["img"] = img
if qu.qsize() < 100:
qu.put(frame)
else:
print(qu.qsize())
class Logic(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
set_initial_alert_temp()
self.window_width = self.ImgWidget.frameSize().width()
self.window_height = self.ImgWidget.frameSize().height()
self.ImgWidget = OwnImageWidget(self.ImgWidget)
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.update_frame)
self.timer.start(1)
self.outside_temp_text_box.setText(str(curr_temp_cel))
def update_frame(self):
if not q2.empty():
frame1 = q2.get()
img = frame1["img"]
img_height, img_width, img_colors = img.shape
scale_w = float(self.window_width) / float(img_width)
scale_h = float(self.window_height) / float(img_height)
scale = min([scale_w, scale_h])
if scale == 0:
scale = 1
img = cv2.resize(img, None, fx=scale, fy=scale, interpolation=cv2.INTER_CUBIC)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
height, width, bpc = img.shape
bpl = bpc * width
image = QtGui.QImage(img.data, width, height, bpl, QtGui.QImage.Format_RGB888)
self.ImgWidget.setImage(image)
def start_inferencing():
while True:
if not q.empty():
frame = q.get()
img = frame["img"]
face_bbox = face.detect_face(img)
if face_bbox is not None:
(f_startX, f_startY, f_endX, f_endY) = face_bbox.astype("int")
f_startX = f_startX + 10
f_startY = f_startY + 10
f_endX = f_endX - 10
f_endY = f_endY - 10
cv2.rectangle(img, (f_startX, f_startY), (f_endX, f_endY), (0, 255, 0), 2)
frame1 = {"img": img}
if q2.qsize() < 100:
q2.put(frame1)
else:
print(q2.qsize())
def main():
capture_thread = threading.Thread(target=grab, args=(0, q, 640, 480))
capture_thread.start()
infer_thread = threading.Thread(target=start_inferencing)
infer_thread.start()
app = QtWidgets.QApplication(sys.argv)
w = Logic(None)
w.setWindowTitle('Test')
w.show()
app.exec_()
main()
Ниже приведено краткое описание того, что происходит в коде:
camera -> frame -> queue.put # (reading frame from camera and putting it in queue)
queue.get -> frame -> detect face -> queue2.put # (getting frame from queue, detecting face in it and putting the updated frames in queue2)
queue2.get -> frame -> display it on qt widget # (getting frame from queue2 and display it on qt widget)
Основная причина медленной подачи живого видео состоит в том, что кадр Функция read in grab
не может обрабатывать быстрее, и, таким образом, размер queue
постоянно увеличивается, и поэтому он в целом становится очень медленным. Есть ли какой-нибудь хороший подход, который я могу использовать, который может обнаружить лицо, а также показать его без каких-либо задержек. Пожалуйста помоги. Спасибо