Правильное использование почти идентичных Python QThreads и сигнала / слота - PullRequest
0 голосов
/ 29 января 2020

У меня есть GUI Я строю, что намереваюсь транслировать 3 камеры одновременно с использованием openCV. После долгого изучения я настроил правильное использование QThread и отдельных моделей в соответствии с MVC. Когда я писал код для GUI, я задавался вопросом, выполняю ли я больше работы, чем необходимо, имея отдельный слот и поток для каждого экземпляра камеры. Я знаю, что потоковое вещание только когда камера работает таким образом, но есть ли лучший способ для нескольких камер (в моем случае), которые имеют идентичные модели и потоки? Ниже приведен мой урезанный код, надеюсь, он объяснит, что я делаю.

class WorkerSignals(QObject):


    finished = pyqtSignal()
    error = pyqtSignal(tuple)
    result = pyqtSignal(object)
    progress = pyqtSignal(int)


class Camera(QObject):

    def __init__(self, cam_num):
        super(Camera, self).__init__()
        self.cam_num = cam_num
        self.cap = None
        self.record = False
        self.out = None
        self.signals = WorkerSignals()

    def initialize(self):
        self.cap = cv2.VideoCapture(self.cam_num)

    def convert_image(self, frame):
        rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        h, w, ch = rgbImage.shape
        bytesperline = ch*w
        converttoqt = QImage(rgbImage.data, w, h, bytesperline, 
            QImage.Format_RGB888)
        p = converttoqt.scaled(self.width, self.height)

        return p

    def run(self):
        self.running = True
        while self.running:
            ret, frame = self.cap.read()
            if ret:
                p = self.convert_image(frame)
                self.signals.result.emit(p)

            time.sleep(1/30)

    def close_camera(self):
        self.cap.release()
        if self.out:
            self.out.release()

    def __str__(self):
        return 'OpenCV Camera {}'.format(self.cam_num)

class MainWindow(QMainWindow):


    def __init__(self, cam1, cam2, cam3):
        super().__init__()
        self.cam1 = cam1  #Instance of class Camera
        self.cam2 = cam2
        self.cam3 = cam3

        self.cam1_thread = QThread()
        self.cam2_thread = QThread()
        self.cam3_thread = QThread()

        self.cam1.moveToThread(self.cam1_thread)
        self.cam2.moveToThread(self.cam2_thread)
        self.cam3.moveToThread(self.cam3_thread)

        self.cam1_thread.started.connect(self.cam1.run)
        self.cam2_thread.started.connect(self.cam2.run)
        self.cam3_thread.started.connect(self.cam3.run)

        self.central_widget = QWidget()
        self.cam1_image = QLabel()
        self.cam2_image = QLabel()
        self.cam3_image = QLabel()

        self.cam1.signals.result.connect(self.cam1_update_image)
        self.cam2.signals.result.connect(self.cam2_update_image)
        self.cam3.signals.result.connect(self.cam3_update_image)

    @pyqtSlot(QImage)
    def cam1_update_image(self, image):
        self.cam1_image.setPixmap(QPixmap.fromImage(image))

    @pyqtSlot(QImage)
    def cam2_update_image(self, image):
        self.cam2_image.setPixmap(QPixmap.fromImage(image))

    @pyqtSlot(QImage)
    def cam3_update_image(self, image):
        self.cam3_image.setPixmap(QPixmap.fromImage(image))
...