【问题标题】:synchronization between functions函数之间的同步
【发布时间】:2019-02-15 08:48:47
【问题描述】:

我正在使用带有 Qt 库的 python3 来构建我的 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】:

    尝试将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_())
    

    【讨论】:

      猜你喜欢
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 2015-10-30
      • 1970-01-01
      • 2019-03-26
      • 1970-01-01
      相关资源
      最近更新 更多