Skip to content

Commit e3b0f97

Browse files
committed
refactor
1 parent 31c4c34 commit e3b0f97

File tree

5 files changed

+32
-21
lines changed

5 files changed

+32
-21
lines changed

src/arduino/app_peripherals/camera/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"IPCamera",
1515
"WebSocketCamera",
1616
"CameraError",
17-
"CameraReadError",
18-
"CameraOpenError",
1917
"CameraConfigError",
18+
"CameraOpenError",
19+
"CameraReadError",
2020
"CameraTransformError",
2121
]

src/arduino/app_peripherals/camera/base_camera.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,25 @@ def capture(self) -> Optional[np.ndarray]:
8787
return None
8888
return frame
8989

90+
def is_started(self) -> bool:
91+
"""Check if the camera is started."""
92+
return self._is_started
93+
94+
def stream(self):
95+
"""
96+
Continuously capture frames from the camera.
97+
98+
This is a generator that yields frames continuously while the camera is started.
99+
Built on top of capture() for convenience.
100+
101+
Yields:
102+
np.ndarray: Video frames as numpy arrays.
103+
"""
104+
while self._is_started:
105+
frame = self.capture()
106+
if frame is not None:
107+
yield frame
108+
90109
def _extract_frame(self) -> np.ndarray | None:
91110
"""Extract a frame with FPS throttling and post-processing."""
92111
with self._camera_lock:
@@ -114,14 +133,6 @@ def _extract_frame(self) -> np.ndarray | None:
114133

115134
return frame
116135

117-
def is_started(self) -> bool:
118-
"""Check if the camera is started."""
119-
return self._is_started
120-
121-
def produce(self) -> Optional[np.ndarray]:
122-
"""Alias for capture method for compatibility."""
123-
return self.capture()
124-
125136
@abstractmethod
126137
def _open_camera(self) -> None:
127138
"""Open the camera connection. Must be implemented by subclasses."""

src/arduino/app_peripherals/camera/camera.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ class Camera:
2121
Supports:
2222
- V4L Cameras (local cameras connected to the system), the default
2323
- IP Cameras (network-based cameras via RTSP, HLS)
24-
- WebSocket Cameras (input streams via WebSocket client)
24+
- WebSocket Cameras (input video streams via WebSocket client)
2525
26-
Note: constructor arguments (except source) must be provided in keyword
27-
format to forward them correctly to the specific camera implementations.
26+
Note: constructor arguments (except those in signature) must be provided in
27+
keyword format to forward them correctly to the specific camera implementations.
2828
"""
2929

3030
def __new__(

src/arduino/app_peripherals/camera/v4l_camera.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def __init__(
4444
a numpy array and returns a numpy array. Default: None
4545
"""
4646
super().__init__(resolution, fps, adjustments)
47-
self.device_index = self._resolve_camera_id(device)
47+
self.device = self._resolve_camera_id(device)
4848
self.logger = logger
4949

5050
self._cap = None
@@ -123,9 +123,9 @@ def _get_video_devices_by_index(self) -> dict[int, str]:
123123

124124
def _open_camera(self) -> None:
125125
"""Open the V4L camera connection."""
126-
self._cap = cv2.VideoCapture(self.device_index)
126+
self._cap = cv2.VideoCapture(self.device)
127127
if not self._cap.isOpened():
128-
raise CameraOpenError(f"Failed to open V4L camera {self.device_index}")
128+
raise CameraOpenError(f"Failed to open V4L camera {self.device}")
129129

130130
self._cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # Reduce buffer to minimize latency
131131

@@ -139,7 +139,7 @@ def _open_camera(self) -> None:
139139
actual_height = int(self._cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
140140
if actual_width != self.resolution[0] or actual_height != self.resolution[1]:
141141
logger.warning(
142-
f"Camera {self.device_index} resolution set to {actual_width}x{actual_height} "
142+
f"Camera {self.device} resolution set to {actual_width}x{actual_height} "
143143
f"instead of requested {self.resolution[0]}x{self.resolution[1]}"
144144
)
145145
self.resolution = (actual_width, actual_height)
@@ -149,10 +149,10 @@ def _open_camera(self) -> None:
149149

150150
actual_fps = int(self._cap.get(cv2.CAP_PROP_FPS))
151151
if actual_fps != self.fps:
152-
logger.warning(f"Camera {self.device_index} FPS set to {actual_fps} instead of requested {self.fps}")
152+
logger.warning(f"Camera {self.device} FPS set to {actual_fps} instead of requested {self.fps}")
153153
self.fps = actual_fps
154154

155-
logger.info(f"Opened V4L camera with index {self.device_index}")
155+
logger.info(f"Opened V4L camera with index {self.device}")
156156

157157
def _close_camera(self) -> None:
158158
"""Close the V4L camera connection."""
@@ -167,6 +167,6 @@ def _read_frame(self) -> np.ndarray | None:
167167

168168
ret, frame = self._cap.read()
169169
if not ret or frame is None:
170-
raise CameraReadError(f"Failed to read from V4L camera {self.device_index}")
170+
raise CameraReadError(f"Failed to read from V4L camera {self.device}")
171171

172172
return frame

src/arduino/app_utils/image/adjustments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def resize(frame: np.ndarray, target_size: Tuple[int, int], maintain_ratio: bool
101101
"""
102102
if frame.shape[1] == target_size[0] and frame.shape[0] == target_size[1]:
103103
return frame
104-
104+
105105
if maintain_ratio:
106106
return letterbox(frame, target_size)
107107
else:

0 commit comments

Comments
 (0)