一、概述
在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:\temp\capimg\cap{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:\temp\capimg\cap{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)。