# ModelConverter

> **Note**
> For managed online conversion, use [HubAI Conversion](https://docs.luxonis.com/cloud/hubai/model-registry/detailed-conversion.md). This page describes running ModelConverter locally.

## Overview

[ModelConverter](https://github.com/luxonis/modelconverter) is an open-source tool for converting neural network models into
deployment formats for Luxonis devices. It supports the RVC2, RVC3, RVC4, and Hailo platforms.

Local conversion has two parts:

 * The `modelconverter` Python package provides the CLI, configuration handling, input staging, caching, inference, benchmarking,
   and analysis tools.
 * Platform-specific Docker images contain the vendor conversion toolchains. This keeps OpenVINO, SNPE, and Hailo dependencies
   isolated from the host system.

## Installation

ModelConverter requires Python 3.10 or newer. Install the CLI from PyPI:

```bash
pip install modelconv
```

Install optional dependencies only when you need the corresponding tools:

```bash
pip install "modelconv[bench]"     # modelconverter benchmark
pip install "modelconv[analysis]"  # RVC4 analysis and visualization
```

Local conversion and inference require [Docker](https://docs.docker.com/engine/install/). Docker Desktop is recommended on Windows
and macOS; Ubuntu is recommended for native Linux installations.

Run the CLI as your regular user, without `sudo`. Make sure that user has permission to access the Docker daemon so generated
files remain user-owned.

Verify the installation:

```bash
modelconverter --version
modelconverter --help
```

## Supported Inputs and Platforms

ModelConverter accepts a standalone model, a YAML configuration file, or an [NN
Archive](https://docs.luxonis.com/software-v3/ai-inference/nn-archive.md). Model inputs may be local relative or absolute paths,
or remote URLs supported by the configured filesystem plugins, such as `s3://` and `gs://`.

Supported source model formats are:

 * ONNX (`.onnx`), supported by all platforms.
 * OpenVINO IR (`.xml` and `.bin`), supported for RVC2 and RVC3.
 * TensorFlow Lite (`.tflite`).

For ONNX models larger than 2 GB, keep the external data file next to the model and name it `<model>.onnx_data`. Include both
files, with the same naming convention, when using an NN Archive.

## Configure a Conversion

The recommended input is an NN Archive because it keeps the model and its metadata together. YAML configuration remains available
for standalone and advanced workflows. The complete schema and examples are maintained in
[`defaults.yaml`](https://github.com/luxonis/modelconverter/blob/main/configs/defaults.yaml) and the upstream [`configs`
directory](https://github.com/luxonis/modelconverter/tree/main/configs).

A compact single-stage configuration can look like this:

```yaml
name: resnet18
input_model: ./models/resnet18.onnx

shape: [1, 3, 224, 224]
layout: NCHW
data_type: float32

encoding:
  from: RGB
  to: BGR

mean_values: imagenet
scale_values: imagenet

calibration:
  path: ./calibration
  max_images: 100
  resize_method: RESIZE
```

Paths inside a YAML file are resolved relative to that file, not the directory from which ModelConverter is invoked. You can
therefore keep a configuration beside its model and calibration data and run it from anywhere.

### Inputs and Outputs

The common input and output fields are:

| Field | Description |
| --- | --- |
| `input_model` | Model path or remote URL. Required for each stage. |
| `input_bin` | OpenVINO IR weights file. Usually inferred from the matching `.xml` file. |
| `inputs` | Per-input names, shapes, layouts, data types, encodings, normalization, and optional frozen values. |
| `outputs` | Output tensor names. They are inferred when the source format provides them. |
| `shape` / `layout` / `data_type` | Global input settings used when they are not overridden for a specific input. |
| `encoding.from` | Color order expected by the source model. Defaults to `RGB`. |
| `encoding.to` | Color order expected at runtime. Defaults to `BGR`. |
| `mean_values` / `scale_values` | Per-channel normalization values or the `imagenet` preset. |
| `keep_intermediate_outputs` | Keep conversion intermediates. Defaults to `true`. |
| `onnx_simplification` | Use `onnxsim`, experimental `onnxslim`, or `false`. Defaults to `onnxsim`. |
| `onnx_optimizations` | Enable, disable, or configure ModelConverter's ONNX graph optimizations. |

The global input fields apply to every input. Values under an individual `inputs` entry take precedence for that input.

When `encoding` is a single value, ModelConverter uses it for both `encoding.from` and `encoding.to`. Keep mean and scale values
in the original channel order used during training; ModelConverter handles any required channel permutation.

### Calibration Data

Calibration data can be a directory containing images (`.jpg`, `.jpeg`, or `.png`), NumPy arrays (`.npy`), raw buffers (`.raw`),
or an LDF dataset identifier:

```yaml
calibration:
  path: dataset_name:split
  max_images: 100
  resize_method: PAD
```

Use `dataset_name:split:loader_plugin` to select a custom LDF loader. Multi-input LDF calibration datasets are not currently
supported.

Images are resized and converted according to the configuration. `.npy` and `.raw` files are used without preprocessing, so their
data type, shape, and layout must already be correct. RVC4 and Hailo calibration buffers must use NHWC layout.

When calibration data is omitted, ModelConverter generates random samples. This is useful for testing whether a model converts,
but real representative data should be used for production quantization. Prefer a held-out validation subset that reflects the
data the deployed model will receive; avoid reusing training samples when representative held-out data is available.

> **NN Archive calibration**
> An NN Archive stores model metadata and preprocessing, but it does not contain the calibration dataset. Supply `calibration.path` when converting an archive with a quantized RVC4 or Hailo flow. Otherwise, ModelConverter falls back to random calibration data.

```bash
modelconverter convert rvc4 --path ./model.tar.xz \
  calibration.path ./calibration
```

Calibration is used by the default RVC4 and Hailo quantization flows, optional for RVC3, and ignored for RVC2. Modes that disable
calibration, such as RVC4 `FP16_STANDARD`, do not require a calibration dataset.

### Platform-Specific Settings

| Platform | Common settings |
| --- | --- |
| RVC2 | `number_of_shaves`, `superblob`, `compress_to_fp16`, `n_workers`, `mo_args`, and `compile_tool_args`. |
| RVC3 | `pot_target_device`, `compress_to_fp16`, `mo_args`, and `compile_tool_args`. |
| RVC4 | `quantization_mode`, `htp_socs`, `optimization_level`, `encodings`, `strict_quantization_overrides`, and additional SNPE
arguments. |
| Hailo | `hw_arch`, `optimization_level`, `compression_level`, `batch_size`, `alls`, and calibration controls. |

RVC4 provides these predefined `quantization_mode` values:

| Mode | Precision and tradeoff |
| --- | --- |
| `INT8_STANDARD` | Default W8A8 quantization. It normally provides the best throughput and smallest model size, and requires
representative calibration data. |
| `INT8_ACCURACY_FOCUSED` | W8A8 with enhanced parameter and activation quantizers. It may improve accuracy while retaining 8-bit
weights and activations. |
| `INT8_INT16_MIXED` | 8-bit weights with 16-bit activations. It can improve numerical stability and accuracy at the cost of
throughput and model size. |
| `INT8_INT16_MIXED_ACCURACY_FOCUSED` | The mixed W8A16 mode with enhanced parameter and activation quantizers. It may further
improve accuracy with the same throughput and size tradeoffs as the mixed mode. |
| `INT16_STANDARD` | 16-bit weights and activations. It provides a higher-precision integer path at a greater performance and size
cost than INT8. |
| `FP16_STANDARD` | Floating-point conversion without calibration. It favors numerical stability but generally has lower
throughput and a larger model than INT8. |
| `CUSTOM` | Leaves quantization behavior to custom SNPE arguments and optional encoding overrides. Use it when a predefined mode
does not match the required precision strategy. |

> **Note**
> Every predefined RVC4 quantization mode except `CUSTOM` controls the corresponding SNPE arguments and overrides conflicting values supplied through `snpe_onnx_to_dlc_args`, `snpe_dlc_quant_args`, or `snpe_dlc_graph_prepare_args`.

## Run a Conversion

Run a conversion from a configuration file, NN Archive, or standalone model:

```bash
modelconverter convert <platform> --path <config_archive_or_model> [configuration overrides]
```

For example:

```bash
modelconverter convert rvc4 \
  --path ./resnet18.yaml \
  --output-dir resnet18-rvc4 \
  calibration.max_images 50
```

Configuration overrides are key-value pairs after the CLI options. For list entries, address the item by index:

```bash
modelconverter convert rvc4 \
  --path ./resnet18.yaml \
  inputs.0.name input_1 \
  inputs.0.shape "[1,3,256,256]" \
  outputs.0.name output_0
```

If you rename the default `stage_name`, prefix overrides with the new stage path, for example `stages.encoder.inputs.0.shape`.

### Conversion Options

| Option | Description |
| --- | --- |
| `--path` | Configuration file, NN Archive, standalone model, or remote URL. |
| `--output-dir` | Name of the directory created below `output/`. |
| `--to` | Output packaging: `nn_archive` (default) or `native`. |
| `--main-stage` | Main stage used when packaging a multi-stage conversion as an NN Archive. |
| `--tool-version` | Vendor toolchain version used by the platform image. |
| `--image` / `--docker-image` | Explicit Docker image. A complete image tag takes precedence over `--tool-version`. |
| `--archive-preprocess` | Store preprocessing metadata in the NN Archive instead of modifying the model. |
| `--memory` | Limit container memory, for example `4GiB` or `512M`. |
| `--cpus` | Limit container CPU cores; fractional values such as `0.5` are supported. |
| `--gpu` / `--no-gpu` | Enable or disable the NVIDIA runtime for Hailo containers. |
| `--dev` | Build and run the development image with the local source mounted. |

Run `modelconverter convert --help` for the full set of options.

## Docker Images and Tool Versions

The CLI pulls a matching official image when one is available. Current official images are hosted in the [Luxonis GitHub Container
Registry](https://github.com/orgs/luxonis/packages?tab=packages&q=modelconverter):

| Platform | Available official tool versions | Default |
| --- | --- | --- |
| RVC2 | OpenVINO `2021.4.0`, `2022.3.0` | `2022.3.0` |
| RVC3 | OpenVINO `2022.3.0` | `2022.3.0` |
| RVC4 | SNPE `2.32.6`, `2.41.0` | `2.41.0` |
| Hailo | Build locally from Hailo AI Software Suite | `2025.04` |

Select another available version with `--tool-version`:

```bash
modelconverter convert rvc4 --tool-version 2.41.0 --path ./model.onnx
```

When an official image is unavailable, the CLI can build an image from the repository Dockerfile if its vendor dependencies are
available. Locally built images use `luxonis/modelconverter-<platform>:<tool-version>-latest`. Pass a custom image explicitly when
it does not follow that convention:

```bash
modelconverter convert rvc4 \
  --image luxonis/modelconverter-rvc4:custom \
  --path ./model.onnx
```

For RVC4 local builds, supplying a full SNPE build version such as `2.41.0.251128` lets the CLI download that version from
Qualcomm's catalog when available. A short version such as `2.41.0` requires a matching local image or archive. See [Conversion
Troubleshooting](https://docs.luxonis.com/software-v3/ai-inference/conversion/troubleshooting.md) for deployment compatibility
guidance.

Hailo images must be built locally. Obtain the matching Hailo AI Software Suite image from Hailo and follow the [upstream build
instructions](https://github.com/luxonis/modelconverter#build-instructions). GPU-accelerated Hailo conversion additionally
requires the [NVIDIA Container
Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html).

## Inputs, Outputs, and Cache

The CLI accepts normal host paths and stages required inputs in an automatically managed cache at
`${XDG_CACHE_HOME:-~/.cache}/modelconverter`.

ModelConverter copies only the files referenced by the configuration, deduplicates them by content, and reuses unchanged inputs.
The default cache budget is 50 GiB; least-recently-used entries are removed before a conversion when necessary. Files used by an
active conversion are not removed.

Inspect or clear the cache with:

```bash
modelconverter cache info
modelconverter cache clean
modelconverter cache clean -y
```

Set `MODELCONVERTER_CACHE_MAX_SIZE` to change the budget, or set it to `0` for no limit:

```bash
MODELCONVERTER_CACHE_MAX_SIZE=20GiB modelconverter convert rvc4 --path ./model.onnx
```

Results are written below `output/` in the current working directory:

```text
output/
└── resnet18-rvc4/
    ├── resnet18.onnx
    ├── resnet18.dlc
    ├── modelconverter.log
    ├── config.yaml
    ├── buildinfo.json
    └── intermediate_outputs/
```

If `--output-dir` is omitted, ModelConverter generates a name from the model, platform, date, and time. It replaces an existing
directory only when the directory is empty or is marked as the result of an earlier ModelConverter operation. It refuses to
overwrite unrelated content.

## Multi-Stage Conversion

Put multiple models under `stages` when the output of one stage supplies calibration data to another. A linked calibration entry
identifies the preceding `stage` and either its `output` or a custom post-processing `script`.

```yaml
stages:
  detector:
    input_model: ./detector.onnx

  recognizer:
    input_model: ./recognizer.onnx
    calibration:
      stage: detector
      output: features
```

Specify `--main-stage` when producing an NN Archive from a multi-stage configuration. See the upstream
[`multistage.yaml`](https://github.com/luxonis/modelconverter/blob/main/configs/multistage.yaml) example for a complete
configuration.

## Package an NN Archive

Use the `archive` command to package a standalone model and inferred metadata without running a platform conversion:

```bash
modelconverter archive ./model.onnx --save-path ./model.tar.xz
```

The destination can also be a remote URL supported by LuxonisML. Use `--put-file-plugin` when the destination requires a specific
registered upload plugin.

## Inference

Run inference on a converted model with:

```bash
modelconverter infer <platform> \
  --model-path <converted_model> \
  --input-path <input_directory> \
  --output-dir <output_name> \
  --config <config_or_archive>
```

The input directory must contain one subdirectory per model input, named after that input. Each directory can contain images,
`.npy` arrays, or `.raw` buffers. Images are preprocessed from the configuration; arrays and raw buffers are passed through
unchanged.

Inference results are written to `output/<output_name>/`, with a log at `output/<output_name>.log`. ModelConverter marks its
inference output directories so a repeated run can safely replace earlier results without deleting unrelated files.

## Benchmarking

See the dedicated [Benchmarking guide](https://docs.luxonis.com/software-v3/ai-inference/benchmarking.md) for installation,
supported platforms and artifacts, device connection requirements, and usage examples.

## RVC4 Analysis

The `analysis` extra provides tools for comparing ONNX and DLC layer outputs, measuring per-layer cycle usage on an RVC4 device,
and visualizing the resulting CSV files.

```bash
modelconverter analyze \
  --dlc-model-path output/<conversion>/model.dlc \
  --onnx-model-path output/<conversion>/intermediate_outputs/model-modified.onnx \
  --image-dirs ./input_images

modelconverter visualize output/analysis/<model_name>
```

Use the modified ONNX model from `intermediate_outputs` as the reference because it includes preprocessing and graph
transformations applied before DLC conversion. Use the final top-level DLC as the default comparison target. Analysis requires an
RVC4 device accessible through ADB with `snpe-net-run` and `snpe-diagview` available.

## Interactive Shell

Open a shell inside the selected platform image:

```bash
modelconverter shell rvc4
```

Run a single command instead of an interactive shell with `--command`:

```bash
modelconverter shell rvc4 --command "snpe-net-run --help"
```
