pythonpyqt5qcamera

How to click a photo using QCamera in PyQt5?


PyQT5 QCamera not clicking a photo


I tried refering their official PyQt5 QCamera Documentation but didn't understood much.

  1. I have created a Mainwindow with a pushbutton
  2. Button on click, executes the clickphoto function
  3. clickphoto function runs to capture image only when available cameras list length > 0, else prints Error
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
import os
class Ui_MainWindow(object):
    def clickphoto(self):
        print("clickphoto Called !")
        available_cameras = QCameraInfo.availableCameras()
        if len(available_cameras)>0:
            print(available_cameras[0].description())
            try:
                camera = QCamera(available_cameras[0])
                camera.setCaptureMode(QCamera.CaptureStillImage)
                camera.start()
                capture = QCameraImageCapture(camera)
                capture.capture(str(os.getcwd())+"//"+"999.jpg")

                # i also tried capture.capture("999.jpg") still no output 
                # (checked in Pictures folder)

            except Exception as e:
                print("Exception occured, ",e)
        else:
            print("Error")

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(251, 271)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.clickphotobtn = QtWidgets.QPushButton(self.centralwidget)
        self.clickphotobtn.setGeometry(QtCore.QRect(90, 110, 75, 23))
        self.clickphotobtn.setObjectName("clickphotobtn")

        # click event !!
        self.clickphotobtn.clicked.connect(self.clickphoto)

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 251, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.clickphotobtn.setText(_translate("MainWindow", "Capture"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Output

PS C:\Users\Beast80K\Documents\Auto Brightness> & C:/Users/Beast80K/AppData/Local/Programs/Python/Python39/python.exe "c:/Users/Beast80K/Documents/Auto Brightness/trycappic.py"
clickphoto Called !
USB2.0 PC CAMERA
Unsupported media type: "{32595559-0000-0010-8000-00AA00389B71}"
Unsupported media type: "{32595559-0000-0010-8000-00AA00389B71}"
Unsupported media type: "{32595559-0000-0010-8000-00AA00389B71}"
Unsupported media type: "{32595559-0000-0010-8000-00AA00389B71}"
Unsupported media type: "{32595559-0000-0010-8000-00AA00389B71}"

Solution

  • You have to take into account that:

    1. Check if the device has the ability to take photos.

    2. The capture of photos is asynchronous so you must use signals to know if the device is ready to take photos and if it has finished saving the photo.

    import os
    from pathlib import Path
    from typing import ChainMap
    import uuid
    
    from PyQt5.QtWidgets import QApplication, QMainWindow
    from PyQt5.QtMultimedia import QCamera, QCameraImageCapture, QCameraInfo
    
    from gui import Ui_MainWindow
    
    CURRENT_DIRECTORY = Path(__file__).resolve().parent
    PHOTO_DIRECTORY = CURRENT_DIRECTORY / "photos"
    
    PHOTO_DIRECTORY.mkdir(parents=True, exist_ok=True)
    
    
    class MainWindow(QMainWindow):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.ui = Ui_MainWindow()
            self.ui.setupUi(self)
    
            self.ui.clickphotobtn.clicked.connect(self.handle_clicked)
    
        def handle_clicked(self):
            self.capture()
    
        def capture(self):
            for camera_info in QCameraInfo.availableCameras():
                camera = QCamera(camera_info, self)
                if not camera.isCaptureModeSupported(QCamera.CaptureStillImage):
                    print("Camera cannot capture images")
                    continue
                camera.setCaptureMode(QCamera.CaptureStillImage)
                camer.errorOccurred.connect(self.handle_errorOccurred)
                camera.start()
                image_capture = QCameraImageCapture(camera, self)
                image_capture.readyForCaptureChanged.connect(
                    self.handle_readyForCaptureChanged
                )
                image_capture.imageSaved.connect(self.handle_imageSaved)
                camera.searchAndLock()
    
        def handle_readyForCaptureChanged(self, ok):
            if ok:
                image_capture = self.sender()
                image_capture.capture(os.fspath(PHOTO_DIRECTORY / str(uuid.uuid4())))
                camera = image_capture.mediaObject()
                if isinstance(camera, QCamera):
                    camera.unlock()
    
        def handle_imageSaved(self):
            image_capture = self.sender()
            camera = image_capture.mediaObject()
            if isinstance(camera, QCamera):
                camera.stop()
                camera.deleteLater()
            image_capture.deleteLater()
    
        def handle_errorOccurred(self, error):
            print(error, self.sender().errorString())
    
    if __name__ == "__main__":
        import sys
    
        app = QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())
    

    Note: It is not recommended to modify the code generated by QtDesigner so you must restore the file and call it gui.py