Increase frame rate for QCamera/QCameraViewfinder using PySide2 (Qt5)

433 views Asked by At

I'm tying to create a simple application to monitor a webcam and taking pictures, basically following the Qt for Python Camera Example, which uses PySide6 (Qt6).

However, for my case, I must use PySide2 (Qt5) instead, as the embed computer for this application has i386 architecture (32-bit Debian 11 installed). This is a small (working) sample code:

from pathlib import Path
from tempfile import NamedTemporaryFile
from PySide2 import QtWidgets, QtMultimedia, QtMultimediaWidgets


class SimpleCameraGUI(QtWidgets.QMainWindow):
    def __init__(self):
        super(SimpleCameraGUI, self).__init__(None)
        # main GUI elelements
        central_widget = QtWidgets.QWidget()
        hlayout = QtWidgets.QHBoxLayout()
        vlayout = QtWidgets.QVBoxLayout()
        self.start = QtWidgets.QPushButton('Start camera')
        self.stop = QtWidgets.QPushButton('Stop camera')
        self.take_pic = QtWidgets.QPushButton('Take Picture')
        self.camera_widget = QtMultimediaWidgets.QCameraViewfinder()
        # elements to Layout
        hlayout.addWidget(self.start)
        hlayout.addWidget(self.stop)
        hlayout.addWidget(self.take_pic)
        vlayout.addWidget(self.camera_widget)
        vlayout.addLayout(hlayout)
        central_widget.setLayout(vlayout)
        self.setCentralWidget(central_widget)
        # camera elements
        self.info = QtMultimedia.QCameraInfo()
        self.camera = QtMultimedia.QCamera(self.info.defaultCamera())
        self.image = QtMultimedia.QCameraImageCapture(self.camera)
        self.camera.setViewfinder(self.camera_widget)
        # connections
        self.start.clicked.connect(self.camera.start)
        self.stop.clicked.connect(self.camera.stop)
        self.take_pic.clicked.connect(self.save_temp_picture)
        # show GUI
        self.show()
    
    def save_temp_picture(self):
        filename = NamedTemporaryFile(suffix='.jpg', delete=True)
        self.image.capture(filename.name)
        QtWidgets.QMessageBox.information(
            None,
            'Temporary file saved',
            f'Location: <a href={Path(filename.name).as_uri()}>{filename.name}</a>'
        )
    

if __name__ == '__main__':
    app = QtWidgets.QApplication()
    win = SimpleCameraGUI()
    win.resize(640, 480)
    app.exec_()

The application works fine, but the video inside the QCameraViewfinder widget is extremely slow. I believe it has something to do with frame rate settings, but couldn't find where/how to change the parameters. My PySide2 version is 5.15.2.1.

Tried to use a QVideoWidget, but results are the same. Also tried to use the method setViewfinderSettings of the QCamera, but couldn't figure out how to actually use it.

1

There are 1 answers

0
kstenio On

After some searching I did found a solution.

One must create a QCameraViewfinderSettings object, set the desired frame rate range using setMinimumFrameRate() and setMaximumFrameRate() methods and finally apply those settings to the QCamera using setViewfinderSettings() method. I also discovered that it is important to choose the proper resolution of your camera by using setResolution().

Below is a revised code:

from pathlib import Path
from tempfile import NamedTemporaryFile
from PySide2 import QtWidgets, QtMultimedia, QtMultimediaWidgets


class SimpleCameraGUI(QtWidgets.QMainWindow):
    def __init__(self):
        super(SimpleCameraGUI, self).__init__(None)
        # main GUI elelements
        central_widget = QtWidgets.QWidget()
        hlayout = QtWidgets.QHBoxLayout()
        vlayout = QtWidgets.QVBoxLayout()
        self.start = QtWidgets.QPushButton('Start camera')
        self.stop = QtWidgets.QPushButton('Stop camera')
        self.take_pic = QtWidgets.QPushButton('Take Picture')
        self.camera_widget = QtMultimediaWidgets.QCameraViewfinder()
        # elements to Layout
        hlayout.addWidget(self.start)
        hlayout.addWidget(self.stop)
        hlayout.addWidget(self.take_pic)
        vlayout.addWidget(self.camera_widget)
        vlayout.addLayout(hlayout)
        central_widget.setLayout(vlayout)
        self.setCentralWidget(central_widget)
        # camera elements
        self.info = QtMultimedia.QCameraInfo()
        self.camera = QtMultimedia.QCamera(self.info.defaultCamera())
        self.image = QtMultimedia.QCameraImageCapture(self.camera)
        self.camera.setViewfinder(self.camera_widget)
        # sets resolution and frame rate to camera/viewfinder
        self.settings = QtMultimedia.QCameraViewfinderSettings()
        self.settings.setResolution(640, 480)
        self.settings.setMinimumFrameRate(15)
        self.settings.setMaximumFrameRate(30)
        self.camera.setViewfinderSettings(self.settings)
        # connections
        self.start.clicked.connect(self.camera.start)
        self.stop.clicked.connect(self.camera.stop)
        self.take_pic.clicked.connect(self.save_temp_picture)
        # show GUI
        self.show()
    
    def save_temp_picture(self):
        filename = NamedTemporaryFile(suffix='.jpg', delete=True)
        self.image.capture(filename.name)
        QtWidgets.QMessageBox.information(
            None,
            'Temporary file saved',
            f'Location: <a href={Path(filename.name).as_uri()}>{filename.name}</a>'
        )
    

if __name__ == '__main__':
    app = QtWidgets.QApplication()
    win = SimpleCameraGUI()
    win.resize(640, 480)
    app.exec_()