# 使用 OpenVino 进行手动转换（RVC2 和 RVC3）

## 概述

RVC2 和 RVC3 的转换基于 OpenVINO 工具包。 ModelConverter Docker 镜像 提供了所有必要的工具。 安装 ModelConverter CLI 如下：

```bash
pip install modelconv
```

然后运行：

```bash
modelconverter shell <platform>
```

其中 platform 表示你要为目标平台进行转换，即 rvc2 或 rvc3。

这相当于从 luxonis/modelconverter-<platform>:latest 镜像启动一个 Docker 容器， 并将其作为交互式终端会话（-it）运行，同时使用 --rm 标志确保退出会话后容器自动删除：

```bash
docker run --rm -it \
    -v $(pwd)/shared_with_container:/app/shared_with_container/ \
    luxonis/modelconverter-<platform>:latest
```

或者，你也可以自行安装 OpenVino 工具包，运行：

```bash
pip install openvino-dev==2022.3
```

在以下章节中，我们将逐步说明转换过程。

## 简化模型（可选）

为了获得性能最优的模型，建议在转换步骤之前进行模型简化。 对于 .onnx 模型，可以运行如下简化命令：

```bash
pip install onnxsim
onnxsim <onnx模型路径> <简化后的onnx模型路径>
```

## 编译 OpenVINO IR

首先将模型从其原始格式转换为 OpenVINO 中间表示（IR） 格式。 该格式包含两个文件：编码网络拓扑的 .xml 文件，以及存储模型权重和偏置的 .bin 文件。 使用 OpenVINO
[模型优化器（v2022.3.0）](https://docs.openvino.ai/2022.3/openvino_docs_MO_DG_Deep_Learning_Model_Optimizer_DevGuide.html)
进行此转换，支持以下源模型格式：

 * ONNX
 * TensorFlow
 * PyTorch
 * PaddlePaddle
 * MXNet
 * Kaldi
 * Caffe

要将模型转换为 IR，请运行：

```bash
mo --input_model <（未简化/已简化的）源模型路径> --compress_to_fp16
```

注意，建议使用 --compress_to_fp16 参数以在设备上获得最佳性能。 更多详情请参见[此处](https://docs.openvino.ai/2022.3/openvino_docs_MO_DG_FP16_Compression.html)。

> 有关转换选项的完整列表，请查阅
> `mo --help`
> 。 如果计划在 Luxonis 生态系统中使用模型，建议设置标志，使模型期望未归一化的 BGR 输入。 因此，如果模型期望 RGB 输入或需要归一化，请务必设置
> `--reverse_input_channels`
> 、
> `--mean_values`
> 和
> `--scale_values`
> 标志。

## 量化（仅 RVC3）

如果为 RVC3 进行转换，则必须在编译为 BLOB 之前，使用 [OpenVINO 训练后优化工具（POT）](https://docs.openvino.ai/2022.3/pot_introduction.html) 进行模型量化。
请参考以下[示例](https://docs.openvino.ai/2022.3/pot_configs_examples_README.html)获取指导。

## 编译 BLOB

模型转换为 OpenVINO 的 IR 格式后，下一步是将其编译为可在 MYRIAD 设备上进行推理并转换为 BLOB 格式。 使用 [OpenVINO
编译工具（v2022.3.0）](https://docs.openvino.ai/2022.3/openvino_inference_engine_tools_compile_tool_README.html) 进行此工作。

要将模型从 IR 转换为 BLOB，请运行：

```bash
compile_tool -d MYRIAD -m <.xml 模型路径（确保 .bin 在同一根目录下）>
```

注意，编译工具是 OpenVINO 工具包的一部分。 如果你手动安装了该工具包，其位置将取决于安装路径。 通常，它位于 OpenVINO 安装目录的 .../tools/compile_tool 文件夹下。 你可以按如下方式运行：

```bash
cd .../tools/compile_tool
./compile_tool -d MYRIAD -m ...
```

> 有关转换选项的完整列表，请查阅
> `compile_tool -h`
> 。

## 高级

### 模型优化器

#### 均值和缩放值

模型输入图像的归一化通过 --mean_values 和 --scale_values 实现。 默认情况下，来自 Camera 节点的帧是 U8 数据类型，取值范围为 [0,255]。

然而，模型通常使用归一化帧进行训练，范围在 [-1,1] 或 [0,1] 之间。 为确保推理结果准确，需要事先对帧进行归一化。

虽然可以创建自定义模型在推理前进行归一化 （[此处示例](https://github.com/luxonis/oak-examples/tree/main/tutorials/custom-models/generate_model)），
但在模型优化器步骤中使用标志将归一化直接包含在模型内部更为高效。

以下是一些常见的归一化选项（假设初始输入范围为 [0,255]）：

 * 如果要求输入值在 0 到 1 之间，使用 mean=0 和 scale=255，计算为 ([0,255] - 0) / 255 = [0,1]。
 * 如果要求输入值在 -1 到 1 之间，使用 mean=127.5 和 scale=127.5，计算为 ([0,255] - 127.5) / 127.5 = [-1,1]。
 * 如果要求输入值在 -0.5 到 0.5 之间，使用 mean=127.5 和 scale=255，计算为 ([0,255] - 127.5) / 255 = [-0.5,0.5]。

更多信息请参考 [OpenVINO
文档](https://docs.openvino.ai/2022.3/openvino_docs_MO_DG_Additional_Optimization_Use_Cases.html#specifying-mean-and-scale-values)。

#### 模型布局

可以使用 --layout 参数定义模型布局。例如：

```bash
--layout NCHW
```

其中：

 * N - 批次大小
 * C - 通道数
 * H - 高度
 * W - 宽度

如果图像布局与模型布局不匹配，DepthAI 将显示相应的错误信息： [NeuralNetwork(0)] [warning] Input image (416x416) does not match NN (3x416)

在请求输出时，你可以通过 API 在交错（Interleaved）/HWC 和平面（Planar）/CHW 布局之间切换：

```python
import depthai as dai
pipeline = dai.Pipeline()
cam = pipeline.create(dai.node.Camera).build()
output = cam.requestOutput(
    size=SIZE, type=dai.ImgFrame.Type.BGR888i # 或 BGR888p（i 表示交错，p 表示平面）
)
```

更多详情请参见 [OpenVINO
文档](https://docs.openvino.ai/2022.3/openvino_docs_MO_DG_Additional_Optimization_Use_Cases.html#specifying-layout)。

#### 颜色顺序

神经网络模型通常使用 RGB 颜色顺序的图像进行训练。默认情况下，Camera 节点 输出 BGR 格式的帧。输入帧颜色顺序与训练模型不匹配可能导致预测不准确。 为此，使用 --reverse_input_channels 标志。

此外，还可以通过 API 将相机输出切换为 RGB，无需使用该标志：

```python
import depthai as dai
pipeline = dai.Pipeline()
cam = pipeline.create(dai.node.Camera).build()
output = cam.requestOutput(
    size=SIZE, type=dai.ImgFrame.Type.RGB888p
)
```

更多详情请参见 [OpenVINO
文档](https://docs.openvino.ai/2022.3/openvino_docs_MO_DG_Additional_Optimization_Use_Cases.html#reversing-input-channels)。

### 编译工具

#### 输入层精度

使用 -ip U8 将在模型的所有输入层上添加一个 U8->FP16 转换层， 这通常是期望的配置。然而，在特定场景下，例如处理非帧数据时， 直接使用 FP16 精度是必要的。在这种情况下，可以选择 -ip FP16。

#### SHAVE

在编译期间增加 SHAVE 核心数量可以提升模型速度，但 SHAVE 核心与性能之间的关系 并非线性。固件会给出一个建议的最佳 SHAVE 核心数量，通常是可用核心的一半。
