上篇文章,我们介绍了使用 PyQt5 打开图像,以及播放本地视频的实现方法。这篇文章,我们在此基础上讲解一下如何用 PyQt5 实现打开摄像头采集视频的功能。
先分析一下,要想实现打开摄像头,我们首先要建立 一个按钮 来打开摄像头,另外建立 一个按钮 用来关闭摄像头。更进一步,我们万一有多个摄像头,比如说笔记本的内置摄像头和外置相机,我们也可以建立一个可选择的 堆叠按钮,来做出选择。
首先将 label 拖到屏幕中央,并在左侧设计成合适的宽和高,用于显示视频数据。
这个label是透明的,为了方便展示,我们为它填充个黑色,呈现出一种幕布的感觉。
使用鼠标右击 label 中心,点击改变样式表;
选择黑色,点击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实现打开摄像头采集视频功能
日常学习记录,一起交流讨论吧!侵权联系~