如何使用 PyQt5 QThread 从 CLASS(ShowVideo) 中获取值以在第二个 CLASS(ImageViewer) 中使用(根据我的程序)

Posted

技术标签:

【中文标题】如何使用 PyQt5 QThread 从 CLASS(ShowVideo) 中获取值以在第二个 CLASS(ImageViewer) 中使用(根据我的程序)【英文标题】:How to fetch value from a CLASS(ShowVideo) to use in second CLASS(ImageViewer) (according to my program) by using PyQt5 QThread 【发布时间】:2019-11-20 08:28:23 【问题描述】:

我正在尝试检索 x 的值,即是来自 ShowVideo 类的计数器,并在 ImageViewer 类的按钮中显示计数器。视频运行完美,但我没有了解如何在视频开始运行时显示计数器的逻辑。所有函数应该同时工作,这里i 作为变量是在showVideo 类下的函数startVideo() 中声明的计数器名称。我想更新按钮上的值,即 button_in(class ImageViewer, method InitUI()) 作为计数器。

'''

import cv2
import numpy as np
import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5.QtCore import pyqtSignal,QRect,QThread
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap

filenameOpen =0

class ShowVideo(QtCore.QObject):# its only running a videooo

    camera = cv2.VideoCapture(filenameOpen)

    VideoSignal = QtCore.pyqtSignal(QtGui.QImage)


#############################################
    # newValue=QtCore.pyqtSignal(int)
    # stopped= pyqtSignal()
#################################################    
    def __init__(self, parent = None):
        # super(ShowVideo, self).__init__(parent)
        super().__init__()

    @QtCore.pyqtSlot()
    def startVideo(self):

        run_video = True
        #     self.counterThread.startVideo()QImage
        x=0
        while run_video:
            # ret, image = self.camera.read()
            ret, image = self.camera.read()
            height, width, channels = image.shape
            frame=image.copy()
            frameClone = frame.copy()       
            # frame = cv2.resize(frame, (1920, 1080))

            color_swapped_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            height, width, _ = color_swapped_image.shape


            qt_image = QtGui.QImage(color_swapped_image.data,
                                    width, 
                                    height,
                                    color_swapped_image.strides[0],
                                    QtGui.QImage.Format_RGB888)                    
            self.VideoSignal.emit(qt_image) 
            # return x
            # print(x)
            # x=x+1

class ImageViewer(QtWidgets.QMainWindow):
    def __init__(self, parent = None):
        super().__init__()
        left=0
        top=0
        width=1920
        height=1080
        iconName="icon.png"
        self.setWindowIcon(QtGui.QIcon(iconName))
        self.setGeometry(left,top,width,height)
        self.image = QtGui.QImage()
        self.initUI()
        self.show()

    def initUI(self):
        self.setWindowTitle('Emotion Analysis')
        button_video = QPushButton(self)
        button_file = QPushButton(self)
        button_play = QPushButton(self)
        self.button_in=QPushButton(self)
        button_out=QPushButton(self)
        button_total=QPushButton(self)
        self.button_stop = QPushButton(self)
        self.label_image=QLabel(self)
        label_image_blank=QLabel(self)
        label_in=QLabel(self)
        label_out=QLabel(self)
        label_total=QLabel(self)    

        # button definations>>>>>>>>>>>>>>>>>>>>
        button_video.setGeometry((QRect(10,30,90,65)))# syntax(x,y,<>,^)
        button_video.setIcon(QtGui.QIcon("securitycamera.png"))
        button_video.setIconSize(QtCore.QSize(50,50))
        # button.setToolTip("This is Click Me Button")
        button_video.setToolTip("<h4>Live Stream<h4>")
        button_video.clicked.connect(vid.startVideo)

        button_file.setGeometry((QRect(110,30,90,65)))# syntax(x,y,<>,^)
        button_file.setIcon(QtGui.QIcon("file.png"))
        button_file.setIconSize(QtCore.QSize(50,50))
        button_file.setToolTip("<h4>Add new connection<h4>")
        button_file.clicked.connect(QtWidgets.qApp.quit) # this line is also working condition, the quit() method is defined above 

        button_play.setGeometry((QRect(1710,30,90,65)))# syntax(x,y,<>,^)
        # button_play.setGeometry((QRect(1710,300,90,65)))# syntax(x,y,<>,^)
        button_play.setIcon(QtGui.QIcon("play_red.png"))
        button_play.setIconSize(QtCore.QSize(50,50))
        button_play.setToolTip("<h4>Play video<h4>")
        button_play.clicked.connect(vid.startVideo)

        self.button_stop.setGeometry((QRect(1820,30,90,65)))# syntax(x,y,<>,^)
        self.button_stop.setIcon(QtGui.QIcon("stop.png"))
        self.button_stop.setIconSize(QtCore.QSize(50,50))
        self.button_stop.setToolTip("<h4>Stop Video<h4>")
        self.button_stop.clicked.connect(QApplication.instance().quit)
#############################################################
        self.button_in.setGeometry((QRect(1710,500,90,45)))# syntax(x,y,<>,^)
        self.button_in.setText("0")# it should be updated while counter runs
        # self.button_in.setText(x)
        self.button_in.setFont(QtGui.QFont("Sanserif",20))

        # self.counterThread=QThread()
        # self.counter=ShowVideo()
        # self.counter.moveToThread(self.counterThread)
        # self.button_in.clicked.connect(self.startCounting)
        # self.vid.newValue.connect(self.button_in.setText)
        # self.counterThread.started.connect(self.counter.startVideo)





#####################################################################
        button_out.setGeometry((QRect(1710,550,90,45)))# syntax(x,y,<>,^)
        button_out.setText("0")
        button_out.setFont(QtGui.QFont("Sanserif",20))

        button_total.setGeometry((QRect(1710,600,90,45)))# syntax(x,y,<>,^)
        button_total.setText("0")
        button_total.setFont(QtGui.QFont("Sanserif",20))


        # label definations>>>>>>>>>>>>>>>>>>>>

        self.label_image.setGeometry((QRect(10,110,1500,900))) # syntax(x,y,<>,^)
        self.label_image.setPixmap(QPixmap("black.jpg"))
        self.label_image.setScaledContents(True)

        label_in.setGeometry((QRect(1600,500,100,50))) # syntax(x,y,<>,^)
        label_in.setText("In")
        label_in.setFont(QtGui.QFont("Sanserif",20))

        label_out.setGeometry((QRect(1600,550,100,50))) # syntax(x,y,<>,^)
        label_out.setText("Out")
        label_out.setFont(QtGui.QFont("Sanserif",20))

        label_total.setGeometry((QRect(1600,600,100,50))) # syntax(x,y,<>,^)
        label_total.setText("Total")
        label_total.setFont(QtGui.QFont("Sanserif",20))     

    @QtCore.pyqtSlot(QtGui.QImage)
    def setImage(self, image):
        self.label_image.setPixmap(QPixmap.fromImage(image))
        # self.vid.newValue.connect(self.button_in.setText)



    # @QtCore.pyqtSlot(int)
    # def startCounting(self,x):
    # #     # if not self.counterThread.isRunning():
    # #     #     self.counterThread.startVideo()
    # #     # pass
    #     self.vid.newValue.connect(self.button_in.setText)

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    thread = QtCore.QThread() #thread declareation
    thread.start()
    vid = ShowVideo() # calling 1st class
    vid.moveToThread(thread)
    image_viewer = ImageViewer() #calling second class 
    vid.VideoSignal.connect(image_viewer.setImage)  
    # vid.VideoSignal.connect(image_viewer.startCounting)   
    sys.exit(app.exec_()) '''

【问题讨论】:

不要为了吸引注意力而用噪音编辑您的问题。 【参考方案1】:

可能最简单的方法是在ShowVideo.startVedio 中发射ShowVideo.VideoSignal 并将vid.VideoSignal 连接到image_viewer.setText 时随图像一起发射帧号,即

class ShowVideo(QtCore.QObject):

    VideoSignal = QtCore.pyqtSignal(QtGui.QImage, int)

    ....

    @QtCore.pyqtSlot()
    def startVideo(self):

        ....

        x += 1
        self.VideoSignal.emit(qt_image, x)

....

if __name__ == '__main__':

    ....

    vid.VideoSignal.connect(lambda img, frame: image_viewer.button_in.setText(str(frame)) )

【讨论】:

与计数器配合良好,但相机已开启但无法运行视频

以上是关于如何使用 PyQt5 QThread 从 CLASS(ShowVideo) 中获取值以在第二个 CLASS(ImageViewer) 中使用(根据我的程序)的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5 QThread 不会因终止或标志变量而停止

PyQt5 - 如何在使用 QThread 时减少 CPU 使用率(低于 50%)?

PyQt5:使用 QObject 和 QThread 时出现 AttributeError

PyQt5 OpenCV 网络摄像头使用 QThread

在 PyQt5 中取消 QThread

PyQt5 - 使用QThread更新Qtablewidget