How to click a photo using QCamera in PyQt5?

909 views Asked by At

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}"
  • Python 3.9.6
  • Qt version: 5.15.2
  • Windows 10 21h1 (OS Build 19043.1237)
1

There are 1 answers

5
eyllanesc On BEST ANSWER

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