赞
踩
上篇文章,我们介绍了使用 PyQt5 打开图像,以及播放本地视频的实现方法。这篇文章,我们在此基础上讲解一下如何用 PyQt5 实现打开摄像头采集视频的功能。
先分析一下,要想实现打开摄像头,我们首先要建立 一个按钮 来打开摄像头,另外建立 一个按钮 用来关闭摄像头。更进一步,我们万一有多个摄像头,比如说笔记本的内置摄像头和外置相机,我们也可以建立一个可选择的 堆叠按钮,来做出选择。
首先将 label 拖到屏幕中央,并在左侧设计成合适的宽和高,用于显示视频数据。
这个label是透明的,为了方便展示,我们为它填充个黑色,呈现出一种幕布的感觉。
使用鼠标右击 label 中心,点击改变样式表;
点击添加颜色,background-color;
选择黑色,点击ok,之后再点击Apply,最后点击ok。
这样一个幕布就建好了。
做到这里基础界面就算完成了,将其保存,并使用PyUIC工具转化为.py文件,剩下的部分就剩编写逻辑代码了。
在显示视频方面,我们主要的思想就是通过点击“打开摄像头”按钮,来根据我们选择的相机类型,打开相应摄像头,点击”关闭摄像头“,直接就关闭相机。
首先是打开摄像头部分:
我们使用 timer.start() 来打开计时开关,用于播放视频。
self.CAM_NUM = 0 # 视频流 self.cap = cv2.VideoCapture() # 打开相机采集视频 def open_camera(self): # 获取选择的设备名称 index = self.comboBox.currentIndex() self.CAM_NUM = index # 检测该设备是否能打开 flag = self.cap.open(self.CAM_NUM) if flag is False: QMessageBox.information(self, "警告", "该设备未正常连接", QMessageBox.Ok) else: # 幕布可以播放 self.labe.setEnabled(True) # 打开摄像头按钮不能点击 self.pushButton.setEnabled(False) # 关闭摄像头按钮可以点击 self.pushButton_2.setEnabled(True) self.timer.start() self.timer.blockSignals(False)
然后是关闭摄像头部分:
我们使用 timer.stop() 来关闭计时器,进而关闭相机。
# 关闭相机
def close_camera(self):
self.cap.release()
self.pushButton.setEnabled(True)
self.pushButton_2.setEnabled(False)
self.timer.stop()
最后是播放视频及显示视频功能的实现部分:
将计时器与显示图像函数连接,当计时器运行时,则显示图像;当计时器关闭时,则不显示图像。
# 播放视频画面 def init_timer(self): self.timer = QTimer(self) self.timer.timeout.connect(self.show_pic) # 显示视频图像 def show_pic(self): ret, img = self.cap.read() if ret: cur_frame = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 视频流的长和宽 height, width = cur_frame.shape[:2] pixmap = QImage(cur_frame, width, height, QImage.Format_RGB888) pixmap = QPixmap.fromImage(pixmap) # 获取是视频流和label窗口的长宽比值的最大值,适应label窗口播放,不然显示不全 ratio = max(width/self.label.width(), height/self.label.height()) pixmap.setDevicePixelRatio(ratio) # 视频流置于label中间部分播放 self.label.setAlignment(Qt.AlignCenter) self.label.setPixmap(pixmap)
下面给出整体代码:
import sys from PyQt5.QtWidgets import QMessageBox, QFileDialog, QLineEdit from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * from ui_code.untitled import Ui_MainWindow import cv2 class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # UI界面 self.setupUi(self) self.CAM_NUM = 0 self.cap = cv2.VideoCapture() self.background() # 在label中播放视频 self.init_timer() def background(self): # 文件选择按钮 self.pushButton.clicked.connect(self.open_camera) self.pushButton_2.clicked.connect(self.close_camera) self.pushButton.setEnabled(True) # 初始状态不能关闭摄像头 self.pushButton_2.setEnabled(False) # 打开相机采集视频 def open_camera(self): # 获取选择的设备名称 index = self.comboBox.currentIndex() print(index) self.CAM_NUM = index # 检测该设备是否能打开 flag = self.cap.open(self.CAM_NUM) print(flag) if flag is False: QMessageBox.information(self, "警告", "该设备未正常连接", QMessageBox.Ok) else: # 幕布可以播放 self.label.setEnabled(True) # 打开摄像头按钮不能点击 self.pushButton.setEnabled(False) # 关闭摄像头按钮可以点击 self.pushButton_2.setEnabled(True) self.timer.start() print("beginning!") # 关闭相机 def close_camera(self): self.cap.release() self.pushButton.setEnabled(True) self.pushButton_2.setEnabled(False) self.timer.stop() # 播放视频画面 def init_timer(self): self.timer = QTimer(self) self.timer.timeout.connect(self.show_pic) # 显示视频图像 def show_pic(self): ret, img = self.cap.read() if ret: cur_frame = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 视频流的长和宽 height, width = cur_frame.shape[:2] pixmap = QImage(cur_frame, width, height, QImage.Format_RGB888) pixmap = QPixmap.fromImage(pixmap) # 获取是视频流和label窗口的长宽比值的最大值,适应label窗口播放,不然显示不全 ratio = max(width / self.label.width(), height / self.label.height()) pixmap.setDevicePixelRatio(ratio) # 视频流置于label中间部分播放 self.label.setAlignment(Qt.AlignCenter) self.label.setPixmap(pixmap) if __name__ == '__main__': app = QApplication(sys.argv) main = MainWindow() main.show() sys.exit(app.exec_())
这是代码运行结果,实现了摄像头采集视频功能。
该专栏博文地址:
界面开发(1) — PyQt5环境配置
界面开发(2)— 使用PyQt5制作用户登陆界面
界面开发(3)— PyQt5用户登录界面连接数据库
界面开发(4)— PyQt5实现打开图像及视频播放功能
界面开发(5)— PyQt5实现打开摄像头采集视频功能
奥比中光深度相机(一) — 环境配置
奥比中光深度相机(二) — PyQt5实现打开深度摄像头功能
日常学习记录,一起交流讨论吧!侵权联系~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。