# ModelConverter

> 有关在线使用 ModelConverter 工具的指南，请参考
> [HubAI 转换](https://docs.luxonis.com/cloud/hubai/model-registry/detailed-conversion.md)
> 。

## 概述

ModelConverter 是我们用于将神经网络模型本地转换为适用于 Luxonis 设备的部署格式的[开源](https://github.com/luxonis/modelconverter)工具。 它包括：

 * ModelConverter Docker 镜像 - 针对特定目标的容器镜像，捆绑了所需的转换工具链。
 * ModelConverter CLI - modelconverter 命令，用于运行转换、打开交互式 shell 以及访问推理、基准测试和分析工具。

## 安装

ModelConverter 要求系统上已安装 Docker。 建议使用 Ubuntu 操作系统以获得最佳兼容性。 在 Windows 或 macOS 上，建议使用 [Docker
Desktop](https://www.docker.com/products/docker-desktop) 进行安装。
否则，请根据操作系统的官方[网站](https://docs.docker.com/engine/install/)上的安装说明进行操作。

ModelConverter CLI 可以从 Python 包索引 (PyPI) 安装，命令如下：

```bash
pip install modelconv
```

运行 modelconverter --help 查看可用的命令和选项。

高级工作流可使用可选扩展：

 * pip install "modelconv[bench]" 用于 modelconverter benchmark
 * pip install "modelconv[analysis]" 用于 RVC4 DLC 分析与可视化

当本地镜像不可用时，CLI 可以在可能的情况下自动构建它们。有关特定目标的镜像可用性和先决条件，请参考[仓库构建说明](https://github.com/luxonis/modelconverter#local-usage)。

## 准备工作

### 模型来源

感兴趣的模型应为以下格式之一：

 * ONNX (.onnx)，
 * OpenVINO IR (.xml 和 .bin)，或
 * TensorFlow Lite (.tflite)。

模型文件可以是独立的，也可以打包为 [NN Archive](https://docs.luxonis.com/software-v3/ai-inference/nn-archive.md)。

### 校准数据（可选）

如果您不打算在转换过程中对模型进行量化，可以跳过此步骤。 否则，请准备一个包含用于指导量化的图像文件（.jpg、.png 或 .jpeg）的目录。 ModelConverter 会自动将它们处理为合适的格式。 请确保用于校准的图像与用于训练模型的图像不同。
通常，验证数据集用于此目的。 此外，您也可以提供 .npy 或 .raw 文件作为校准数据。 但请注意，这些文件不会进行自动处理，因此请确保正确准备它们 （例如，对于 RVC4 转换，布局需为 NHWC）。

### 共享文件夹

使用 CLI 时，在当前工作目录中保留一个 shared_with_container 目录。它会被挂载到转换容器内的 /app/shared_with_container/ 路径下。

推荐的目录结构如下：

 * archives 用于存储 NN Archive，
 * calibration_data 用于存储校准数据，
 * configs 用于存储配置文件，
 * models 用于存储模型文件，
 * outputs 用于存储转换输出。

可运行以下命令创建文件夹：

```bash
mkdir shared_with_container
cd shared_with_container
mkdir archives calibration_data configs models outputs
```

只要文件在容器内可见，此结构并非强制要求，但它有助于组织本地和下载的资源。ModelConverter 首先检查提供的路径，然后相对于 /app/shared_with_container/ 进行解析。可使用 --output-dir 设置
output_dir；否则，它将根据模型名称、目标名称和时间戳自动生成。

## 转换

转换通过 ModelConverter CLI 运行。 整个过程由 [转换参数](#Parameters) 引导。 您可以在 [配置文件](#Config%20File) 中定义它们，或者将模型来源作为 [NN
Archive](https://docs.luxonis.com/software-v3/ai-inference/nn-archive.md) 提供，ModelConverter 将自动为您填写转换参数。 此外，您可以在 CLI
上传递键值覆盖，以在单次运行中更改转换参数。

要运行转换：

 1. 为目标模型准备一个配置文件或 NN Archive。
 2. 如果使用本地文件，请将相关的模型文件、配置文件、NN Archive 文件和校准数据放入 shared_with_container 的子目录中。 如果从 NN Archive 进行转换，则无需提供模型文件。
    校准数据为可选，仅当您计划在转换过程中量化模型时才需提供。
 3. 使用 --path 参数指向挂载文件夹内的配置文件或 NN Archive 来运行转换。 或者，也可以提供 s3:// 和 gcs:// URL。

```bash
modelconverter convert <platform> --path <url_or_path> [ conversion parameter overrides ]
```

### 常用 CLI 选项

| 选项 | 描述 |
| --- | --- |
| `--tool-version` | 选择底层转换工具版本。 |
| `--image` | 使用特定的 Docker 镜像，而不是默认的标签查找。 |
| `--output-dir` | 在 `shared_with_container/outputs` 下设置输出目录名称。 |
| `--to` | 选择输出打包格式，例如 `native` 或 `nn_archive`。 |
| `--archive-preprocess` | 将预处理步骤存储在 NN Archive 中，而不是嵌入到模型中。 |

> 对于本地构建的镜像，CLI 期望标签格式为
> `luxonis/modelconverter-rvc4:<tool-version>-latest`
> 。如果您使用自定义标签，请使用
> `--image`
> 明确传递。

> 对于
> `RVC4`
> ，完整的 SNPE 构建版本（例如
> `2.32.6.250402`
> ）允许 CLI 在首次构建时自动下载归档，前提是该版本存在于高通的目录中。短版本（如
> `2.32.6`
> ）则假定归档或镜像已本地可用。要为您的部署目标选择合适的 SNPE 版本，请参阅
> [转换疑难解答中的 SNPE 兼容性表](https://docs.luxonis.com/software-v3/ai-inference/conversion/troubleshooting.md)
> 。

> 对于超过 2 GB 的 ONNX 模型，外部数据文件必须与模型位于同一目录，且命名为
> `<model>.onnx_data`
> 。如果从 NN Archive 转换，请在归档中同时包含
> `.onnx`
> 文件和对应的
> `.onnx_data`
> 文件。

> 请注意，NN Archive 不包含任何校准数据信息，因此您必须通过设置
> *overrides*
> 中的
> `calibration`
> 参数来手动提供校准数据。 使用量化转换为 RVC4 的示例：
> ```bash
> modelconverter convert rvc4 --path archives/<nn_archive>.tar.xz \
> calibration.path calibration_data/<calibration_data_dir>
> ```

> 请注意，如果使用配置文件进行转换，并且您修改了
> [默认阶段名称](https://github.com/luxonis/modelconverter/blob/main/shared_with_container/configs/defaults.yaml)
> （
> `stages.stage_name`
> ），则必须在
> *overrides*
> 中提供每个阶段的完整路径。例如，如果阶段名称改为
> `stage1`
> ，则使用
> `stages.stage1.calibration.path`
> 而不是仅仅
> `calibration.path`
> 。
> ```bash
> modelconverter convert rvc4 --path configs/<config_file>.yaml \
> stages.stage1.calibration.path calibration_data/<calibration_data_dir>
> ```

或者，您也可以不使用 ModelConverter CLI，而是通过 docker run 命令运行转换：

```bash
docker run --rm -it \
    -v $(pwd)/shared_with_container:/app/shared_with_container/ \
    luxonis/modelconverter-<platform>:<tool-version>-latest \
    convert <platform> \
    --path <s3_url_or_path> [ conversion parameter overrides ]
```

## 多阶段转换

ModelConverter 还支持多阶段转换，即一个模型的输出作为另一个模型的输入。这通过配置文件中的 stages 部分进行配置。当前示例请参阅
[defaults.yaml](https://github.com/luxonis/modelconverter/blob/main/shared_with_container/configs/defaults.yaml) 和
[示例配置目录](https://github.com/luxonis/modelconverter/tree/main/shared_with_container/configs)。

## 交互式 Shell

如果您需要在容器内检查工具链或手动运行厂商工具，可以打开交互式 shell：

```bash
modelconverter shell rvc4
```

## 参数

以下部分总结了最常用的转换参数及其默认值。完整的当前选项集请参阅
[defaults.yaml](https://github.com/luxonis/modelconverter/blob/main/shared_with_container/configs/defaults.yaml) 和
[当前示例配置](https://github.com/luxonis/modelconverter/tree/main/shared_with_container/configs)。

### 顶层参数

| 参数 | 描述 | 默认值 |
| --- | --- | --- |
| `input_model` | 模型源文件的路径。可以是本地路径、s3 或 gcs URL。必填。 | - |
| `inputs` | 模型输入列表。 | - |
| `outputs` | 模型输出列表。 | - |
| `disable_onnx_simplification` | 禁用 ONNX 简化。 | `False` |
| `disable_onnx_optimization` | 禁用 ONNX 优化。 | `False` |
| `keep_intermediate_outputs` | 不删除中间文件。 | `True` |

### 输入参数

inputs 是模型每个输入的参数列表。每个输入可以包含以下参数：

| 参数 | 描述 | 默认值 | 示例 |
| --- | --- | --- | --- |
| `name` | 输入名称。 | - | `"input_0"` |
| `shape` | 输入形状。 | - | `[1, 3, 224, 224]` |
| `layout` | 输入布局。 | - | `"NCHW"` |
| `data_type` | 输入数据类型。 | - | `"float32"` |
| `encoding` | 输入编码。可选值：`RGB`、`BGR`、`GRAY` 或 `NONE` | - | `"RGB"` |
| `encoding.from` | 源模型期望的输入编码。 | `"RGB"` | `"RGB"` |
| `encoding.to` | 导出的模型期望的输入编码。 | `"BGR"` | `"BGR"` |
| `mean_values` | 用于归一化输入的均值，遵循原始模型的通道顺序。可以是单个数字、数字列表，或字符串 `"imagenet"`（表示 ImageNet 归一化）。 | - | `[ 123.675, 116.28, 103.53 ]` |
| `scale_values` | 用于归一化输入的缩放值，遵循原始模型的通道顺序。可以是单个数字、数字列表，或字符串 `"imagenet"`（表示 ImageNet 归一化）。 | - | `[ 58.395, 57.12, 57.375 ]` |
| `calibration` | 指定如何校准输入。详情请参阅 [校准参数](#Calibration%20Parameters)。 | - | - |

> `inputs`
> 列表的参数也可以在
> [顶层](#Top-level)
> 全局配置，省略
> `name`
> 参数，此时这些参数将应用于所有模型输入。如果这些参数也在
> `inputs`
> 列表内定义，则会覆盖针对
> `name`
> 参数指定输入的全局配置。如果未指定任何输入，则将从模型推断得出。

> 当
> `encoding`
> 设置为单个值时，该值会自动同时应用于
> `encoding.from`
> 和
> `encoding.to`
> 。如需使用不同的值，可以分别显式设置
> `encoding.from`
> 和
> `encoding.to`
> 。

### 输出

| 参数 | 描述 | 默认值 | 示例 |
| --- | --- | --- | --- |
| `name` | 输出名称。 | - | `"output_0"` |
| `shape` | 输出形状。 | - | `[1, 1000]` |
| `layout` | 输出布局。 | - | `"NC"` |
| `data_type` | 输出的数据类型。 | - | `"float32"` |

如果未指定输出，则将根据模型推断得出。

### 校准

校准数据可以通过两种方式指定：

#### 随机

如果未提供校准数据，工具将生成随机数据用于校准。 不建议使用随机校准数据，因为这可能导致次优的量化结果。 此选项作为快速测试转换过程的方式。

| 参数 | 描述 | 默认值 |
| --- | --- | --- |
| `max_images` | 用于校准的图像数量。 | `20` |
| `min_value` | 输入数据的最小值。 | `0.0` |
| `max_value` | 输入数据的最大值。 | `255.0` |
| `mean` | 输入数据的均值。 | `127.5` |
| `std` | 输入数据的标准差。 | `35.0` |
| `data_type` | 输入数据的数据类型。 | `"float32"` |

#### 引导式

此校准方法使用真实图像对模型进行校准。

| 参数 | 描述 | 默认值 |
| --- | --- | --- |
| `path` | 校准数据的路径。可以是本地路径、s3 或 gcs 网址。 | - |
| `max_images` | 用于校准的图像数量。默认使用全部图像。 | `-1` |
| `resize_method` | 如何调整图像大小以匹配模型输入形状。可选值：`"resize"`、`"pad"` 或 `"crop"`。 | `"resize"` |

### 平台特定参数

以下参数针对各个目标平台：

#### RVC2

| 参数 | 描述 | 默认值 | 示例 |
| --- | --- | --- | --- |
| `superblob` | 将模型编译为超 blob 格式。 | `True` | - |
| `compress_to_fp16` | 将模型权重压缩为 FP16 精度。 | `True` | - |
| `number_of_shaves` | 使用的 SHAVE 数量。仅当超 blob 转换禁用时使用。 | `8` | - |
| `number_of_cmx_slices` | 使用的 CMX 切片数量。仅当超 blob 转换禁用时使用。 | `8` | - |
| `mo_args` | 模型优化器的附加参数列表。以此方式提供的参数将**始终**优先于 ModelConverter 内部逻辑所指定的参数。 | `[]` | `["--use_legacy_frontend"]` |
| `compile_tool_args` | 编译工具的附加参数列表。以此方式提供的参数将**始终**优先于 `ModelConverter` 内部逻辑所指定的参数。 | `[]` | `["-ov_api_1_0"]` |

#### RVC4

| 参数 | 描述 | 默认值 | 示例 |
| --- | --- | --- | --- |
| `snpe_onnx_to_dlc_args` | SNPE ONNX 转 DLC 工具的附加参数列表。 | - | `["--batch", "6"]` |
| `snpe_dlc_quant_args` | SNPE DLC 量化工具的附加参数列表。 | - | `["--weights_bitwidth=16"]` |
| `snpe_dlc_graph_prepare_args` | SNPE DLC 图准备工具的附加参数列表。 | - | `["--htp_archs=v73"]` |
| `keep_raw_images` | 在中间数据中保留用于校准的原始图像。 | `False` | - |
| `use_per_channel_quantization` | 对卷积、反卷积和全连接运算中的权重和偏置启用逐轴元素量化。 | `True` | - |
| `use_per_row_quantization` | 对矩阵乘法和全连接运算启用逐行量化。 | `False` | - |
| `htp_socs` | 目标 HTP SoC 列表。 | `["sm8550"]` | `["sm8550", "sm8650", "qcs6490"]` |
| `optimization_level` | DLC 图准备的优化级别。可用选项为 `1`、`2` 和 `3`。 | `2` | - |
| `quantization_mode` | 预定义的量化模式。 | `INT8_STANDARD` | - |

量化模式

在 CLI 中覆盖时，使用 rvc4.quantization_mode 在 RVC4 转换的不同预定义量化模式之间进行选择。可用模式有：

 * INT8_STANDARD：带校准的标准 INT8 量化（默认），以获得最佳性能（FPS）和模型大小。
 * INT8_ACCURACY_FOCUSED：带校准的 INT8 量化。此模式采用更先进的量化技术，可能在不降低性能或增加模型大小的情况下提高准确性（取决于模型）。
 * INT8_INT16_MIXED：带校准的混合 INT8 和 INT16 量化。此模式在所有层使用 8 位权重和 16 位激活，以提高数值稳定性和准确性，但会降低性能（FPS）并增加模型大小。
 * INT8_INT16_MIXED_ACCURACY_FOCUSED：带校准的混合 INT8 和 INT16 量化，采用更先进的量化技术，可能提高准确性，但会降低性能（FPS）并增加模型大小。
 * FP16_STANDARD：不带校准的 FP16 量化，适用于需要更高准确性和数值稳定性的模型，但会牺牲性能（FPS）并增加模型大小。
 * CUSTOM：自定义量化模式，用户可以在配置文件或命令行参数中指定更高级的选项。

> 当
> `quantization_mode`
> 设置为
> `CUSTOM`
> 以外的任何值时，该模式的默认设置将覆盖配置文件或命令行参数中提供的任何自定义设置（通过
> `rvc4.snpe_onnx_to_dlc_args`
> 、
> `rvc4.snpe_dlc_quant_args`
> 或
> `rvc4.snpe_dlc_graph_prepare_args`
> 覆盖选项）。

### 配置文件

转换参数可以在一个 .yaml 配置文件中定义。 请参阅下面的示例，或查阅更多 [示例](https://github.com/luxonis/modelconverter/tree/main/shared_with_container/configs)
获取更多信息。

```yaml
# 相对于 `shared_with_container` 目录的本地路径
input_model: models/model.onnx

mean_values: imagenet
scale_values: imagenet
data_type: float32
shape: [ 1, 3, 256, 256 ]

# ONNX 模型期望 RGB 输入，
# 导出的模型将期望 BGR 输入
encoding:
  from: RGB
  to: BGR

calibration:
  # 校准路径可以是 s3 url
  path: s3://url/to/calibration_data.zip
  max_images: 20
```
