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)