Color Conversion API
Color-space conversions between NV12 and packed RGB/BGR.
Camera streams arrive as NV12 (semi-planar YUV 4:2:0, limited range);
models and drawing want packed RGB/BGR. Frame.to_rgb() already covers
NV12→RGB in numpy — the reverse direction and the plane-level utilities
were missing, so apps kept re-implementing them (parking-lot carries its
own trio of converters, parking_lot/app.py:312-358).
cv2 accelerates every conversion when installed; otherwise a vectorised
numpy path is used (BT.601 limited range, matching cv2’s
COLOR_YUV2BGR_NV12 semantics). The numpy chroma path is
nearest-neighbour on decode / 2×2 block mean on encode, so round-trips
lose a little chroma detail — fine for model input, not for pixel-exact
comparisons.
from neoruntime_ipc_sdk.color import rgb_to_nv12, nv12_resize
nv12 = rgb_to_nv12(rgb) # (h*3/2, w) uint8
small = nv12_resize(nv12, (1920, 1080), (640, 384))
- neoruntime_ipc_sdk.color.bgr_to_nv12(bgr)[source]
Convert a BGR
(h, w, 3)array to an NV12(h*3/2, w)buffer.
- neoruntime_ipc_sdk.color.nv12_resize(nv12, src_size, dst_size)[source]
Resize an NV12 buffer from
src_sizetodst_size(width, height).Resizes the Y and UV planes separately — avoids the NV12→BGR→resize→BGR→NV12 round-trip (the approach proven in parking-lot). With cv2 the planes are resized with bilinear interpolation; the numpy fallback uses nearest-neighbour.
- neoruntime_ipc_sdk.color.nv12_to_bgr(nv12, width, height)[source]
Convert an NV12 buffer to a BGR
(height, width, 3)uint8 array.
- neoruntime_ipc_sdk.color.nv12_to_rgb(nv12, width, height)[source]
Convert an NV12 buffer to an RGB
(height, width, 3)uint8 array.Hardware-first: rides the accel router (DSP convert when the daemon is reachable,
_nv12_to_rgb_impl()otherwise).
- neoruntime_ipc_sdk.color.rgb_to_nv12(rgb)[source]
Convert an RGB
(h, w, 3)array to an NV12(h*3/2, w)buffer.Hardware-first: rides the accel router (DSP convert when the daemon is reachable,
_rgb_to_nv12_impl()otherwise).
Functions
nv12_to_rgb / nv12_to_bgr
- neoruntime_ipc_sdk.color.nv12_to_rgb(nv12, width, height)[source]
Convert an NV12 buffer to an RGB
(height, width, 3)uint8 array.Hardware-first: rides the accel router (DSP convert when the daemon is reachable,
_nv12_to_rgb_impl()otherwise).
- neoruntime_ipc_sdk.color.nv12_to_bgr(nv12, width, height)[source]
Convert an NV12 buffer to a BGR
(height, width, 3)uint8 array.
rgb_to_nv12 / bgr_to_nv12
- neoruntime_ipc_sdk.color.rgb_to_nv12(rgb)[source]
Convert an RGB
(h, w, 3)array to an NV12(h*3/2, w)buffer.Hardware-first: rides the accel router (DSP convert when the daemon is reachable,
_rgb_to_nv12_impl()otherwise).
- neoruntime_ipc_sdk.color.bgr_to_nv12(bgr)[source]
Convert a BGR
(h, w, 3)array to an NV12(h*3/2, w)buffer.
nv12_resize
- neoruntime_ipc_sdk.color.nv12_resize(nv12, src_size, dst_size)[source]
Resize an NV12 buffer from
src_sizetodst_size(width, height).Resizes the Y and UV planes separately — avoids the NV12→BGR→resize→BGR→NV12 round-trip (the approach proven in parking-lot). With cv2 the planes are resized with bilinear interpolation; the numpy fallback uses nearest-neighbour.
Examples
Feed an NV12 model with an RGB frame
from neoruntime_ipc_sdk import rgb_to_nv12, nv12_resize
# Encode the annotated RGB frame and resize it as NV12 — no
# NV12->RGB->resize->RGB->NV12 round-trip anywhere
nv12 = rgb_to_nv12(rgb_frame)
small = nv12_resize(nv12, (1920, 1080), (640, 384))
Route through DSP hardware
# Prefers the DSP leg (see the Accel Routing API); falls back to the
# numpy/cv2 software implementation when the DSP is unreachable and
# records the degradation in health()
from neoruntime_ipc_sdk import get_default_router
router = get_default_router()
small = router.run("resize_nv12", nv12, (1920, 1080), (640, 384))