python - 在 QLabel 元素中实时显示 CV2

标签 python opencv pyqt pyqt5 qthread

我目前正在为我使用 OpenCV 制作的监控系统编写 GUI。我想在设置框旁边的 QLabel 中查看实时视频输入,但我对发射/信号/插槽主题很陌生,所以我对代码顺序有点不知所措。 GUI 是从 QtCreator 转换过来的,只是为了让 Layout 正确。这些按钮还没有任何功能。 到目前为止,这是我的代码:

import sys
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *


#getting the live vid
class Thread(QThread):
    changePixmap = pyqtSignal(QImage)

    def run(self):
        cap1 = cv2.VideoCapture('single.mp4')
        while True:
            ret, frame = cap1.read()
            rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            cvt2qt = QImage(rgb_image.data, rgb_image.shape[1], rgb_image.shape[0], QImage.Format_RGB888)
            self.changePixmap.emit(cvt2qt)                         # I don't really understand this yet


class Ui_MainWindow(object):
    def setImage(self, image):
        self.label.setPixmap(QPixmap.fromImage(image))

    @pyqtSlot(QImage)                                              # I'm not sure about this function
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1280, 779)
        MainWindow.setMinimumSize(QtCore.QSize(920, 405))
        self.centralWidget = QtWidgets.QWidget(MainWindow)
        self.centralWidget.setMinimumSize(QtCore.QSize(400, 400))
        self.centralWidget.setBaseSize(QtCore.QSize(800, 600))
        self.centralWidget.setObjectName("centralWidget")

        # here is where I want to put the image.
        self.label = QtWidgets.QLabel(self.centralWidget)
        self.label.setGeometry(QtCore.QRect(10, 10, 881, 671))
        self.label.setScaledContents(True)
        self.label.setObjectName("label")
        th = Thread(self)                                           # Here is, where I struggle
        th.changePixmap.connect(self.setImage)
        th.start()
        MainWindow.setCentralWidget(self.centralWidget)

        self.dockWidget = QtWidgets.QDockWidget(MainWindow)
        self.dockWidget.setMinimumSize(QtCore.QSize(200, 0))
        self.dockWidget.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.dockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable)
        self.dockWidget.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea|QtCore.Qt.RightDockWidgetArea)
        self.dockWidget.setObjectName("dockWidget")

        self.dockWidgetContents = QtWidgets.QWidget()
        self.dockWidgetContents.setObjectName("dockWidgetContents")

        self.groupBox = QtWidgets.QGroupBox(self.dockWidgetContents)
        self.groupBox.setGeometry(QtCore.QRect(0, 30, 141, 281))
        self.groupBox.setMinimumSize(QtCore.QSize(90, 0))
        self.groupBox.setObjectName("groupBox")

        self.pushButton = QtWidgets.QPushButton(self.groupBox)
        self.pushButton.setGeometry(QtCore.QRect(10, 20, 121, 32))
        self.pushButton.setObjectName("pushButton")

        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_2.setGeometry(QtCore.QRect(10, 50, 121, 32))
        self.pushButton_2.setObjectName("pushButton_2")

        self.pushButton_3 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_3.setGeometry(QtCore.QRect(10, 80, 121, 32))
        self.pushButton_3.setObjectName("pushButton_3")

        self.radioButton = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton.setGeometry(QtCore.QRect(20, 120, 100, 20))
        self.radioButton.setObjectName("radioButton")

        self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_2.setGeometry(QtCore.QRect(20, 150, 100, 20))
        self.radioButton_2.setObjectName("radioButton_2")

        self.radioButton_3 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_3.setGeometry(QtCore.QRect(20, 180, 100, 20))
        self.radioButton_3.setObjectName("radioButton_3")
        self.dockWidget.setWidget(self.dockWidgetContents)
        MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dockWidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "ARCV"))
        self.groupBox.setTitle(_translate("MainWindow", "Settings"))
        self.pushButton.setText(_translate("MainWindow", "Start Recording"))
        self.pushButton_2.setText(_translate("MainWindow", "Stop Recording"))
        self.pushButton_3.setText(_translate("MainWindow", "Quit GUI"))
        self.radioButton.setText(_translate("MainWindow", "Camera 1"))
        self.radioButton_2.setText(_translate("MainWindow", "Camera 2"))
        self.radioButton_3.setText(_translate("MainWindow", "Camera 3"))


class Prog(QMainWindow):
    def __init__(self):
        super().__init__();
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

if __name__=='__main__':
    Program =  QApplication(sys.argv)
    MyProg = Prog()
    MyProg.show()
    sys.exit(Program.exec_())

我希望,你能帮助我。谢谢。 骑士

最佳答案

QThread 等待作为必须是 QObject 的父级的参数,在您的情况下,self 是 Ui_MainWindow 类的对象不继承自导致问题的QObject

我看到您正在实现一个名为 Prog 的类,您必须在其中执行逻辑而不是修改 Qt Designer 生成的代码。

因此,如果我们将逻辑移至该类,应该没有问题。

另一方面,装饰器@pyqtSlot 必须在连接到信号的函数中使用,你把它放在没有意义的构造函数中,它必须在 setImage().

import sys

import cv2

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1280, 779)
        MainWindow.setMinimumSize(QtCore.QSize(920, 405))
        self.centralWidget = QtWidgets.QWidget(MainWindow)
        self.centralWidget.setMinimumSize(QtCore.QSize(400, 400))
        self.centralWidget.setBaseSize(QtCore.QSize(800, 600))
        self.centralWidget.setObjectName("centralWidget")

        # here is where I want to put the image.
        self.label = QtWidgets.QLabel(self.centralWidget)
        self.label.setGeometry(QtCore.QRect(10, 10, 881, 671))
        self.label.setScaledContents(True)
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralWidget)

        self.dockWidget = QtWidgets.QDockWidget(MainWindow)
        self.dockWidget.setMinimumSize(QtCore.QSize(200, 0))
        self.dockWidget.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.dockWidget.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable)
        self.dockWidget.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea|QtCore.Qt.RightDockWidgetArea)
        self.dockWidget.setObjectName("dockWidget")

        self.dockWidgetContents = QtWidgets.QWidget()
        self.dockWidgetContents.setObjectName("dockWidgetContents")

        self.groupBox = QtWidgets.QGroupBox(self.dockWidgetContents)
        self.groupBox.setGeometry(QtCore.QRect(0, 30, 141, 281))
        self.groupBox.setMinimumSize(QtCore.QSize(90, 0))
        self.groupBox.setObjectName("groupBox")

        self.pushButton = QtWidgets.QPushButton(self.groupBox)
        self.pushButton.setGeometry(QtCore.QRect(10, 20, 121, 32))
        self.pushButton.setObjectName("pushButton")

        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_2.setGeometry(QtCore.QRect(10, 50, 121, 32))
        self.pushButton_2.setObjectName("pushButton_2")

        self.pushButton_3 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_3.setGeometry(QtCore.QRect(10, 80, 121, 32))
        self.pushButton_3.setObjectName("pushButton_3")

        self.radioButton = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton.setGeometry(QtCore.QRect(20, 120, 100, 20))
        self.radioButton.setObjectName("radioButton")

        self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_2.setGeometry(QtCore.QRect(20, 150, 100, 20))
        self.radioButton_2.setObjectName("radioButton_2")

        self.radioButton_3 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_3.setGeometry(QtCore.QRect(20, 180, 100, 20))
        self.radioButton_3.setObjectName("radioButton_3")
        self.dockWidget.setWidget(self.dockWidgetContents)
        MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dockWidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "ARCV"))
        self.groupBox.setTitle(_translate("MainWindow", "Settings"))
        self.pushButton.setText(_translate("MainWindow", "Start Recording"))
        self.pushButton_2.setText(_translate("MainWindow", "Stop Recording"))
        self.pushButton_3.setText(_translate("MainWindow", "Quit GUI"))
        self.radioButton.setText(_translate("MainWindow", "Camera 1"))
        self.radioButton_2.setText(_translate("MainWindow", "Camera 2"))
        self.radioButton_3.setText(_translate("MainWindow", "Camera 3"))


#getting the live vid
class Thread(QtCore.QThread):
    changePixmap = QtCore.pyqtSignal(QtGui.QImage)

    def __init__(self, *args, **kwargs):
        QtCore.QThread.__init__(self, *args, **kwargs)
        self.flag = False

    def run(self):
        cap1 = cv2.VideoCapture('single.mp4')
        self.flag = True
        while self.flag:
            ret, frame = cap1.read()
            if ret:
                rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                cvt2qt = QtGui.QImage(rgb_image.data, rgb_image.shape[1], rgb_image.shape[0], QtGui.QImage.Format_RGB888)
                self.changePixmap.emit(cvt2qt)                         # I don't really understand this yet

    def stop(self):
        self.flag = False


class Prog(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.th = Thread(self)
        self.th.changePixmap.connect(self.setImage)
        self.th.start()

    @QtCore.pyqtSlot(QtGui.QImage) 
    def setImage(self, image):
        self.label.setPixmap(QtGui.QPixmap.fromImage(image))

    def closeEvent(self, event):
        self.th.stop()
        self.th.wait()
        super().closeEvent(event)

if __name__=='__main__':
    Program =  QtWidgets.QApplication(sys.argv)
    MyProg = Prog()
    MyProg.show()
    sys.exit(Program.exec_())

关于python - 在 QLabel 元素中实时显示 CV2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50880850/

相关文章:

python - 在PyQt QThreads中同步事件

python - PyQt QTableView非英文字符排序问题

python - Groupby 来自另一个(相同行数)数据框的列

c++ - 奇怪的编译错误 c++ opencv 2.4.10 在 ubuntu 14.04lts

python - 如何在OPENCV python中从图像中删除背景灰色图纸

linux - 将已编译的 cmake 构建克隆到相同的硬件

python - PyQt5:使用谷歌字体

python - 如何验证 python 中没有调用模拟方法?

Python 生成用于 S3 上传的 AWS CLI 进程,但它变得非常慢

python - 从 unittest 测试调用时 argparse 失败