capture_helper.camera module
capture_helper.camera
Live camera-frame iterator that bridges capture_helper.list_sources()
output with the same numpy BGR (H, W, 3) uint8 contract that
video_helper.extract_frames() uses for file-based decoding. The
intent is: if you can drop a video file path into a pipeline, you can
drop a live camera in.
Implementation
Shells out to
ffmpegwith the right per-OS input driver (-f avfoundation/-f v4l2/-f dshow) built bycapture_helper.sources.ffmpeg_input_args().Asks ffmpeg to decode + scale + pad to the requested output size and emit raw
bgr24to stdout. We read fixed-size byte blocks and reshape into(H, W, 3).Pure synchronous generator — matches the
video_helper.extract_frames()API. Async wrapping is left to the caller (e.g.asyncio.to_thread).
Usage example
>>> import capture_helper as ch
>>> import cv2
>>> cam = ch.pick_source("camera")
>>> for frame in ch.iter_camera_frames(cam, output_width=640, output_height=360,
... fps=30, max_frames=300):
... cv2.imshow("preview", frame)
... if cv2.waitKey(1) & 0xFF == ord("q"):
... break
- capture_helper.camera.iter_camera_frames(source, *, width=None, height=None, fps=None, output_width=None, output_height=None, pad_color='black', max_frames=None)[source]
Yield live camera frames as numpy BGR uint8 arrays.
Wraps ffmpeg with the per-OS input driver picked up from
source["driver"]and emits(H, W, 3)uint8arrays in OpenCV’s BGR channel order — the same shape and dtypevideo_helper.extract_frames()yields. Consumers built for the file-based path therefore plug in unchanged.- Parameters:
source (Source) – Device dict returned by
pick_source()/list_sources(). Itskindmust be"camera".width (int, optional) – Capture-side resolution request. Passed to ffmpeg as
-video_size WxHbefore the input — the OS driver picks the closest supported mode if the exact value isn’t available. LeaveNoneto use the driver’s default.height (int, optional) – Capture-side resolution request. Passed to ffmpeg as
-video_size WxHbefore the input — the OS driver picks the closest supported mode if the exact value isn’t available. LeaveNoneto use the driver’s default.fps (float, optional) – Capture-side frame rate request. Same caveat as
width / height. LeaveNonefor the driver default.output_width (int, optional) –
Post-decode output size. Behaviour mirrors
video_helper.extract_frames():both set → scale-fit (aspect preserved) then pad with
pad_colorto exactlyoutput_width × output_height;one set → scale that axis, preserve aspect on the other;
neither set → native camera frame size.
output_height (int, optional) –
Post-decode output size. Behaviour mirrors
video_helper.extract_frames():both set → scale-fit (aspect preserved) then pad with
pad_colorto exactlyoutput_width × output_height;one set → scale that axis, preserve aspect on the other;
neither set → native camera frame size.
pad_color (str, optional) – Colour name (
"black"/"white"/"#RRGGBB"/ …) used when scale-fit-and-pad applies. Default"black".max_frames (int, optional) – Stop after yielding this many frames.
None(default) = unbounded — runs until the source disconnects or the consumer breaks.
- Yields:
numpy.ndarray – Successive frames as
(H, W, 3)BGRuint8arrays. Same convention as OpenCV andvideo_helper.extract_frames().- Raises:
ValueError – If
source["kind"]isn’t"camera".FileNotFoundError – If
ffmpegisn’t on PATH.RuntimeError – If ffmpeg exits before the first frame is decoded (typical when the OS denied camera permission or the device is in use by another process).
- Return type:
Iterator[ndarray]
Examples
>>> cam = ch.pick_source("camera") >>> for frame in ch.iter_camera_frames(cam, ... output_width=224, output_height=224, ... max_frames=10): ... # frame.shape == (224, 224, 3), dtype uint8, BGR. ... model(frame)