检测框绘制 API
Drawing utilities - annotate RGB numpy arrays with detection boxes and text.
All functions take an RGB uint8 array (H, W, 3) and return a NEW array; the input is never modified. cv2 accelerates rendering when installed, otherwise Pillow (a hard SDK dependency) is used.
render_overlay_rgba is the hardware companion: it renders the same annotation as a minimal straight-alpha RGBA canvas (plus its frame offset) for DspClient.blend_hw instead of rasterizing onto the pixels.
Example
frame = client.get_frame(“main”) # Frame rgb = draw_detections(frame.to_rgb(), result)
- neoruntime_ipc_sdk.draw.draw_boxes(image, boxes, labels=None, scores=None, color=(0, 255, 0), thickness=2)[source]
Draw bounding boxes (pixel coordinates) on an RGB array copy.
- Parameters:
image (ndarray) – RGB uint8 array (H, W, 3).
boxes (Iterable) – iterable of (x1, y1, x2, y2) or BoundingBox-like objects.
labels (Sequence[str | None] | None) – optional per-box text (combined with scores when given).
scores (Sequence[float] | None) – optional per-box confidence.
thickness (int) – line thickness in pixels.
Returns: new RGB array; the input array is not modified.
- neoruntime_ipc_sdk.draw.draw_text(image, text, xy, color=(255, 255, 255), font_scale=0.5, thickness=1)[source]
Draw a text string at pixel position xy on an RGB array copy.
- neoruntime_ipc_sdk.draw.draw_detections(image, result_or_objects, color=None)[source]
Draw an InferenceResult (or a list of DetectedObject) on an RGB copy.
Each object gets a box plus a “label score” caption. When color is None, a per-class color from PALETTE is chosen via class_id.
Routing: NV12 2D arrays ride the accel router (DSP blend when the daemon is reachable, the CPU mirror otherwise); RGB arrays go straight to the software raster (no doomed hardware attempt, no fake degradation row); keep-fd frames raise — the zero-copy blend chain that would serve them is gated (state-dependent field wedge).
- neoruntime_ipc_sdk.draw.render_overlay_rgba(frame_w, frame_h, boxes=(), labels=None, scores=None, colors=None, thickness=2, polygons=(), tracks=())[source]
Render boxes + captions + polygons + tracks as a minimal straight-alpha RGBA overlay.
Returns
(rgba, x0, y0): an(h, w, 4)uint8 canvas holding every shape and its top-left position on the frame. Hand it toDspClient.blend_hw()for the hardware composite — the canvas is the union bbox of all shapes (clamped to the frame, floored at 16x16), so untouched pixels never enter the blend and the quota footprint stays small.polygonsis a sequence of(points, color)pairs drawn as closed outlines (zone shapes);tracksthe same shape drawn open (trajectories).pointsis any (N, 2) sequence of frame pixel coordinates;color=Nonefalls back to green like boxes.Straight alpha by construction: each shape is first drawn white-on-black as a coverage mask (cv2 LINE_AA captions give edge coverage t; rectangles stay hard-edged like
draw_boxes()), then shapes are colored in draw order and alpha is the mask union — so compositing witht*C + (1-t)*basereproduces the software output. Colors default to green; pick fromPALETTEby class_id to matchdraw_detections().
- neoruntime_ipc_sdk.draw.render_overlay_fragments(frame_w, frame_h, boxes=(), labels=None, scores=None, colors=None, thickness=2, polygons=(), tracks=())[source]
Render boxes as tight stroke fragments instead of one bbox canvas.
Same inputs and straight-alpha contract as
render_overlay_rgba(), but returns a list of(rgba, x, y)fragments to spread over oneDspClient.blend_hw()call (the daemon composites the whole overlay list in a single job, so extra fragments cost only their area). Each box becomes up to four thin canvases — caption+top edge, bottom edge, left edge, right edge — so a box pays for its2 * thicknessstroke perimeter plus its caption strip, not its area: a full-frame 1280x720 box drops from a 0.9 MP canvas (render, RGBA->ARGB repack, wire bytes and blend are all area-bound; ~3.7 MB per frame over the socket) to ~0.06 MP of 16 px strips. Polygons and tracks stay one canvas per shape (that shape’s own bbox, not the union of everything).Pixels are identical to
render_overlay_rgba()for non-overlapping shapes: every fragment is rasterized by the same backend at the same frame coordinates on a smaller canvas, and the fragments tile the shape extents without gaps or overlap. Two caveats: overlapping shapes composite marginally differently (an AA edge landing on another shape’s stroke blends against it instead of taking the union mask), and in the per-shape fallback below a caption wider than its shape clips at that shape’s extent (the fragment path itself widens a caption’s strip to its measured text extent instead). Call once per detection for exact single-canvas parity.Fragment count is bounded for the caller:
blend_hwcaps one job at 64 overlays and each box costs up to four fragments, so past ~15 boxes this falls back to one canvas per shape, and past 64 shapes to the one shared union canvas — the return always fits one blend job.
- neoruntime_ipc_sdk.draw.draw_polygons(image, shapes, thickness=2, closed=True)[source]
Draw polygon outlines (or open tracks) on an RGB array copy.
The software counterpart of
render_overlay_rgba()’s polygons/tracks legs, mirroringdraw_boxes()’ copy-in copy-out conventions — reach for it when the frame stays client-side and no blend is needed.- Parameters:
image (ndarray) – RGB uint8 array (H, W, 3).
shapes (Iterable) – iterable of
(points, color)pairs,pointsbeing any (N, 2) sequence of pixel coordinates (same schema asrender_overlay_rgba());color=Nonemeans green.thickness (int) – line thickness in pixels.
closed (bool) – close each outline (True for zones, False for tracks).
Returns: new RGB array; the input array is not modified.
draw_boxes
- neoruntime_ipc_sdk.draw_boxes(image, boxes, labels=None, scores=None, color=(0, 255, 0), thickness=2)[source]
Draw bounding boxes (pixel coordinates) on an RGB array copy.
- Parameters:
image (ndarray) – RGB uint8 array (H, W, 3).
boxes (Iterable) – iterable of (x1, y1, x2, y2) or BoundingBox-like objects.
labels (Sequence[str | None] | None) – optional per-box text (combined with scores when given).
scores (Sequence[float] | None) – optional per-box confidence.
thickness (int) – line thickness in pixels.
Returns: new RGB array; the input array is not modified.
draw_text
draw_detections
- neoruntime_ipc_sdk.draw_detections(image, result_or_objects, color=None)[source]
Draw an InferenceResult (or a list of DetectedObject) on an RGB copy.
Each object gets a box plus a “label score” caption. When color is None, a per-class color from PALETTE is chosen via class_id.
Routing: NV12 2D arrays ride the accel router (DSP blend when the daemon is reachable, the CPU mirror otherwise); RGB arrays go straight to the software raster (no doomed hardware attempt, no fake degradation row); keep-fd frames raise — the zero-copy blend chain that would serve them is gated (state-dependent field wedge).
draw_polygons
- neoruntime_ipc_sdk.draw_polygons(image, shapes, thickness=2, closed=True)[source]
Draw polygon outlines (or open tracks) on an RGB array copy.
The software counterpart of
render_overlay_rgba()’s polygons/tracks legs, mirroringdraw_boxes()’ copy-in copy-out conventions — reach for it when the frame stays client-side and no blend is needed.- Parameters:
image (ndarray) – RGB uint8 array (H, W, 3).
shapes (Iterable) – iterable of
(points, color)pairs,pointsbeing any (N, 2) sequence of pixel coordinates (same schema asrender_overlay_rgba());color=Nonemeans green.thickness (int) – line thickness in pixels.
closed (bool) – close each outline (True for zones, False for tracks).
Returns: new RGB array; the input array is not modified.
render_overlay_rgba
- neoruntime_ipc_sdk.render_overlay_rgba(frame_w, frame_h, boxes=(), labels=None, scores=None, colors=None, thickness=2, polygons=(), tracks=())[source]
Render boxes + captions + polygons + tracks as a minimal straight-alpha RGBA overlay.
Returns
(rgba, x0, y0): an(h, w, 4)uint8 canvas holding every shape and its top-left position on the frame. Hand it toDspClient.blend_hw()for the hardware composite — the canvas is the union bbox of all shapes (clamped to the frame, floored at 16x16), so untouched pixels never enter the blend and the quota footprint stays small.polygonsis a sequence of(points, color)pairs drawn as closed outlines (zone shapes);tracksthe same shape drawn open (trajectories).pointsis any (N, 2) sequence of frame pixel coordinates;color=Nonefalls back to green like boxes.Straight alpha by construction: each shape is first drawn white-on-black as a coverage mask (cv2 LINE_AA captions give edge coverage t; rectangles stay hard-edged like
draw_boxes()), then shapes are colored in draw order and alpha is the mask union — so compositing witht*C + (1-t)*basereproduces the software output. Colors default to green; pick fromPALETTEby class_id to matchdraw_detections().
使用示例
绘制检测框与标签
from neoruntime_ipc_sdk import draw_boxes
# boxes 为像素坐标 (x1, y1, x2, y2);labels/scores 与 boxes 一一对应
annotated = draw_boxes(
image,
boxes=[(120, 80, 360, 300), (400, 200, 620, 460)],
labels=["car", "person"],
scores=[0.92, 0.87],
color=(0, 255, 0),
thickness=2,
)
绘制任意文本
from neoruntime_ipc_sdk import draw_text
annotated = draw_text(
image, "FPS: 15.2", (12, 24),
color=(255, 255, 255), font_scale=0.5, thickness=1,
)
直接渲染推理结果
from neoruntime_ipc_sdk import InferenceClient, draw_detections
infer = InferenceClient()
result = infer.infer("yolov5m_vehicles", frame)
rgb = frame.to_rgb() # Frame 先物化(keep-fd 帧不能直接画)
# 接受 InferenceResult 或 list[DetectedObject],自动画框 + 标签 + 置信度
# SDK 0.7.4 起:NV12 2D 数组本身即走 DSP blend 路由,RGB 数组走软件光栅
annotated = draw_detections(rgb, result)
多边形与轨迹(区域/轨迹可视化,dsp-offload P2)
from neoruntime_ipc_sdk import draw_polygons, render_overlay_rgba
# shapes = [(points, color)];points 是 (N, 2) 像素坐标序列,
# color=None 用默认绿色。closed=False 画开放折线(轨迹)。
zone = [(80, 60), (560, 60), (560, 380), (80, 380)]
track = [(100, 240), (200, 200), (320, 210), (430, 260)]
annotated = draw_polygons(image, [(zone, (255, 192, 0)),
(track, (0, 200, 255))], closed=True)
# 轨迹单独画:draw_polygons(image, [(track, (0, 200, 255))], closed=False)
# 硬件腿:同样的 shapes 进 render_overlay_rgba 的 polygons/tracks,
# 与 boxes 一起并入最小画布并集,一次 blend_hw 合成
rgba, x0, y0 = render_overlay_rgba(
w, h, boxes, labels, scores, colors,
polygons=[(zone, (255, 192, 0))],
tracks=[(track, (0, 200, 255))],
)
annotated = dsp.blend_hw(nv12, [(rgba, x0, y0)])
Note
draw_* 函数返回**副本**,不修改传入图像;输入/输出均为 RGB
像素坐标(与 to_array 输出一致)。