feat(input/gestures): add CameraCapture and public __init__ exports
This commit is contained in:
parent
a31e6099c6
commit
524cc62812
2 changed files with 72 additions and 0 deletions
|
|
@ -0,0 +1,15 @@
|
|||
"""
|
||||
cf_input.gestures — camera capture, hand detection, landmark normalization.
|
||||
|
||||
Public API:
|
||||
CameraCapture — OpenCV frame source
|
||||
HandsDetector — MediaPipe Hands wrapper
|
||||
HandLandmarks — immutable detected hand dataclass
|
||||
normalize_hand() — scale/translation-invariant feature vector
|
||||
"""
|
||||
|
||||
from circuitforge_core.input.gestures.camera import CameraCapture
|
||||
from circuitforge_core.input.gestures.hands import HandLandmarks, HandsDetector
|
||||
from circuitforge_core.input.gestures.normalizer import normalize_hand
|
||||
|
||||
__all__ = ["CameraCapture", "HandLandmarks", "HandsDetector", "normalize_hand"]
|
||||
57
circuitforge_core/input/gestures/camera.py
Normal file
57
circuitforge_core/input/gestures/camera.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
"""
|
||||
OpenCV camera capture — context manager wrapping VideoCapture.
|
||||
|
||||
Yields BGR frames. Callers convert to RGB before passing to HandsDetector:
|
||||
frame_rgb = frame_bgr[:, :, ::-1]
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Iterator
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
|
||||
class CameraCapture:
|
||||
"""
|
||||
Thin wrapper around cv2.VideoCapture.
|
||||
|
||||
Usage:
|
||||
with CameraCapture(device_index=0) as cam:
|
||||
for frame_bgr in cam.frames():
|
||||
process(frame_bgr)
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
device_index: int = 0,
|
||||
width: int = 640,
|
||||
height: int = 480,
|
||||
fps: int = 30,
|
||||
) -> None:
|
||||
self._cap = cv2.VideoCapture(device_index)
|
||||
self._cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
|
||||
self._cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
|
||||
self._cap.set(cv2.CAP_PROP_FPS, fps)
|
||||
|
||||
@property
|
||||
def is_open(self) -> bool:
|
||||
return self._cap.isOpened()
|
||||
|
||||
def frames(self) -> Iterator[np.ndarray]:
|
||||
"""Yield BGR uint8 frames until camera fails or caller breaks."""
|
||||
while self._cap.isOpened():
|
||||
ok, frame = self._cap.read()
|
||||
if not ok:
|
||||
break
|
||||
yield frame
|
||||
|
||||
def release(self) -> None:
|
||||
self._cap.release()
|
||||
|
||||
def __enter__(self) -> CameraCapture:
|
||||
return self
|
||||
|
||||
def __exit__(self, *_: object) -> None:
|
||||
self.release()
|
||||
Loading…
Reference in a new issue