【问题标题】:Display camera stream in a QLabel在 QLabel 中显示相机流
【发布时间】:2013-11-30 11:48:01
【问题描述】:

我想使用 python OpenCV 绑定在 QLabel 中显示网络摄像头流。我在这里找到了一些以前的帖子:

一开始我尝试了一个简单的“while”循环:

def onRun(self):
    self.playing = True
    capture = cv2.VideoCapture(0)
    while self.playing:
        _, data = capture.read()
        data = cv2.cvtColor(data, cv2.cv.CV_BGR2RGB)
        qImage = QtGui.QImage(data, data.shape[1], data.shape[0], 
            QtGui.QImage.Format_RGB888)
        self.lblImage.setPixmap(QtGui.QPixmap.fromImage(qImage))
        self.lblImage.adjustSize()
        time.sleep(0.02)

但我遇到了“白窗”问题。我发现解决这个问题的正确方法是创建一个新线程。我的问题是:关于新线程的全部内容是什么?我应该创建 QThread 还是什么?它在线程中发出的信号/插槽是什么?

我从未使用过线程,所以这对我来说是全新的。

【问题讨论】:

  • 您可能想在此处阅读有关 Markdown 的工作原理以及如何格式化帖子的信息。 :-) 另外,我们已经有一个标签字段,不需要在标题中重复它们。
  • 抱歉我的格式和标题 - 这是我第一次来这里,下次我会记住的:)

标签: python multithreading opencv webcam pyside


【解决方案1】:

我自己无法对此进行测试,但是仅处理循环中的待处理事件还不够吗?

即:

def onRun(self):
    self.playing = True
    capture = cv2.VideoCapture(0)
    while self.playing:
        ...
        QtGui.qApp.processEvents()
        time.sleep(0.02)

【讨论】:

    【解决方案2】:

    解决方案是使用 pyqtSignal。这是一个例子:

    import time
    from PyQt5.QtCore import pyqtSignal, pyqtSlot
    from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
    from PyQt5.QtGui import QPixmap, QImage
    import sys
    import threading
    import numpy as np
    
    
    class FakeCamera(QWidget):
        """Simulate a camera"""
        image_taken = pyqtSignal(np.ndarray)
    
        def __init__(self, callback, time_cost=0.01, image_shape=(256, 256)):
            super(FakeCamera, self).__init__()
            self.time_cost = time_cost  # the time cost to take a frame, determine the frame rate
            self.image_shape = image_shape
            self.image_taken.connect(callback)
            self._stop = threading.Event()
    
        def start(self):
            """start a thread to take images"""
    
            def run():
                while not self._stop.is_set():
                    time.sleep(self.time_cost)
                    image = np.random.randint(0, 256, self.image_shape, np.uint8)
                    self.image_taken.emit(image)
    
            threading.Thread(target=run).start()
    
        def stop(self):
            self._stop.set()
    
    
    class WindowDemo(QWidget):
        def __init__(self):
            super(WindowDemo, self).__init__()
    
            # label
            self.label = QLabel()
            self.label.setScaledContents(True)
            self.label.setMinimumSize(1, 1)
            # layout
            vbox = QVBoxLayout()
            vbox.addWidget(self.label)
            self.setLayout(vbox)
            # camera
            self.camera = FakeCamera(self.show_image)
            # start a thread to take images
            self.camera.start()
    
        @pyqtSlot(np.ndarray)
        def show_image(self, image):
            qimage = QImage(image, image.shape[1], image.shape[0], QImage.Format_Grayscale8)
            self.label.setPixmap(QPixmap.fromImage(qimage))
    
        def closeEvent(self, e):
            self.camera.stop()
            e.accept()
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        win = WindowDemo()
        win.show()
        sys.exit(app.exec_())
    
    

    【讨论】:

      猜你喜欢
      • 2012-07-09
      • 2020-05-02
      • 1970-01-01
      • 2016-09-22
      • 1970-01-01
      • 2012-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多