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

Karen110
• 阅读 1766

一、引言

在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、设计图形化界面

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

`from PyQt5 import QtCore, QtGui, QtWidgets  


class Ui_MainWindow(object):  
    def setupUi(self, MainWindow):  
        MainWindow.setObjectName("MainWindow")  
        MainWindow.resize(625, 430)  
        self.centralwidget = QtWidgets.QWidget(MainWindow)  
        self.centralwidget.setObjectName("centralwidget")  
        self.ImgDisp = QtWidgets.QLabel(self.centralwidget)  
        self.ImgDisp.setGeometry(QtCore.QRect(0, 0, 54, 12))  
        self.ImgDisp.setObjectName("ImgDisp")  
        MainWindow.setCentralWidget(self.centralwidget)  
        self.menubar = QtWidgets.QMenuBar(MainWindow)  
        self.menubar.setGeometry(QtCore.QRect(0, 0, 625, 17))  
        self.menubar.setObjectName("menubar")  
        self.menushowImg = QtWidgets.QMenu(self.menubar)  
        self.menushowImg.setObjectName("menushowImg")  
        MainWindow.setMenuBar(self.menubar)  
        self.statusbar = QtWidgets.QStatusBar(MainWindow)  
        self.statusbar.setObjectName("statusbar")  
        MainWindow.setStatusBar(self.statusbar)  
        self.toolBar = QtWidgets.QToolBar(MainWindow)  
        self.toolBar.setObjectName("toolBar")  
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)  
        self.actionshowImg = QtWidgets.QAction(MainWindow)  
        self.actionshowImg.setObjectName("actionshowImg")  
        self.menushowImg.addAction(self.actionshowImg)  
        self.menubar.addAction(self.menushowImg.menuAction())  
        self.toolBar.addAction(self.actionshowImg)  

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

    def retranslateUi(self, MainWindow):  
        _translate = QtCore.QCoreApplication.translate  
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))  
        self.ImgDisp.setText(_translate("MainWindow", "."))  
        self.menushowImg.setTitle(_translate("MainWindow", "menu"))  
        self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))  
        self.actionshowImg.setText(_translate("MainWindow", "showImg"))  
`

*     




3.2、主程序

`import cv2,sys  
from PyQt5 import QtGui,QtWidgets,QtCore  
import mainWin  

def cvImgtoQtImg(cvImg): #定义opencv图像转PyQt图像的函数  
    QtImgBuf = cv2.cvtColor(cvImg,  cv2.COLOR_BGR2BGRA)  

    QtImg = QtGui.QImage(QtImgBuf.data, QtImgBuf.shape[1], QtImgBuf.shape[0], QtGui.QImage.Format_RGB32)  

    return QtImg  



class mainwin(QtWidgets.QMainWindow,mainWin.Ui_MainWindow):  
    def __init__(self):  
        super().__init__()  
        self.setupUi(self)  
        self.bClose = False  

        self.actionshowImg.triggered.connect(self.playVideoFile) #建立菜单点击的信号与方法playVideoFile连接  

    def playVideoFile(self): #播放影片  
        cap = cv2.VideoCapture(r'f:\video\mydream.mp4') #打开影片  
        fps = 24  
        if not cap.isOpened():  
            print("Cannot open Video File")  
            exit()  

        while not self.bClose:  
            ret, frame = cap.read() #逐帧读取影片  
            if not ret:  
                if frame is None:  
                    print("The video has end.")  
                else:  
                    print("Read video error!")  
                break  

            QtImg = cvImgtoQtImg(frame)  #将帧数据转换为PyQt图像格式  
            self.ImgDisp.setPixmap(QtGui.QPixmap.fromImage(QtImg)) #在ImgDisp显示图像  
            size = QtImg.size()   
            self.ImgDisp.resize(size)#根据帧大小调整标签大小  
            self.ImgDisp.show() #刷新界面  
            cv2.waitKey(int(1000/fps)) #休眠一会,确保每秒播放fps帧  

        # 完成所有操作后,释放捕获器  
        cap.release()  


if __name__=='__main__':  
    app = QtWidgets.QApplication(sys.argv)  
    w = mainwin()  
    w.show()  
    sys.exit(app.exec_())  
`

*     


注意:

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

3.3、运行程序

初始界面

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

点击showImg,开始播放视频:
PyQt转换显示Python-OpenCV图像实现图形化界面的视频播放

关于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,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
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
Easter79 Easter79
2年前
vue+element 表格formatter数据格式化并且插入html标签
前言   vue中element框架,其中表格组件,我既要行内数据格式化,又要插入html标签一贯思维,二者不可兼得也一、element表格数据格式化  !(https://oscimg.oschina.net/oscnet/3c43a1cb3cbdeb5b5ad58acb45a42612b00.p
Karen110 Karen110
2年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
Karen110 Karen110
2年前
OpenCV-Python图像转换为PyQt图像的变形及花屏无法正常显示问题研究
☞░ 前往老猿Python博文目录 ░一、引言在《PyQt转换显示PythonOpenCV图像实现图形化界面的视频播放》介绍了实现在OpenCV和PyQt之间转换并传递图像实现在PyQt上播放视频图像的功能。其中的关键函数如下:defcvImgtoQtImg(cvImg):定义opencv图像转PyQt图像的函数QtImgBufcv2.
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Django之Django模板
1、问:html页面从数据库中读出DateTimeField字段时,显示的时间格式和数据库中存放的格式不一致,比如数据库字段内容为2012082616:00:00,但是页面显示的却是Aug.26,2012,4p.m.答:为了页面和数据库中显示一致,需要在页面格式化时间,需要添加<td{{dayrecord.p\_time|date:
Stella981 Stella981
2年前
Opencv与Qt (一)之运行测试读取图片
刚刚在vs上装好了QT和Opencv,试一下效果把。我简单的创建了一个label,然后使用Opencv导入图像,因为Opencv导入图像是MAT格式的,在使用Qt的时候我们要把导入的图像转换成Qimage类型的。所以,我写了一个转换函数。QImageQtGuiApplication1::cvMat2QImage(constMat&m
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这