Source code for zoloto.cameras.camera

from pathlib import Path
from typing import Any, Generator, Optional

from cv2 import CAP_PROP_BUFFERSIZE, VideoCapture
from numpy import ndarray

from .base import BaseCamera
from .mixins import IterableCameraMixin, VideoCaptureMixin


def find_camera_ids() -> Generator[int, None, None]:
    """
    Find and return ids of connected cameras.

    Works the same as VideoCapture(-1).
    """
    for camera_id in range(8):
        capture = VideoCapture(camera_id)
        opened = capture.isOpened()
        capture.release()
        if opened:
            yield camera_id


[docs]class Camera(BaseCamera, IterableCameraMixin, VideoCaptureMixin):
[docs] def __init__( self, camera_id: int, *, calibration_file: Optional[Path] = None ) -> None: super().__init__(calibration_file=calibration_file) self.camera_id = camera_id self.video_capture = self.get_video_capture(self.camera_id)
[docs] def get_video_capture(self, camera_id: int) -> VideoCapture: cap = VideoCapture(camera_id) cap.set(CAP_PROP_BUFFERSIZE, 1) return cap
[docs] def capture_frame(self) -> ndarray: # Hack: Double capture frames to fill buffer. self.video_capture.read() return super().capture_frame()
[docs] def close(self) -> None: super().close() self.video_capture.release()
[docs] @classmethod def discover(cls, **kwargs: Any) -> Generator["Camera", None, None]: for camera_id in find_camera_ids(): yield cls(camera_id, **kwargs)
[docs]class SnapshotCamera(BaseCamera, VideoCaptureMixin): """ A modified version of Camera optimised for single use. - Doesn't keep the camera open between captures """
[docs] def __init__( self, camera_id: int, *, calibration_file: Optional[Path] = None ) -> None: super().__init__(calibration_file=calibration_file) self.camera_id = camera_id
[docs] def get_video_capture(self, camera_id: int) -> VideoCapture: return VideoCapture(camera_id)
[docs] def capture_frame(self) -> ndarray: self.video_capture = self.get_video_capture(self.camera_id) frame = super().capture_frame() self.video_capture.release() return frame
[docs] @classmethod def discover(cls, **kwargs: Any) -> Generator["SnapshotCamera", None, None]: for camera_id in find_camera_ids(): yield cls(camera_id, **kwargs)