A display sink that overlays bounding boxes and text on an image input and shows it in an OpenCV window. Based on opencv-plot from dora-hub, brought up to the dora 1.0 node contract and packaged with uv. Python rather than Rust: the opencv Rust crate generates its bindings from the OpenCV headers on the build machine, so it needs libopencv-dev and libclang-dev per machine and per architecture and does not cross-compile. Every dependency here ships prebuilt wheels for linux-x86_64, linux-aarch64 and macos-arm64. Covers every encoding the upstream node did — bgr8, rgb8, jpeg/jpg/jpe/bmp/ webp/png, yuv420 and avif — plus both bbox formats, the text overlay, PLOT_WIDTH/PLOT_HEIGHT and headless operation under CI=true.
38 lines
1.2 KiB
Python
38 lines
1.2 KiB
Python
"""Parsing of the `bbox` input: an Arrow struct carrying boxes and labels."""
|
|
|
|
import numpy as np
|
|
|
|
from opencv_plot.plot import Bboxes
|
|
|
|
|
|
def parse(value, bbox_format: str) -> Bboxes:
|
|
"""Read a `bbox` payload. `bbox_format` is the `format` metadata parameter."""
|
|
fields = value[0]
|
|
corners = _flat(fields, "bbox").reshape(-1, 4)
|
|
|
|
if bbox_format == "xyxy":
|
|
pass
|
|
elif bbox_format == "xywh":
|
|
# xywh is centre-based: x and y are the box centre, not a corner.
|
|
x, y, w, h = corners.T
|
|
corners = np.stack([x - w / 2, y - h / 2, x + w / 2, y + h / 2], axis=1)
|
|
else:
|
|
raise RuntimeError(f"unsupported bbox format: {bbox_format}")
|
|
|
|
return Bboxes(
|
|
corners=corners,
|
|
conf=_flat(fields, "conf"),
|
|
labels=_flat(fields, "labels", numeric=False),
|
|
)
|
|
|
|
|
|
def _flat(fields, name: str, numeric: bool = True) -> np.ndarray:
|
|
"""Read a struct field as a flat numpy array.
|
|
|
|
Senders wrap each field in a single-element list -- that is what
|
|
`pa.array([{...}])` produces from numpy arrays -- so unwrap it when present.
|
|
"""
|
|
column = fields[name]
|
|
column = getattr(column, "values", column)
|
|
return column.to_numpy(zero_copy_only=False) if not numeric else column.to_numpy()
|