PyQt转换显示Python-OpenCV图像实现图形化界面的视频播放

一、引言

在Python-OpenCV中显示图像时调用的是一个单独的窗口,有时我们需要将这些图像显示在PyQt的图形化界面上,这样就可以将整个图像显示与PyQt图形化界面进行整合。但OpenCV格式的图像和PyQt格式的图像并不同,这就需要进行转换。

二、背景知识

  1. Python-OpenCV的图像是BGR格式的,而PyQt图像格式是RGB格式的,二者需要转换;

  2. 为了快速转换,图像必须基于内存进行操作;

  3. PyQt的QImage类可以从内存数组构建;

  4. OpenCV可以读取视频图像,使用waitKey可以实现休眠特定时长而不影响系统消息处理。

关于PyQt和OpenCV之间的图像转换请参考《Python-OpenCV中图像颜色空间转换》。

三、案例

下面的案例读取一个视频文件的图像进行显示,如果再叠加一个音频播放的功能,就实现了一个视频播放器。

3.1、设计图形化界面


该图形界面非常简单,包含了一个仅有“ShowImg”的菜单和对应工具栏,一个名为ImgDisp的标签对象用于显示图像(蓝色标记部分)。使用PyUIC生成的界面对象代码如下:

1`from PyQt5 import QtCore, QtGui, QtWidgets 2 3 4class Ui_MainWindow(object): 5 def setupUi(self, MainWindow): 6 MainWindow.setObjectName("MainWindow") 7 MainWindow.resize(625, 430) 8 self.centralwidget = QtWidgets.QWidget(MainWindow) 9 self.centralwidget.setObjectName("centralwidget") 10 self.ImgDisp = QtWidgets.QLabel(self.centralwidget) 11 self.ImgDisp.setGeometry(QtCore.QRect(0, 0, 54, 12)) 12 self.ImgDisp.setObjectName("ImgDisp") 13 MainWindow.setCentralWidget(self.centralwidget) 14 self.menubar = QtWidgets.QMenuBar(MainWindow) 15 self.menubar.setGeometry(QtCore.QRect(0, 0, 625, 17)) 16 self.menubar.setObjectName("menubar") 17 self.menushowImg = QtWidgets.QMenu(self.menubar) 18 self.menushowImg.setObjectName("menushowImg") 19 MainWindow.setMenuBar(self.menubar) 20 self.statusbar = QtWidgets.QStatusBar(MainWindow) 21 self.statusbar.setObjectName("statusbar") 22 MainWindow.setStatusBar(self.statusbar) 23 self.toolBar = QtWidgets.QToolBar(MainWindow) 24 self.toolBar.setObjectName("toolBar") 25 MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) 26 self.actionshowImg = QtWidgets.QAction(MainWindow) 27 self.actionshowImg.setObjectName("actionshowImg") 28 self.menushowImg.addAction(self.actionshowImg) 29 self.menubar.addAction(self.menushowImg.menuAction()) 30 self.toolBar.addAction(self.actionshowImg) 31 32 self.retranslateUi(MainWindow) 33 QtCore.QMetaObject.connectSlotsByName(MainWindow) 34 35 def retranslateUi(self, MainWindow): 36 _translate = QtCore.QCoreApplication.translate 37 MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 38 self.ImgDisp.setText(_translate("MainWindow", ".")) 39 self.menushowImg.setTitle(_translate("MainWindow", "menu")) 40 self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar")) 41 self.actionshowImg.setText(_translate("MainWindow", "showImg")) 42` 43 44* 45 46 47 48 49

3.2、主程序

1`import cv2,sys 2from PyQt5 import QtGui,QtWidgets,QtCore 3import mainWin 4 5def cvImgtoQtImg(cvImg): #定义opencv图像转PyQt图像的函数 6 QtImgBuf = cv2.cvtColor(cvImg, cv2.COLOR_BGR2BGRA) 7 8 QtImg = QtGui.QImage(QtImgBuf.data, QtImgBuf.shape[1], QtImgBuf.shape[0], QtGui.QImage.Format_RGB32) 9 10 return QtImg 11 12 13 14class mainwin(QtWidgets.QMainWindow,mainWin.Ui_MainWindow): 15 def __init__(self): 16 super().__init__() 17 self.setupUi(self) 18 self.bClose = False 19 20 self.actionshowImg.triggered.connect(self.playVideoFile) #建立菜单点击的信号与方法playVideoFile连接 21 22 def playVideoFile(self): #播放影片 23 cap = cv2.VideoCapture(r'f:\video\mydream.mp4') #打开影片 24 fps = 24 25 if not cap.isOpened(): 26 print("Cannot open Video File") 27 exit() 28 29 while not self.bClose: 30 ret, frame = cap.read() #逐帧读取影片 31 if not ret: 32 if frame is None: 33 print("The video has end.") 34 else: 35 print("Read video error!") 36 break 37 38 QtImg = cvImgtoQtImg(frame) #将帧数据转换为PyQt图像格式 39 self.ImgDisp.setPixmap(QtGui.QPixmap.fromImage(QtImg)) #在ImgDisp显示图像 40 size = QtImg.size() 41 self.ImgDisp.resize(size)#根据帧大小调整标签大小 42 self.ImgDisp.show() #刷新界面 43 cv2.waitKey(int(1000/fps)) #休眠一会,确保每秒播放fps帧 44 45 # 完成所有操作后,释放捕获器 46 cap.release() 47 48 49if __name__=='__main__': 50 app = QtWidgets.QApplication(sys.argv) 51 w = mainwin() 52 w.show() 53 sys.exit(app.exec_()) 54` 55 56* 57 58 59

注意:

本文的实现方法存在不足,相关完善方案请见《OpenCV-Python图像转换为PyQt图像的变形及花屏问题研究》。

3.3、运行程序

初始界面

点击showImg,开始播放视频:

关于PyQt的使用请参考付费专栏《使用PyQt开发图形界面Python应用》,专栏文件目录《使用PyQt开发图形界面Python应用专栏目录》。

也可以参考免费专栏《PyQt入门知识》,专栏文件目录《使用PyQt进行Python图形界面程序开发文章目录》。

关于老猿的付费专栏

老猿的付费专栏《使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,付费专栏《moviepy音视频开发专栏》详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,两个专栏加起来只需要19.9元,都适合有一定Python基础但无相关专利知识的小白读者学习。这2个收费专栏都有对应免费专栏,只是收费专栏的文章介绍更具体、内容更深入、案例更多。

收费专栏文章目录:《moviepy音视频开发专栏文章目录》、《使用PyQt开发图形界面Python应用专栏目录》。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《专栏:Python基础教程目录》从零开始学习Python。

如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

本文转转自微信公众号老猿Python原创https://mp.weixin.qq.com/s/oXjzDkYaR-Ke3K6zznXtkg,如有侵权,请联系删除。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

一篇文章带你了解JavaScript日期

日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用

vue+element 表格formatter数据格式化并且插入html标签

前言   vue中element框架,其中表格组件,我既要行内数据格式化,又要插入html标签一贯思维,二者不可兼得也一、element表格数据格式化  !(https://oscimg.oschina.net/oscnet/3c43a1cb3cbdeb5b5ad58acb45a42612b00.p