PyQt5摄像头的使用--摄像头操作概述及使用摄像头拍照

1、功能概述
PyQt5多媒体模块为摄像头操作提供了几个类,可以用于获取摄像头设备信息,通过摄像头进行拍照和录像。

Qt多媒体模块的功能实现是依赖于平台的。在Windows平台上,Qt多媒体模块依赖于两个插件:一个是使用Microsoft DirectShow API的插件,DirectShow在Windows 98引入,在Windows XP以后就逐渐过时了;另一个是Windows Media Foundation(WMF)的插件,WMF插件在Windows Vista引入,用于替代DirectShow。

Qt中的WMF插件目前无法提供摄像头支持,对摄像头的有限支持是由DirectShow插件提供的,目前只能显示取景器和抓取静态图片,其他大部分功能不支持。所以,目前在Windows平台上,Qt的摄像头控制不支持视频录制功能,也不支持底层的视频功能,例如使用QVideoProbe探测视频帧。

PyQt5的多媒体模块在Windows平台上也无法实现摄像头录像功能。

2、主要类与函数
++++++++++++++++++++++++++++
QCameraInfo:摄像头设备信息类

availableCameras():返回QCameraInfo类型的列表,表示系统可用的摄像头。

defaultCamera():返回一个QCameraInfo对象,是系统默认的摄像头设备信息。

description():返回摄像头设备描述。

deviceName():返回摄像头设备名称。

position():返回值是枚举类型QCamera.Position,表示摄像头的位置。
例如手机一般有两个摄像头,前置摄像头位置类型为QCamera.FrontFace,后置摄像头位置类型为QCamera.BackFace,未指定位置的是QCamera.UnspecifiedPosition。
++++++++++++++++++++++++++++
QCamera:操作摄像头的类,创建QCamera对象时需传递一个QCameraInfo对象作为参数。

setViewfinder(viewfinder):为摄像头指定一个QVideoWidget或QGraphicsVideoItem对象viewfinder作为取景器,用于摄像头图像预览。一般使用一个QCameraViewfinder类对象用于摄像头预览,其父类是QVideoWidget。

setCaptureMode(mode):用于设置摄像头工作模式,参数mode是枚举类型QCamera. CaptureModes,有以下几种取值:
QCamera.CaptureViewfinder(取景器模式,摄像头仅用于预览);
QCamera.CaptureStillImage(抓取静态图片模式);
QCamera.CaptureVideo(视频录制模式)。

isCaptureModeSupported(mode),判断摄像头是否支持某种工作模式,参数mode是枚举类型QCamera.CaptureModes。

searchAndLock():拍照之前执行,用于在快门半按下时锁定摄像头的曝光、白平衡等参数

unlock():拍照后执行,用于解除锁定。
++++++++++++++++++++++++++++
QCameraImageCapture:控制摄像头进行静态图片的抓取

setEncodingSettings(settings):设置拍照图片的编码,settings是QImageEncoderSettings类型,设置内容包括编码方案、分辨率、图片质量等。

setBufferFormat(format):设置拍照缓冲区的图片的格式,参数format是枚举类型QVideoFrame.PixelFormat,有几十种取值,这里用QVideoFrame.Format_Jpeg,也就是使用JPEG格式。

setCaptureDestination(destination):用于设置所拍摄图片的保存方式,destination是枚举类型QCameraImageCapture.CaptureDestination,有以下两种取值:
QCameraImageCapture.CaptureToBuffer(拍摄的图片保存在缓冲区里,会发射信号
imageCaptured(),在此信号的槽函数里可以提取缓冲区中的图片); - QCameraImageCapture.CaptureToFile(拍摄的图片自动保存文件到用户目录的“图片”
文件夹里,保存图片后会发射imageSaved()信号)。 如果设置为CaptureToBuffer,就只会发射imageCaptured()信号,图片出现在缓冲区,不会自动保存为文件,也不会发射imageCaptured()信号;而如果设置为CaptureToFile,两个信号都会被发射。

QCameraImageCapture的3个信号及关联的槽函数的作用如下。

readyForCaptureChanged(ready):信号在摄像头是否可以拍照的状态变化时发射,bool型参数ready正好用于控制拍照按钮的使能状态。

imageCaptured(imageID, preview)在图像被抓取到缓冲区后发射,imageID是图像的编号,每次拍照时自动累加,preview是QImage类型,是拍摄的图片。在关联的槽函数里,将此图片的内容显示到界面上的QLabel组件LabImage上。

imageSaved(imageID, fileName)信号在图片保存为文件后发射,fileName是自动保存的文件名称。在关联的槽函数里显示了imageID和文件名fileName。
++++++++++++++++++++++++++++
QMediaRecorder:通过摄像头和音频输入设备进行视频录制

3、代码实现
在这里插入图片描述
这个窗口工作区的左侧是摄像头预览显示,是一个QCameraViewfinder组件,右侧是拍摄照片的显示,是一个QLabel组件。两个GroupBox组件之间使用了分割布局。

from PyQt5.QtGui import QImage,QPixmap
from PyQt5.QtMultimedia import (QCameraInfo,QCameraImageCapture,
      QImageEncoderSettings,QMultimedia,QVideoFrame,QSound,QCamera)
from ui_MainWindow import Ui_MainWindow

class QmyMainWindow(QMainWindow): 

   def __init__(self, parent = None):
      super().__init__(parent)    #调用父类构造函数,创建窗体
      self.ui = Ui_MainWindow()     #创建UI对象
      self.ui.setupUi(self)       #构造UI界面

      self.__LabCameraState = QLabel("摄像头state:")
      self.__LabCameraState.setMinimumWidth(150)
      self.ui.statusBar.addWidget(self.__LabCameraState)

      self.__LabImageID = QLabel("图片文件ID:") 
      self.__LabImageID.setMinimumWidth(100)
      self.ui.statusBar.addWidget(self.__LabImageID)

      self.__LabImageFile = QLabel("")   #保存的图片文件名
      self.ui.statusBar.addPermanentWidget(self.__LabImageFile)

      self.camera = None   #QCamera对象
      cameras = QCameraInfo.availableCameras()  #list[QCameraInfo]
      if len(cameras)>0:
         self.__iniCamera()       #初始化摄像头
         self.__iniImageCapture() #初始化静态画图
         self.camera.start()

##  ==============自定义功能函数========================
   def __iniCamera(self):   ##创建 QCamera对象
      camInfo=QCameraInfo.defaultCamera()    #获取缺省摄像头,QCameraInfo
      self.ui.comboCamera.addItem(camInfo.description())    #摄像头描述
      self.ui.comboCamera.setCurrentIndex(0)

      self.camera=QCamera(camInfo)  #创建摄像头对象
      self.camera.setViewfinder(self.ui.viewFinder)   #设置取景框预览
   ##          camera.setCaptureMode(QCamera.CaptureViewfinder) #预览
      self.camera.setCaptureMode(QCamera.CaptureStillImage)  #设置为抓图
   ##          camera.setCaptureMode(QCamera.CaptureVideo)

      mode=QCamera.CaptureStillImage
      supported=self.camera.isCaptureModeSupported(mode)
      self.ui.checkStillImage.setChecked(supported) #支持拍照

      supported=self.camera.isCaptureModeSupported(QCamera.CaptureVideo)
      self.ui.checkVideo.setChecked(supported)     #支持视频录制

      supported=self.camera.exposure().isAvailable()
      self.ui.checkExposure.setChecked(supported) #支持曝光补偿
      
      supported=self.camera.focus().isAvailable()
      self.ui.checkFocus.setChecked(supported)    #支持变焦
      
      self.camera.stateChanged.connect(self.do_cameraStateChanged)

   def __iniImageCapture(self):  ##创建 QCameraImageCapture对象
      self.capturer = QCameraImageCapture(self.camera)
      settings=QImageEncoderSettings()    #拍照设置
      settings.setCodec("image/jpeg")     #设置抓图图形编码
      settings.setResolution(640, 480)    #分辨率
      settings.setQuality(QMultimedia.HighQuality)    #图片质量
      self.capturer.setEncodingSettings(settings) 

      self.capturer.setBufferFormat(QVideoFrame.Format_Jpeg)   #缓冲区格式

      if self.ui.chkBoxSaveToFile.isChecked():
         dest=QCameraImageCapture.CaptureToFile    #保存到文件
      else:
         dest=QCameraImageCapture.CaptureToBuffer  #保存到缓冲区
      self.capturer.setCaptureDestination(dest)    #保存目标
      
      self.capturer.readyForCaptureChanged.connect(self.do_imageReady)
      
      self.capturer.imageCaptured.connect(self.do_imageCaptured)
      
      self.capturer.imageSaved.connect(self.do_imageSaved)
      
##  ==============event处理函数==========================
        
        
##  ==========由connectSlotsByName()自动连接的槽函数============        
   @pyqtSlot(bool)   ##设置保存方式
   def on_chkBoxSaveToFile_clicked(self,checked):
      if checked:
         dest=QCameraImageCapture.CaptureToFile    #保存到文件
      else:
         dest=QCameraImageCapture.CaptureToBuffer  #保存到缓冲区
      self.capturer.setCaptureDestination(dest)    #保存目标

   @pyqtSlot()   ##拍照
   def on_actCapture_triggered(self): 
      QSound.play("shutter.wav")    #播放快门音效
      self.camera.searchAndLock()   #快门半按下时锁定摄像头参数
      self.capturer.capture()       #拍照
      self.camera.unlock()          #快门按钮释放时解除锁定

   @pyqtSlot()   ##打开摄像头
   def on_actStartCamera_triggered(self):
      self.camera.start()

   @pyqtSlot()  ##关闭摄像头
   def on_actStopCamera_triggered(self):
      self.camera.stop()
      
   
        
   ##  =============自定义槽函数===============================        
   def do_cameraStateChanged(self,state):    ##摄像头状态变化
      if (state==QCamera.UnloadedState):
         self.__LabCameraState.setText("摄像头state: UnloadedState")
      elif (state==QCamera.LoadedState):
         self.__LabCameraState.setText("摄像头state: LoadedState")
      elif (state==QCamera.ActiveState):
         self.__LabCameraState.setText("摄像头state: ActiveState")
         
      self.ui.actStartCamera.setEnabled(state!=QCamera.ActiveState)
      self.ui.actStopCamera.setEnabled(state==QCamera.ActiveState)

   def do_imageReady(self,ready):   ##是否可以拍照了
      self.ui.actCapture.setEnabled(ready)

   def do_imageCaptured(self,imageID,preview): ##图片被抓取到内存
                                          #preview是 QImage
      H=self.ui.LabImage.height()
      W=self.ui.LabImage.width()
      
      scaledImage = preview.scaled(W,H,
                        Qt.KeepAspectRatio, Qt.SmoothTransformation)
      self.ui.LabImage.setPixmap(QPixmap.fromImage(scaledImage))
      self.__LabImageID.setText("图片文件ID:%d"%imageID)
      self.__LabImageFile.setText("图片保存为: ")

   def do_imageSaved(self,imageID,fileName):    ##图片被保存
      self.__LabImageID.setText("图片文件ID:%d"%imageID)
      self.__LabImageFile.setText("图片保存为: "+fileName)
      
   
##  ============窗体测试程序 ================================
if  __name__ == "__main__":        #用于当前窗体测试
   app = QApplication(sys.argv)    #创建GUI应用程序
   form=QmyMainWindow()            #创建窗体
   form.show()
   sys.exit(app.exec_())

猜你喜欢

转载自blog.csdn.net/qq_35412059/article/details/129699413