Unsolved Qcamera supportedViewfinderPixelFormats doesn't return the full list
-
Hi,
I'm trying to capture a still image from my camera, my camera isn AUKEY brand, viewing the camera in a program like guvcview and playing with the settings it seems like the camera can be set to 1920x1080 only if the format is set to H264, RGB3 or MJPEG.unfortunately the list of formats returned by
supportedViewfinderPixelFormats
only showsFormat_YUYV
which for my camera only support 640x480 and 1280x720.supported formats returned by v4l2-ctrl:
╰─➤ v4l2-ctl --list-formats -d /dev/video0 ioctl: VIDIOC_ENUM_FMT Type: Video Capture [0]: 'MJPG' (Motion-JPEG, compressed) [1]: 'H264' (H.264, compressed) [2]: 'YUYV' (YUYV 4:2:2)
my sample program:
import sys import os import signal import traceback from PyQt5 import QtWidgets as qtw from PyQt5 import QtCore as qtc from PyQt5 import QtGui as qtg from PyQt5.QtMultimedia import QCameraInfo, QCamera, QCameraImageCapture,QImageEncoderSettings from PyQt5.QtMultimediaWidgets import QCameraViewfinder class mainwindow(qtw.QMainWindow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.centralwidget = qtw.QWidget() self.setCentralWidget(self.centralwidget) self.gridLayout = qtw.QGridLayout(self.centralwidget) self.avatarLayout = qtw.QHBoxLayout() self.gridLayout.addLayout(self.avatarLayout, 0, 0, 1, 1) self.avatar = qtw.QLabel() self.avatar.setText("") self.avatar.setStyleSheet("background-color:#c7dcff") self.start_cam = qtw.QPushButton("start camera") self.capture_cam = qtw.QPushButton("capture camera") self.viewFinderContainer = qtw.QWidget() self.viewFinderContainer_layout =qtw.QGridLayout(self.viewFinderContainer) self.viewFinder = QCameraViewfinder() self.viewFinderContainer.setStyleSheet("background-color:#98b8ed") self.viewFinderContainer_layout.addWidget(self.viewFinder) self.viewFinderContainer.setMinimumHeight(400) self.viewFinderContainer.setMinimumWidth(400) self.avatar.setMinimumHeight(600) self.avatar.setMinimumWidth(400) self.avatarLayout.addWidget(self.viewFinderContainer) self.avatarLayout.addWidget(self.avatar) self.gridLayout.addWidget(self.start_cam,1,0,1,1) self.gridLayout.addWidget(self.capture_cam,2,0,1,1) self.statusbar = qtw.QStatusBar(self) self.setStatusBar(self.statusbar) self.start_cam.clicked.connect(self.get_webcam) self.capture_cam.clicked.connect(self.capture_img) self.online_webcams = QCameraInfo.availableCameras() self.show() @qtc.pyqtSlot() def get_webcam(self): if not self.online_webcams: self.statusbar.showMessage("you didn't connect a camera") else: print("getting webcam") self.my_webcam = QCamera(self.online_webcams[0]) self.my_webcam.statusChanged.connect(self.status_changed) self.my_webcam.setViewfinder(self.viewFinder) self.my_webcam.setCaptureMode(QCamera.CaptureStillImage) self.my_webcam.error.connect(lambda: print(self.my_webcam.errorString())) print("starting webcam") self.my_webcam.start() self.capture = QCameraImageCapture(self.my_webcam) self.cap_end_settings = QImageEncoderSettings() # self.cap_end_settings.setResolution(qtc.QSize(1080,1920)) self.capture.setEncodingSettings(self.cap_end_settings) self.capture.setCaptureDestination(self.capture.CaptureToBuffer) self.capture.error.connect(lambda i, e, s: print(s)) self.capture.imageCaptured.connect(self.captured) self.current_camera_name = self.online_webcams[0].description() def captured(self,d,i): print('captured') print("scale the pixmap") pixmap = qtg.QPixmap.fromImage(i.convertToFormat(qtg.QImage.Format_ARGB32)).scaledToHeight(600,qtc.Qt.SmoothTransformation) self.avatar.setPixmap(pixmap) @qtc.pyqtSlot(QCamera.Status) def status_changed(self,status): print("status changed, new status: ",status) # Camera is loaded and we can query and set settings if status == QCamera.LoadedStatus: print("printing supported camera PixelFormats") print(self.my_webcam.supportedViewfinderPixelFormats()) print("setting pixel format") self.my_webcam.viewfinderSettings().setPixelFormat(30) print(self.my_webcam.viewfinderSettings().pixelFormat()) print("printing supported camera resolutions") print(self.my_webcam.supportedViewfinderResolutions()) # print("setting resolution") # self.my_webcam.viewfinderSettings().setResolution(1080,1920) # print("printing supported camera resolutions") # print(self.my_webcam.viewfinderSettings().resolution()) # print("printing current camera resolutions") # print(self.my_webcam.viewfinderSettings().resolution()) @qtc.pyqtSlot() def capture_img(self): if (self.capture.isReadyForCapture()): self.capture.capture() def setup_interrupt_handling(): """Setup handling of KeyboardInterrupt (Ctrl-C) for PyQt.""" signal.signal(signal.SIGINT, _interrupt_handler) # Regularly run some (any) python code, so the signal handler gets a # chance to be executed: safe_timer(50, lambda: None) # Define this as a global function to make sure it is not garbage # collected when going out of scope: def _interrupt_handler(signum, frame): """Handle KeyboardInterrupt: quit application.""" w.cleanup() qtw.QApplication.quit() def safe_timer(timeout, func, *args, **kwargs): """ Create a timer that is safe against garbage collection and overlapping calls. See: http://ralsina.me/weblog/posts/BB974.html """ def timer_event(): try: func(*args, **kwargs) finally: qtc.QTimer.singleShot(timeout, timer_event) qtc.QTimer.singleShot(timeout, timer_event) def excepthook(exc_type, exc_value, exc_tb): tb = "".join(traceback.format_exception(exc_type, exc_value, exc_tb)) print("error catched!:") print("error message:\n", tb) qtw.QApplication.quit() if __name__ == '__main__': os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" sys.excepthook = excepthook try: qtw.QApplication.setAttribute(qtc.Qt.AA_EnableHighDpiScaling) except AttributeError: # Attribute only exists for Qt>=5.6. pass app = qtw.QApplication(sys.argv) setup_interrupt_handling() w = mainwindow() ret = app.exec_() sys.exit(ret)
-
Hi,
Which version of PyQt5 ?
How did you install it ?
Which distribution are you using ?
Do you get the same result with PySide2/6 ? -
@SGaist said in Qcamera supportedViewfinderPixelFormats doesn't return the full list:
Hi,
Which version of PyQt5 ?
PyQt5==5.15.4
PyQt5-sip==12.9.0How did you install it ?
pip install PyQt5
Which distribution are you using ?
Manjaro linux
Do you get the same result with PySide2/6 ?
On, Pyside2 the problem is the same, I couldn't port it to PySide6 however, still have no experience in the version 6 bindings
-
Some problem here. Qt 5.15.3 on Ubuntu 22.04.
I'm using the C++ interface.supportedViewfinder*
only returnsYUYV
formats even though the camera also supportsMJPG
and RGB formats.
They are consistently missing everywhere. E.g. setting a resolution inQCameraViewFinderSettings
and leaving pixel formats and frame rate unspecified only returns theYUYV
frame rates.As far as I know, Qt uses gstreamer on Linux, so the problem may be in either of the two.
V4L2 correctly detects all formats. -
Same code on Windows 10 returns
YUYV
andJpeg
pixel formats. I still don't get the RGB formats that V4L2 lists, but at leastJpeg
is there.
Hence, it seems to be specifically a Qt on Linux issue.