zoukankan      html  css  js  c++  java
  • pyqt5开发(2-1)界面+显示视频+多线程

     

    功能:

    使用多线程采集视频刷新主窗口,完成跨线程通信。

     采用队列传图

     

    说明:

    1为什么不用qt本身的信号和槽函数实现或者Qthread?

    这个也是可以实现的,但是考虑学习的通用性,例如将来不用qt写界面或者其他嵌入式设备部署(树莓派+英伟达开发板),这套机制也是可以复用的。这样将会很灵活不用局限于QT本身拥有的东西,使用队列可以自己灵活增加数据类型。2线程配合队列完成跨线程通信。

    2注意线程锁的使用。

    3尝试使用进程代替线程,失败了,入口错误?

      为什么要用进程,像树莓派好像使用多线程是无效的,实际还是在一个线程跑,使用多进程才是分开了加速。

      进程也会带来问题,队列跨进程之后里所表示的数据将无法识别问题。

    实现过程

    1首先搭建环境

    https://www.cnblogs.com/kekeoutlook/p/13964523.html

    2创建工程

    目录文件只有3个

    2-1激活环境

    activate py37_tfgpu1131_keras215_opencv341
    

    2-2创建界面

      运行

    designer
    

     生成一个新界面.ui

    一个 lable显示视频和两个按钮

    布局 整体栅格布局  两个局部水平布局

    默认布局-是初始化给多大就是多大,不会随着窗口自适应变大

     保存成 .ui文件

    转换成py文件

    python -m PyQt5.uic.pyuic .输入名字.ui -o .输出名字.py
    

    生成的界面布局结果

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file '.UI_vedio.ui'
    #
    # Created by: PyQt5 UI code generator 5.15.1
    #
    # WARNING: Any manual changes made to this file will be lost when pyuic5 is
    # run again.  Do not edit this file unless you know what you are doing.
    
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(800, 600)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
            self.horizontalLayoutWidget.setGeometry(QtCore.QRect(50, 20, 691, 441))
            self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
            self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
            self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
            self.horizontalLayout.setObjectName("horizontalLayout")
            self.label = QtWidgets.QLabel(self.horizontalLayoutWidget)
            self.label.setObjectName("label")
            self.horizontalLayout.addWidget(self.label)
            self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.centralwidget)
            self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(50, 470, 691, 80))
            self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
            self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
            self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
            self.horizontalLayout_2.setObjectName("horizontalLayout_2")
            self.pushButton_1 = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
            self.pushButton_1.setObjectName("pushButton_1")
            self.horizontalLayout_2.addWidget(self.pushButton_1)
            self.pushButton_2 = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
            self.pushButton_2.setObjectName("pushButton_2")
            self.horizontalLayout_2.addWidget(self.pushButton_2)
            MainWindow.setCentralWidget(self.centralwidget)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
            self.label.setText(_translate("MainWindow", "视频流"))
            self.pushButton_1.setText(_translate("MainWindow", "开始播放"))
            self.pushButton_2.setText(_translate("MainWindow", "结束播放"))
    

      

     

    主程序

    import sys
    from PyQt5.QtWidgets import QApplication,QMainWindow,QFileDialog
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5 import QtWidgets, QtCore, QtGui
    
    #导入图像库
    import cv2
    
    #进程测试
    #import multiprocessing
    
    #线程测试
    import threading
    from queue import Queue
    
    #导入自己创建的图形类
    from UI_vedio import *
    
            
    
    #一个是这个类本身的,一个是这个类继承
    class Example(QMainWindow,Ui_MainWindow):
    
        def __init__(self):
            #类的初始化
            super(Example, self).__init__()
            self.setupUi(self)#界面控件初始化
     
            #相机线程初始化
            self.CAM_Int()
           
            #按钮绑定函数
            self.pushButton_1.clicked.connect(self.on_video)  #开始按键
           
           
        #按键函数
        def on_video(self):      
            if self.open_flag:
                self.pushButton_1.setText('关闭视频')
                self.open_flag=bool(0)
            
                
                
            else:       
                self.pushButton_1.setText('开始播放')
                self.open_flag=bool(1)        
            #self.open_flag = bool(1-self.open_flag)#
            self.lock.acquire()#获得锁
            if self.qcontrol.full():
                self.qcontrol.get()
            self.qcontrol.put(self.open_flag)
            self.lock.release()#释放锁
    
             
            
        def CAM_Int(self):
            #控制信号量
            self.open_flag=1
            self.qcontrol = Queue(1)         #用于主线程控制播放线程控制信号
            self.qcontrol.put(self.open_flag)
            self.qframe =Queue(2)           #用于主线程读取次线程图像数据
            
            #创建播放线程
            self.CAM_Play()
        
    
        def CAM_Play(self):
    
            
            #开启线程
            self.lock = threading.Lock()
            self.t1_video = threading.Thread(target=self.videogo, args=(self.qcontrol,self.qframe,self.lock))
            self.t1_video.start()
            
    
            #多进程报错
            '''
            self.lock=multiprocessing.Lock()
            p1=multiprocessing.Process(target=self.videogo,args=(self.qcontrol,self.qframe,self.lock,))
            p1.daemon = True
            p1.start()
            '''
             
            
            #定时器20毫秒更新画板
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.CAM_SetImage)  
            self.timer.start(20) #单位为毫秒
            
        #配合定时器刷新图像显示
        def CAM_SetImage(self):
            if self.qframe.empty():
                pass
            else:
                image=self.qframe.get()
                self.label.setPixmap(QPixmap.fromImage(image))
            
        def videogo(self,qcontrol,qframe,lock):
            cap = cv2.VideoCapture(0)
            cap.set(cv2.CAP_PROP_FRAME_WIDTH,800)
            cap.set(cv2.CAP_PROP_FRAME_HEIGHT,600)
            cap.set (cv2.CAP_PROP_FPS,25)
           
            while (cap.isOpened()==True):
    
                
                #判断是否需要开启或者关闭
                if bool(1-qcontrol.empty()):         
                    go=qcontrol.get()
                    print(go)
                    if go:
                        pass
                    else:
                        break
                        pass
                   
                
                
                ret, frame = cap.read()  
                if ret:
                    rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                    convertToQtFormat = QtGui.QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888)#在这里可以对每帧图像进行处理,
                    qtimg = convertToQtFormat.scaled(600, 600, Qt.KeepAspectRatio)
                  
                    lock.acquire()#获取锁
                    if qframe.full():#如果满了就清空一帧
                        qframe.get()                 
                    qframe.put(qtimg)
                    lock.release()# 释放锁 
                  
                else:
                    continue
    
    
    
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)     
        ui=Example()  
        ui.show()
        sys.exit(app.exec_())
    
        
    

      

    运行程序

     python .4UI_Video_thread_queue.py
    

      

  • 相关阅读:
    总结c#和javascript中常见的相关的"空"
    javascript从未如此流行(JavaScript has never been so popular .)
    解决ajax调用中ie的缓存问题
    《.NET框架程序设计》第5章 基元类型、引用类型与值类型
    DataTable复制到新的DataTable并筛选
    《.NET框架程序设计》第1章 .NET开发平台体系架构 读后感
    《.NET框架程序设计》第4章 类型基础 读后感
    《.NET框架程序设计》第2章 第3章 读后感
    《道德经》程序员版第四十二章
    数据库设计总结
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/13995568.html
Copyright © 2011-2022 走看看