Skip to content
Back to skills

Matting Inference

ASecurity

"Build, validate, and run the repository's MODNet matting pipeline

  • 247 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 9, 2026
toolspythonbashnodeapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned September 9, 2026

npx -y skills add VectorSpaceLab/AREX-Skill --skill matting-inference --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Matting Inference?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Matting Inference
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/vectorspacelab-matting-inference/badge)](https://www.skillsdirectory.com/skills/vectorspacelab-matting-inference)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "matting-inference"
description: "Build, validate, and run the repository's MODNet matting pipeline
  from a PyTorch checkpoint through fixed-shape ONNX and TensorRT, then blend
  image, video, camera, and background inputs."
disable-model-invocation: true
metadata:
  disco-role: operating
license: MIT
---

# MODNet Matting Inference

Use this skill when the task is to export MODNet, validate its ONNX graph,
build the repository's TensorRT engine, or run `trt_modnet.py` for image/video/
camera matting. The procedures are grounded in this repository at
`modnet/`, `trt_modnet.py`, `test_modnet.py`, and the MODNet-related files under
`utils/`.

This is an operating skill, not a model distribution. The skill does **not**
bundle the MODNet PyTorch checkpoint, a generated TensorRT engine, or the
third-party `modnet/onnx-tensorrt` submodule. Obtain model weights separately
under their upstream license (the README identifies the pretrained MODNet
weights as CC BY-NC-SA 4.0), and keep generated artifacts outside the skill
bundle. The repository checkout may contain `modnet/modnet.onnx`, but a runtime
must not assume that artifact is present in every checkout.

## Fast route

Run commands from the repository root unless a step explicitly says `cd modnet`.
The intended fixed-shape route is:

1. Obtain a compatible MODNet checkpoint, preferably the portrait matting
   checkpoint named in `modnet/README.md`.
2. Export a batch-1 ONNX model with width `512`, height `288`:

   ```bash
   cd modnet
   python -m torch2onnx.export --width 512 --height 288 \
       /path/to/modnet_webcam_portrait_matting.ckpt modnet.onnx
   cd ..
   ```

3. Validate the ONNX graph on CPU with ONNX Runtime; see
   [workflows.md](references/workflows.md).
4. Build an FP16 TensorRT engine with dimensions matching the ONNX export:

   ```bash
   cd modnet
   python onnx_to_tensorrt.py --width 512 --height 288 \
       modnet.onnx modnet.engine
   cd ..
   ```

   The script's CLI defaults are `640x480`, so do not rely on its defaults for
   the `512x288` export. Also inspect the input name before building: the
   exporter writes `input` (lowercase), while this historical builder passes
   `Input` (uppercase) to `profile.set_shape`. If TensorRT rejects `Input` as
   an unknown profile tensor, make the minimal local source correction to use
   the actual input name (`input`), then rerun the build. Do not silently use a
   profile shape or input name that differs from the ONNX graph.
5. From the repository root, run an input mode such as:

   ```bash
   python3 trt_modnet.py --image modnet/image.jpg
   ```

   `utils.modnet.TrtMODNet` loads `modnet/modnet.engine` by this exact
   repository-relative path; `trt_modnet.py` has no `--engine` option.

## Pipeline contract

### PyTorch to ONNX

`modnet/torch2onnx/export.py` constructs `MODNet()` with the MobileNetV2
backbone, loads the checkpoint into a CUDA `DataParallel` wrapper, switches to
evaluation mode, and calls `torch.onnx.export` with opset 11, input name
`input`, and output name `output`. The exported batch is fixed at 1 and the
export dimensions are fixed. The model implementation asserts that its input
height and width are divisible by 4; keep that invariant for custom dimensions.

The documented `512x288` context means **width 512, height 288**, and therefore
the tensor shape is `[1, 3, 288, 512]` (NCHW). Do not reverse width and height.
The exporter creates its dummy tensor as uniform values in `[-1, 1]` on CUDA;
it is not a CPU-only exporter. The checkpoint must match this repository's
MODNet architecture/state-dict keys. `backbone.py` has a separate optional
MobileNetV2 pretrained-checkpoint path, but the export script loads the supplied
MODNet checkpoint directly and does not invoke that path.

### ONNX validation

`modnet/test_onnx.py` is a small visual check. From `modnet/`, it reads
`image.jpg`, resizes it to `(512, 288)`, converts BGR to RGB, transposes to
CHW, casts to `float32`, and normalizes with `(pixel - 127.5) / 127.5`. It
creates an ONNX Runtime session without requesting CUDA and displays the
single output as a grayscale OpenCV window. The script discovers the graph's
input and output names at runtime. It does not save a result or assert a
metric, and it requires a GUI; treat a successful session plus a plausible
matte as the source-level acceptance signal, not as a benchmark.

For a headless or auditable check, use ONNX Runtime CPU to reproduce the same
preprocess, assert that the graph accepts `[1,3,288,512]`, assert one output
with a single-channel spatial matte, and record finite output values. Keep this
check separate from TensorRT: CPU ONNX validation proves graph execution and
pre/postprocessing, not CUDA/TensorRT parity.

### ONNX to TensorRT

`modnet/onnx_to_tensorrt.py` requires TensorRT 7 or newer, parses the ONNX graph
with the explicit-batch API, forces batch 1, allocates a 1 GiB workspace,
enables GPU fallback and FP16, and creates a fixed optimization profile. The
profile must agree with the graph's actual input tensor name and shape. The
script writes a serialized engine only after `build_engine` returns a non-None
engine.

The `--int8` and `--dla_core` flags exist in the parser but the implementation
raises `RuntimeError('INT8 not implemented yet')` or
`RuntimeError('DLA_core not implemented yet')`; they are not supported paths
for MODNet in this repository. Use the default FP16 route. The generated
engine is hardware/runtime-specific and must be rebuilt when the TensorRT,
CUDA, GPU/Jetson target, or relevant engine-building inputs change.

#### TensorRT 7.1 versus 7.2+

The repository README reports that TensorRT 7.1 fails on MODNet's
`InstanceNormalization` with an error like:

```text
UNSUPPORTED_NODE: ... InstanceNormalization does not support dynamic inputs!
```

TensorRT 7.2 fixes the issue for the standard Python builder route. On 7.2 or
later, use `modnet/onnx_to_tensorrt.py` after matching dimensions and correcting
the historical profile-name mismatch if needed. On 7.1, the documented
workaround is to fetch and build the `onnx-tensorrt` submodule locally, patch
its old CMake requirement as described in [workflows.md](references/workflows.md),
and invoke its `onnx2trt` binary with `-d 16 -v`. This is a version-bound
third-party build, not a bundled dependency; record the exact TensorRT,
onnx-tensorrt, compiler, and CUDA versions. Do not claim that the workaround
works on an untested modern combination.

### TensorRT runtime and matting

`utils/modnet.py` implements `TrtMODNet` for TensorRT 7+ and PyCUDA. It
initializes built-in TensorRT plugins, deserializes
`modnet/modnet.engine`, and expects exactly two bindings in order: `input` and
`output`. It requires float input/output bindings, input shape `[1,3,H,W]`,
and output shape `[1,1,H,W]`. The engine's H/W are used as the inference input
shape; the returned matte is resized back to the original frame's H/W.

Each frame is processed as follows:

1. Resize BGR input to the engine's `(W,H)` with `cv2.INTER_AREA`.
2. Convert BGR to RGB, transpose HWC to CHW, cast to `float32`.
3. Normalize each channel with `(x - 127.5) / 127.5`.
4. Copy the contiguous tensor to a pagelocked CUDA buffer and run
   `execute_async_v2`.
5. Reshape the output to the engine output's last two dimensions and resize it
   to the original frame shape.

`trt_modnet.py` blends the original BGR frame and a background using
`img * matte + bg * (1 - matte)`. The runtime therefore expects a matte whose
values behave like `[0,1]`; do not convert it to `[0,255]` before blending.
The source docstring's phrase “0 or 255 pixels” is stale relative to this
blend formula. `pycuda.autoinit` creates a CUDA context at import time, so help
or runtime checks can fail before argument parsing when PyCUDA/CUDA is absent.

## Input, background, demo, and recording behavior

`trt_modnet.py` combines `Camera`, `Background`, `BackgroundBlender`, and an
optional writer:

- `--image FILE`: read a still image repeatedly. Without `--do_resize`, its
  native dimensions become the output dimensions.
- `--video FILE`: read a video. `--video_looping` reopens it at EOF;
  `--do_resize --width W --height H` resizes frames to the requested output.
- `--rtsp URI`: open an RTSP H.264 stream through a detected GStreamer decoder;
  `--rtsp_latency` defaults to 200 ms.
- `--usb ID`: open `/dev/videoID`; the source defaults to a GStreamer USB path.
- `--gstr TEMPLATE`: format a GStreamer string with `{width}` and `{height}`.
- `--onboard ID`: select the Jetson onboard camera. The ID is parsed but the
  legacy pipeline itself does not interpolate it.
- `--width`/`--height`: default to `640x480`; live sources use these values,
  while image/video behavior depends on `--do_resize` as above.
- `--copy_frame`: copy live capture frames before processing. This avoids
  reusing a capture-owned array when inference or overlays outlive the read.
- `--background FILE`: a lowercase `.jpg` or `.png` is resized and repeated; a
  lowercase `.mp4` or `.ts` is read and looped; an empty value produces a black
  background. Other suffixes raise `ValueError`, and unreadable image/video
  sources fail during construction or reads.
- `--demo_mode`: changes the blender only. It cycles every 360 frames through
  black-background reveal, black background, replacement-background reveal,
  replacement background, original-background reveal, and original background.
  The sequence is documented precisely in [api-reference.md](api-reference.md).
- `--create_video NAME`: writes every blended frame. `utils/writer.py` tries a
  Jetson GStreamer/H.264 transport stream and otherwise uses OpenCV `mp4v`.
  The implementation appends `.ts` or `.mp4` to `NAME`; pass a basename rather
  than an already suffixed filename.

The display loop stops when the window closes, a source returns `None`, or ESC
is pressed. `F` toggles fullscreen. The writer and camera are released on
normal completion; headless operation is not implemented by the demo itself.

## Required checks before handing off a run

- Confirm the checkpoint, ONNX, and engine paths and record their provenance;
  never infer that a missing artifact can be downloaded automatically.
- Confirm ONNX input/output names and fixed shape. For the documented export,
  expect `input`, `output`, batch 1, and `[1,3,288,512]` input.
- Run the CPU ONNX check independently of the GPU engine check.
- Run the TensorRT builder with a profile name that exists in the parsed graph,
  dimensions matching the exported graph, and no unsupported `--int8` or
  `--dla_core` flags.
- Confirm the deserialized engine has exactly the two expected bindings and
  that a CUDA inference returns a finite matte at the original frame size.
- For video/camera runs, verify the selected source, background dimensions,
  writer output suffix, and a clean ESC/window-close shutdown.
- Use the bundled safe validator before execution when only configuration
  review is possible:

  ```bash
  python3 skills/disco/tensorrt-demos/sub-skills/matting-inference/scripts/validate-matting-config.py \
      --onnx modnet/modnet.onnx --engine modnet/modnet.engine \
      --export-width 512 --export-height 288
  ```

The validator performs no model import, CUDA initialization, file download,
subprocess execution, or file mutation. It checks configuration semantics only.
For detailed failure recovery, use [troubleshooting.md](troubleshooting.md).

## Source evidence

This skill was distilled from `modnet/README.md`, the complete
`modnet/torch2onnx/` exporter/model implementation, `modnet/test_onnx.py`,
`modnet/onnx_to_tensorrt.py`, `trt_modnet.py`, `test_modnet.py`, and the
MODNet runtime helpers `utils/modnet.py`, `utils/background.py`,
`utils/writer.py`, `utils/camera.py`, and `utils/display.py`. Repository-level
MODNet instructions and compatibility claims were cross-checked against the
MODNet section of `README.md`. The generated skill intentionally excludes the
uninitialized `modnet/onnx-tensorrt` source and all model/engine binaries.

Files in this skill

  • SKILL.md11.8 KB
  • api-reference.md8.2 KB
  • references/workflows.md12.5 KB
  • scripts/validate-matting-config.py6.7 KB
  • troubleshooting.md9.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…