Source code for QVideo.cameras.Picamera._imx500
from typing import TYPE_CHECKING
from qtpy import QtCore
from QVideo.lib import QVideoSource
from ._camera import QPicamera
import logging
if TYPE_CHECKING:
from picamera2.devices.imx500 import IMX500 as _IMX500
try:
from picamera2.devices.imx500 import IMX500
except (ImportError, ModuleNotFoundError):
IMX500 = None
logger = logging.getLogger(__name__)
__all__ = ['QIMXCamera', 'QIMXSource']
[docs]
class QIMXCamera(QPicamera):
'''Raspberry Pi AI Camera (IMX500) with on-sensor neural-network inference.
Extends :class:`~QVideo.cameras.Picamera.QPicamera` to drive the IMX500
sensor\'s on-chip AI accelerator. Each captured frame is accompanied by
raw inference outputs, emitted via :attr:`newOutput`. Callers — overlays,
analysis widgets, or application code — connect to :attr:`newOutput` and
interpret the tensors for their specific model.
Requires ``picamera2 >= 0.3.20`` with IMX500 support::
pip install "picamera2[imx500]"
Parameters
----------
model : str
Path to the packed-network file (``.rpk``) to load onto the sensor.
cameraID : int
Index of the camera. Default: ``0``.
width : int
Initial frame width in pixels. Default: ``1280``.
height : int
Initial frame height in pixels. Default: ``960``.
gray : bool
``True`` to deliver grayscale frames. Default: ``False``.
hflip : bool
``True`` to mirror frames horizontally. Default: ``False``.
vflip : bool
``True`` to flip frames vertically. Default: ``False``.
Signals
-------
newOutput : list[numpy.ndarray] or None
Emitted alongside each frame with the raw inference output tensors.
The tensor structure depends on the loaded network model. ``None``
is emitted when the sensor has not yet produced outputs (e.g. on the
first few frames after start-up).
'''
#: Raw IMX500 inference outputs, emitted once per frame.
newOutput = QtCore.Signal(object)
def __init__(self, *args, model: str, **kwargs) -> None:
self._model = model
super().__init__(*args, **kwargs)
def _createDevice(self) -> '_IMX500 | None':
'''Return an :class:`~picamera2.devices.imx500.IMX500` instance.
Returns ``None`` when ``picamera2.devices.imx500`` is unavailable.
'''
if IMX500 is None:
logger.warning(
'picamera2.devices.imx500 is not available. '
'Install with: pip install "picamera2[imx500]"')
return None
return IMX500(self._model, camera_num=self._cameraID)
def _onRequest(self, metadata: dict) -> None:
'''Extract IMX500 inference outputs and emit :attr:`newOutput`.
Parameters
----------
metadata : dict
Frame metadata from :meth:`~picamera2.Picamera2.capture_request`.
'''
outputs = self._device.get_outputs(metadata)
self.newOutput.emit(outputs)
[docs]
class QIMXSource(QVideoSource):
'''Threaded video source backed by :class:`QIMXCamera`.
Parameters
----------
camera : QIMXCamera or None
Camera instance to wrap. If ``None``, a new :class:`QIMXCamera`
is created from the remaining arguments.
*args :
Forwarded to :class:`QIMXCamera` when *camera* is ``None``.
**kwargs :
Forwarded to :class:`QIMXCamera` when *camera* is ``None``.
'''
def __init__(self, *args,
camera: QIMXCamera | None = None,
**kwargs) -> None:
camera = camera if camera is not None else QIMXCamera(*args, **kwargs)
super().__init__(camera)