Skip to content

nvmmsecondaryinfer

TensorRT cascade classifier on detected objects. An in-place passthrough on video/x-raw(memory:NVMM) that reads the upstream GstNvmmDetMeta (from nvmminfer, ideally with nvmmtracker ids), VIC-crops each detection's region out of the NV12 frame, stretch-resizes it to the classifier's input, runs a TensorRT engine on it, and attaches the results as a GstNvmmClassMeta sibling meta — index-aligned with the det meta, like the motion meta. No DeepStream dependency.

The element is multi-rate: a track is re-inferred only every infer-interval frames, and between runs the per-tracker_id cache serves the last result (fresh=0 in the meta). Untracked detections (tracker_id == 0) cannot be cached and re-infer every frame, so put nvmmtracker upstream. Cached tracks unseen for max-track-age frames are dropped.

Preprocessing uses the same device-side path as nvmminfer (VIC crop+resize → NPP planarize/convert), extended with optional per-channel normalization: y = (x * net-scale-factor - offsets[c]) / std-values[c], in the engine's channel order. NPP runs through the _Ctx stream API, so the element does not touch the process-global NPP stream that nvmminfer binds to its own stream.

The engine must be a classification head: input 1x3xHxW FP32, output a per-class score vector ([1,C], [1,C,1,1] or [C]) FP32. Regions are inferred sequentially on a batch-1 engine; with the interval cache the per-frame inference count stays small.

Properties

Property Type Default Notes
engine-file string Serialized TensorRT classifier engine (required; build with trtexec)
labels-file string One class label per line (else class<N>)
infer-interval uint 10 Re-classify a track every N frames (1 = every frame)
max-track-age uint 60 Drop a cached track unseen this many frames
min-roi-size uint 16 Skip detections narrower/shorter than this (surface px)
net-scale-factor double 1/255 Pixel scale applied during preprocess
offsets string Per-channel mean "v0,v1,v2" subtracted after scaling (engine channel order)
std-values string Per-channel std "v0,v1,v2" divided after offsets
color-order enum rgb rgb / bgr — channel order the engine expects
output-activation enum softmax softmax over logits, or none if the engine already outputs probabilities
conf-threshold double 0.0 Minimum top-1 score to attach (and cache) a result

Example

ResNet50 fp16 (built with trtexec from the ONNX that ships with TensorRT under /usr/src/tensorrt/data/resnet50/, torchvision normalization) behind the YOLO detector and tracker:

gst-launch-1.0 ... ! nvmminfer engine-file=yolo11n_fp16.engine ! nvmmtracker \
  ! nvmmsecondaryinfer engine-file=resnet50_fp16.engine \
      labels-file=class_labels.txt output-activation=none \
      net-scale-factor=0.003921569 offsets="0.485,0.456,0.406" \
      std-values="0.229,0.224,0.225" conf-threshold=0.3 \
  ! nvmmdrawdet ! ...   # label: "cat #1 85% [tiger cat 55%]"

nvmmdrawdet renders the classification as a [label conf%] suffix in the box label. Classification costs ~2 ms GPU per region (ResNet50 fp16 on Orin); the interval cache amortizes that across frames. See Inference graphs for the full cascade and fusion compositions.