功能之间的同步

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

我正在使用python3和Qt库来构建我的Gui(pyqt5)。 在主Gui中,我有一个标签可以在其中放置一个图像,一个listWidget应该包含项目作为图标,lineEdit包含流的来源,以及一个按钮来启动我的应用程序。 我的目标是展示实时流媒体和实时分析。 为此,我使用QThread更新我的gui和多处理来进行分析。

这是我的代码:

class Stream(QThread):
    change_image_signal = pyqtSignal(QImage)

    def __init__(self, src, queue):
        QThread.__init__(self)
        self.stream = cv2.VideoCapture(src)
        self.queue = queue

    def run(self):
        frame_shift = 5
        frames_per_sec = 10
        sleep_time = 1 / frames_per_sec
        frame_count = 0
        while self.stream.isOpened():
            ret, frame = self.stream.read()
            frame_count += 1
            if not ret:
                break
            rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            if frame_count % (frame_shift + 1) == 0:
                self.queue.put(rgb_image)
            qt_format_image = QImage(rgb_image.data, rgb_image.shape[1], rgb_image.shape[0], 3 * rgb_image.shape[1],
                                     QImage.Format_RGB888)
            image = qt_format_image.scaled(400, 400)
            self.change_image_signal.emit(image)
            time.sleep(sleep_time)


class ThreadToListWidget(QThread):
    append_item_signal = pyqtSignal(QImage)

    def __init__(self, analyze_queue):
        QThread.__init__(self)
        self.analyze_queue = analyze_queue

    def run(self):
        while True:
            frame = self.analyze_queue.get()
            if frame is None:
                break
            qt_format_image = QImage(frame.data, frame.shape[1], frame.shape[0], 3 * frame.shape[1],
                                     QImage.Format_RGB888)
            image = qt_format_image.scaled(300, 300)
            self.append_item_signal.emit(image)


class AnalyzeProcess(multiprocessing.Process):
    def __init__(self, queue, analyze_queue):
        multiprocessing.Process.__init__(self)
        self.queue = queue
        self.analyze_queue = analyze_queue

    def run(self):
        while True:
            frame = self.queue.get()
            ...
                do analyzing to the frame
            ...
            self.analyze_queue.put(frame)
        self.analyze_queue.put(None)


class MyGui(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        ...
            my widgets:
                line_edit
                image_label
                list_widget
                button
        ...

        self.button.clicked.connect(self.start)

    def start(self):
        queue = multiprocessing.Queue()
        analyze_queue = multiprocessing.Queue()

        self.stream_thread = Stream(self.line_edit.text(), queue)
        self.stream_thread.change_image_signal.connect(self.change_image)

        self.list_widget_thread = ThreadToListWidget(analyze_queue)
        self.list_widget_thread.append_item_signal.connect(self.append_item)

        self.analyze_process = AnalyzeProcess(queue, analyze_queue)

        self.stream_thread.start()
        self.analyze_process.start()
        self.list_widget_thread.start()

    def change_image(self, image):
        self.image_label.setPixmap(QPixmap.fromImage(image))

    def append_item(self, image):
        pix = QPixmap.fromImage(image)
        icon = QIcon(pix)
        item = QListWidgetItem()
        item.setIcon(icon)
        self.list_widget.addItem(item)
        self.repaint()


if __name__ == 'main':
    app = QApplication(sys.argv)
    gui = MyGui()
    gui.show()
    app.exec_()

我的问题是,当我在列表小部件中添加项目时,标签中显示的实时流式传输冻结了一秒钟。 可以任何人告诉我我的代码有什么问题,如果这个问题,因为更新gui的函数之间没有同步?!

multiprocessing pyqt5 qthread
1个回答
0
投票

尝试将time.sleep(sleep_time)更改为QThread.msleep(10)

import sys
import cv2
import multiprocessing
#import time
from PyQt5.QtWidgets import *
from PyQt5.QtCore    import *
from PyQt5.QtGui     import *

class Stream(QThread):
    change_image_signal = pyqtSignal(QImage)

    def __init__(self, src, queue):
        QThread.__init__(self)

        self.stream = cv2.VideoCapture(src)
        self.queue = queue

    def run(self):
        frame_shift    = 5
#        frames_per_sec = 10
#        sleep_time     = 1 / frames_per_sec
        frame_count    = 0
        while self.stream.isOpened():
            ret, frame = self.stream.read()
            frame_count += 1
            if not ret:
                break
            rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            if frame_count % (frame_shift + 1) == 0:
                self.queue.put(rgb_image)
            qt_format_image = QImage(rgb_image.data, rgb_image.shape[1], rgb_image.shape[0], 3 * rgb_image.shape[1],
                                     QImage.Format_RGB888)
            image = qt_format_image.scaled(400, 400)
            self.change_image_signal.emit(image)

#            time.sleep(sleep_time)                               # ---
            QThread.msleep(10)                                    # +++


class ThreadToListWidget(QThread):
    append_item_signal = pyqtSignal(QImage)

    def __init__(self, analyze_queue):
        QThread.__init__(self)
        self.analyze_queue = analyze_queue

    def run(self):
        while True:
            frame = self.analyze_queue.get()
            if frame is None:
                break
            qt_format_image = QImage(frame.data, frame.shape[1], frame.shape[0], 3 * frame.shape[1],
                                     QImage.Format_RGB888)
            image = qt_format_image.scaled(300, 300)
            self.append_item_signal.emit(image)


class AnalyzeProcess(multiprocessing.Process):
    def __init__(self, queue, analyze_queue):
        multiprocessing.Process.__init__(self)
        self.queue = queue
        self.analyze_queue = analyze_queue

    def run(self):
        while True:
            frame = self.queue.get()
            #...
            #            "do analyzing to the frame"
            #...
            self.analyze_queue.put(frame)
        self.analyze_queue.put(None)


class MyGui(QWidget):
    def __init__(self):
        super().__init__()
#...
#   my widgets:
        self.line_edit   = QLineEdit("D:/_Qt/_PyQt/_Qt/Python-Examples/_PyQt5/Player/Samonastrojka.avi")
        self.image_label = QLabel()
        self.list_widget = QListWidget()
#        self.list_widget.resize(420, 300)
        self.list_widget.setFrameShape(self.list_widget.NoFrame) 
        self.list_widget.setFlow(self.list_widget.LeftToRight)   
        self.list_widget.setWrapping(True)                       
        self.list_widget.setResizeMode(self.list_widget.Adjust)
        self.button      = QPushButton("button")

        grid = QGridLayout(self)
        grid.addWidget(self.line_edit,   0, 0, 1, 2)
        grid.addWidget(self.image_label, 1, 0)
        grid.addWidget(self.list_widget, 1, 1)
        grid.addWidget(self.button, 2, 0, 1, 2)
#...
        self.button.clicked.connect(self.start)

    def start(self):
        queue = multiprocessing.Queue()
        analyze_queue = multiprocessing.Queue()

        self.stream_thread = Stream(self.line_edit.text(), queue)
        self.stream_thread.change_image_signal.connect(self.change_image)

        self.list_widget_thread = ThreadToListWidget(analyze_queue)
        self.list_widget_thread.append_item_signal.connect(self.append_item)

        self.analyze_process = AnalyzeProcess(queue, analyze_queue)

        self.stream_thread.start()
        self.analyze_process.start()
        self.list_widget_thread.start()

    def change_image(self, image):
        self.image_label.setPixmap(QPixmap.fromImage(image))

    def append_item(self, image):
        self.list_widget.setIconSize(QSize(70, 70)) 
        pix  = QPixmap.fromImage(image)
        icon = QIcon(pix.scaled(70, 70, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)) 
        item = QListWidgetItem()
        item.setIcon(icon)
        self.list_widget.insertItem(0, item)
        self.repaint()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    gui = MyGui()
    gui.resize(830, 480)
    gui.show()
    sys.exit(app.exec_())

enter image description here

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