一、概述
在PyQt中,可以使用QCamera、QCameraViewfinder、QCameraViewfinderSettings等一系列多媒体操作相关类实现摄像头操作。用这些类不足50行代码+UI界面就可以快速实现简单的摄像头拍照。
二、相关类介绍
2.1、QCamera类
QCamera类是直接对应摄像头的类,包括如下方法:
1、QCamera()
创建摄像头类对象实例。
2、setViewfinder(viewfinder)
设置取景器,取景器就是将图像实时在屏幕显示,就跟相机的屏幕一样,参数是取景器类的实例对象。
3、setViewfinderSettings(viewFinderSettings)
设置取景器相关参数如分辨率等,请见QCameraViewfinderSettings类的介绍。
4、setCaptureMode(mode)
设置捕获图像(拍照)的保存模式,参数mode类型为枚举类型QCamera.CaptureModes,包括如下取值:
※ CaptureViewfinder:相机仅配置为显示取景器
※ CaptureStillImage:相机配置为静态帧捕获
※ CaptureVideo:相机配置为视频捕获
以上三个值可以通过or操作组合起来使用,经老猿验证,如果是拍照以上三个值都支持,CaptureVideo在windows系列操作系统下不支持。
5、start()打开相机
相机打开后取景器就能显示镜头范围内的内容。
6、stop()关闭相机
关闭相机后,取景器不再显示视频。
2.2、QCameraViewfinderSettings类
QCameraViewfinderSettings类是专门用于设置取景器参数的,常用的设置方法(读取方法名去掉set后首字母改为小写就可以了)如下:
1、setResolution(width,height)
以像素为单位设置取景器的分辨率。
2、setPixelAspectRatio(int horizontal, int vertical)
设置取景器的纵横比
3、setMinimumFrameRate(qreal rate)
设置取景器的最小帧速率(以每秒帧数为单位)
4、setMaximumFrameRate(qreal rate)
设置取景器的最大帧速率(以每秒帧数为单位)
5、setPixelFormat(QVideoFrame.PixelFormat format)
设置取景器图像的像素格式,即在内存中的存放格式(或编码方式),其类型为枚举类型enum QVideoFrame.PixelFormat,取值范围如下:
以上方法不需要都使用,具体看应用的要求。
2.3、QCameraViewfinder类
QCameraViewfinder类是取景器对应类,这个类主要的方法就是构造方法,带一个参数指向取景器放置的父对象,不过多介绍。
2.4、QCameraImageCapture类
QCameraImageCapture是用于捕获图像的,主要有如下方法:
1、setCaptureDestination(CaptureDestinations destination)
setCaptureDestination方法设置捕获的图像是输出到文件还是在内存中缓存,参数destination是枚举类型CaptureDestinations ,有如下2个取值:
*※ CaptureToFile:对应值为 1,表示输出到文件
*※ CaptureToBuffer:,对应值为2,表示输出到缓存,可以在缓存中进一步处理
2、capture( QString filename )
capture从当前视频中捕获一帧作为图像保存,保存到参数指定的文件中。
三、实现步骤
3.1、设计界面
通过Qt Designer设计界面如下,窗口为QMainWindow(也可以为QWidget):
在该界面上有两个按钮用于操作,一个GroupBox用于在内存放取景器界面,同时设计了多个布局,为了取景器显示在安排的位置,且能正常显示,在GroupBox内放了一个名字为camerLayout水平布局。
3.2 设计信号和槽的连接
在两个按钮的clicked信号上各自连接了一个槽函数,分别为switchCamera(相机的开关)和takePic(拍照),如图:
3.3、通过PyUIC生成界面代码
将设计的界面保存到CamerWin.ui中,按照《第15.7节 PyQt入门学习:PyQt5应用构建详细过程介绍》将界面生成代码CamerWin.py,对应的界面类为Ui_CameraWin。
3.4、从界面类派Ui_CameraWin生子类
3.4.1、从界面类及QMainWindow派生自定义类CameraMainWin
class CameraMainWin(QtWidgets.QMainWindow,CameraWin.Ui_CameraWin):
注意:如窗口是QWidget类,则要将QMainWindow换为QWidget。
3.4.2、定义CameraMainWin的构造方法
构造方法首先要执行标准化的自定义类构造必须执行代码以完成界面初始化:
super(CameraMainWin, self).__init__()
self.setupUi(self)
然后完成QCamera对象、取景器参数对象、取景器对象、图像捕获对象的定义和初始化:
self.camera = QCamera()
self.camera.setCaptureMode(QCamera.CaptureViewfinder)
self.cameraOpened = False# 设置相机打开状态为未打开
#设置取景器分辨率
viewFinderSettings = QCameraViewfinderSettings ()
viewFinderSettings.setResolution(800,600)
self.camera.setViewfinderSettings(viewFinderSettings)
#初始化取景器
self.viewCamera = QtMultimediaWidgets.QCameraViewfinder(self)
self.camera.setViewfinder(self.viewCamera)
self.camerLayout.addWidget(self.viewCamera) #取景器放置到预留的布局中
#设置图像捕获
self.capImg = QCameraImageCapture(self.camera )
self.capImg.setCaptureDestination(QCameraImageCapture.CaptureToFile)
注意:在构造方法中将取景器放置到了预留的布局中
3.4.3、定义槽函数switchCamera执行相机的开关处理
def switchCamera(self):
if not self.cameraOpened :
self.camera.start() #打开相机
self.cameraOpened = True
self.btnSwitchCamera.setText("关闭摄像头")
else:
self.camera.stop() #关闭相机
self.cameraOpened = False
self.btnSwitchCamera.setText("打开摄像头")
3.4.4、定义槽函数takePic执行拍照
def takePic(self):#拍照响应槽函数,照片保存到文件
FName = fr"c: empcapimgcap{time.strftime('%Y%m%d%H%M%S', time.localtime())}" #文件名初始化
self.capImg.capture(FName)
print(f"捕获图像保存到文件:{FName}.jpg")
3.4.5、主代码中创建自定义类实例并打开窗口
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
W = CameraMainWin()
W.show()
sys.exit(app.exec_())
四、完整的主程序代码
主程序完整代码才46行,如下:
import time,sys
from PyQt5 import QtWidgets,QtMultimediaWidgets
from PyQt5.QtMultimedia import QCamera,QCameraImageCapture,QCameraViewfinderSettings
import CameraWin
class CameraMainWin(QtWidgets.QMainWindow,CameraWin.Ui_CameraWin):
def __init__(self):
super(CameraMainWin, self).__init__()
self.setupUi(self)
#定义相机实例对象并设置捕获模式
self.camera = QCamera()
self.camera.setCaptureMode(QCamera.CaptureViewfinder)
self.cameraOpened = False# 设置相机打开状态为未打开
#设置取景器分辨率
viewFinderSettings = QCameraViewfinderSettings ()
viewFinderSettings.setResolution(800,600)
self.camera.setViewfinderSettings(viewFinderSettings)
#初始化取景器
self.viewCamera = QtMultimediaWidgets.QCameraViewfinder(self)
self.camera.setViewfinder(self.viewCamera)
self.camerLayout.addWidget(self.viewCamera) #取景器放置到预留的布局中
#设置图像捕获
self.capImg = QCameraImageCapture(self.camera )
self.capImg.setCaptureDestination(QCameraImageCapture.CaptureToFile) #CaptureToBuffer
#相机(摄像头)开关处理
def switchCamera(self):
if not self.cameraOpened :
self.camera.start()
self.cameraOpened = True
self.btnSwitchCamera.setText("关闭摄像头")
else:
self.camera.stop()
self.cameraOpened = False
self.btnSwitchCamera.setText("打开摄像头")
def takePic(self):#拍照响应槽函数,照片保存到文件
FName = fr"c: empcapimgcap{time.strftime('%Y%m%d%H%M%S', time.localtime())}" #文件名初始化
self.capImg.capture(FName)
print(f"捕获图像保存到文件:{FName}.jpg")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
W = CameraMainWin()
W.show()
sys.exit(app.exec_())
五、运行截图
运行后开启摄像头后的界面如下:
另外如果没有将取景器放到对应布局中,则运行界面会如下:
可以看到取景器已经缩小到左上角黄色荧光笔标记的角落。
六、小结
本节详细介绍了PyQt中使用QCamera类实现使用电脑摄像头拍照的步骤及相关类,通过不到50行代码就实现了相关功能。当然如果要做功能更完善的代码还可以有许多方面的功能需要实现,包括取景器、相机、图像等都有更多的可以设置的参数,几个类还有些信号如error信号、状态变更信号等可以定义槽函数响应。
另外需要说明的一点是,通过PyQt的多媒体操作类QMediaRecorder可以捕获视频流,但该类只能在安卓或Mac操作系统下使用,windows下不能使用。详细请参考官网相关说明(https://doc.qt.io/qt-5/qtmultimedia-windows.html)。