Source code for QVideo.cameras.Noise._camera

from QVideo.lib import QCamera, QVideoSource
import numpy as np
import time
import logging


logger = logging.getLogger(__name__)


__all__ = ['QNoiseCamera', 'QNoiseSource']


[docs] class QNoiseCamera(QCamera): '''Camera that generates random noise frames. Useful for testing and development without physical camera hardware. All properties are registered on construction; the camera opens automatically. Parameters ---------- cameraID : int Accepted for API consistency with other camera backends; ignored. blacklevel : int Minimum pixel value (inclusive). Default: ``48``. whitelevel : int Maximum pixel value (exclusive). Default: ``128``. *args : Forwarded to :class:`~QVideo.lib.QCamera`. **kwargs : Forwarded to :class:`~QVideo.lib.QCamera`. ''' def __init__(self, *args, cameraID: int = 0, blacklevel: int = 48, whitelevel: int = 128, **kwargs) -> None: super().__init__(*args, **kwargs) self._width = 640 self._height = 480 self._fps = 30. self._blacklevel = int(np.clip(blacklevel, 0, 254)) self._whitelevel = int(np.clip(whitelevel, 1, 255)) register = self.registerProperty register('width', setter=self._setWidth, ptype=int) register('height', setter=self._setHeight, ptype=int) register('fps', ptype=float) register('color', getter=lambda: False, setter=None, ptype=bool) register('blacklevel', setter=self._setBlacklevel, ptype=int) register('whitelevel', setter=self._setWhitelevel, ptype=int) self.open() def _setWidth(self, value: int) -> None: '''Set frame width and emit :attr:`shapeChanged`.''' self._width = int(value) self.shapeChanged.emit(self.shape) def _setHeight(self, value: int) -> None: '''Set frame height and emit :attr:`shapeChanged`.''' self._height = int(value) self.shapeChanged.emit(self.shape) def _setBlacklevel(self, value: int) -> None: '''Set black level, clamped to [0, 254]. Rejects values that would make blacklevel >= whitelevel. ''' value = int(np.clip(value, 0, 254)) if value >= self._whitelevel: logger.warning( f'blacklevel {value} must be less than ' f'whitelevel {self._whitelevel}: ignoring') return self._blacklevel = value def _setWhitelevel(self, value: int) -> None: '''Set white level, clamped to [1, 255]. Rejects values that would make whitelevel <= blacklevel. ''' value = int(np.clip(value, 1, 255)) if value <= self._blacklevel: logger.warning( f'whitelevel {value} must be greater than ' f'blacklevel {self._blacklevel}: ignoring') return self._whitelevel = value def _initialize(self) -> bool: '''Seed the random number generator. Returns ------- bool Always ``True``. ''' self._rng = np.random.default_rng() return True def _deinitialize(self) -> None: '''Release the random number generator.''' self._rng = None
[docs] def read(self) -> QCamera.CameraData: '''Generate and return a random noise frame. Returns ------- tuple[bool, ndarray] ``(True, frame)`` where ``frame`` is a grayscale uint8 array of shape ``(height, width)``. ''' if not self.isOpen(): return False, None time.sleep(1. / self._fps) image = self._rng.integers(self._blacklevel, self._whitelevel, (self._height, self._width), np.uint8) return True, image
[docs] class QNoiseSource(QVideoSource): '''Threaded video source backed by :class:`QNoiseCamera`. Parameters ---------- camera : QNoiseCamera or None Camera instance to wrap. If ``None``, a new :class:`QNoiseCamera` is created from the remaining arguments. *args : Forwarded to :class:`QNoiseCamera` when ``camera`` is ``None``. **kwargs : Forwarded to :class:`QNoiseCamera` when ``camera`` is ``None``. ''' def __init__(self, *args, camera: QNoiseCamera | None = None, **kwargs) -> None: camera = camera or QNoiseCamera(*args, **kwargs) super().__init__(camera)
if __name__ == '__main__': # pragma: no cover QNoiseCamera.example()