The use of PyQt5 camera--an overview of camera operation and using the camera to take pictures

1. Functional overview
The PyQt5 multimedia module provides several classes for camera operations, which can be used to obtain camera device information, take pictures and record videos through the camera.

The function realization of the Qt multimedia module depends on the platform. On the Windows platform, the Qt multimedia module depends on two plug-ins: one is a plug-in using the Microsoft DirectShow API, DirectShow was introduced in Windows 98 and gradually became obsolete after Windows XP; the other is a plug-in for Windows Media Foundation (WMF), The WMF plug-in was introduced in Windows Vista as a replacement for DirectShow.

The WMF plug-in in Qt currently cannot provide camera support. The limited support for the camera is provided by the DirectShow plug-in. At present, it can only display the viewfinder and capture still pictures, and most other functions are not supported. Therefore, currently on the Windows platform, Qt's camera control does not support the video recording function, nor does it support the underlying video functions, such as using QVideoProbe to detect video frames.

The multimedia module of PyQt5 cannot realize the camera recording function on the Windows platform.

2. Main classes and functions
++++++++++++++++++++++++++++
QCameraInfo: Camera device information class

availableCameras(): Returns a list of QCameraInfo types, indicating the cameras available in the system.

defaultCamera(): Returns a QCameraInfo object, which is the system default camera device information.

description(): Returns the camera device description.

deviceName(): Returns the camera device name.

position(): The return value is the enumeration type QCamera.Position, indicating the position of the camera.
For example, a mobile phone generally has two cameras, the position type of the front camera is QCamera.FrontFace, the position type of the rear camera is QCamera.BackFace, and the unspecified position is QCamera.UnspecifiedPosition.
++++++++++++++++++++++++++++
QCamera: The class for operating the camera. When creating a QCamera object, a QCameraInfo object needs to be passed as a parameter.

setViewfinder(viewfinder): Specify a QVideoWidget or QGraphicsVideoItem object viewfinder for the camera as a viewfinder for camera image preview. Generally, a QCameraViewfinder class object is used for camera preview, and its parent class is QVideoWidget.

setCaptureMode(mode): It is used to set the working mode of the camera. The parameter mode is the enumeration type QCamera. CaptureModes, which has the following values:
QCamera.CaptureViewfinder (viewfinder mode, the camera is only used for preview);
QCamera.CaptureStillImage (capture still picture mode);
QCamera.CaptureVideo(video recording mode).

isCaptureModeSupported(mode), to determine whether the camera supports a certain working mode, the parameter mode is the enumeration type QCamera.CaptureModes.

searchAndLock(): Executed before taking a picture, used to lock the camera's exposure, white balance and other parameters when the shutter is half-pressed

unlock(): Executed after taking a picture, used to unlock.
++++++++++++++++++++++++++++++
QCameraImageCapture: Control the camera to capture still pictures

setEncodingSettings(settings): Set the encoding of the picture taken. The settings are of the QImageEncoderSettings type. The settings include the encoding scheme, resolution, and image quality.

setBufferFormat(format): Set the format of the picture in the camera buffer. The parameter format is the enumeration type QVideoFrame.PixelFormat, which has dozens of values. Here, QVideoFrame.Format_Jpeg is used, that is, the JPEG format is used.

setCaptureDestination(destination): used to set the way to save the captured pictures, destination is the enumeration type QCameraImageCapture.CaptureDestination, has the following two values:
QCameraImageCapture.CaptureToBuffer (the captured picture is saved in the buffer, and the signal
imageCaptured() will be emitted , the picture in the buffer can be extracted in the slot function of this signal); - QCameraImageCapture.CaptureToFile (the captured picture is automatically saved to the "picture" folder of the user directory, and the imageSaved() signal will be emitted after the picture is saved)
. If it is set to CaptureToBuffer, only the imageCaptured() signal will be emitted, and the picture will appear in the buffer, and will not be automatically saved as a file, nor will the imageCaptured() signal be emitted; and if it is set to CaptureToFile, both signals will be emitted.

The functions of the three signals of QCameraImageCapture and the associated slot functions are as follows.

readyForCaptureChanged(ready): The signal is emitted when the state of whether the camera can take pictures changes, and the bool parameter ready is just used to control the enabling state of the camera button.

imageCaptured(imageID, preview) is emitted after the image is captured into the buffer. imageID is the number of the image, which is automatically accumulated every time a photo is taken. preview is of type QImage, which is the captured picture. In the associated slot function, display the content of this picture on the QLabel component LabImage on the interface.

The imageSaved(imageID, fileName) signal is emitted after the image is saved as a file, where fileName is the name of the automatically saved file. The imageID and the filename fileName are displayed in the associated slot function.
++++++++++++++++++++++++++++
QMediaRecorder: video recording via camera and audio input devices

3. Code implementation
insert image description here
The left side of the working area of ​​this window is the camera preview display, which is a QCameraViewfinder component, and the right side is the display of the captured photos, which is a QLabel component. A split layout is used between two GroupBox components.

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_())

Guess you like

Origin blog.csdn.net/qq_35412059/article/details/129699413