# onnx_tools

Python API: `modelconverter.utils.onnx_tools`

ONNX graph utilities shared by the conversion backends.

Holds the passes modelconverter applies to an ONNX model before handing it over to a platform's vendor toolchain: baking the
configured input normalization (channel reversal, mean subtraction and scaling) into the graph, and simplifying, optimizing and
fusing the graph with `onnxsim`, `onnxruntime` and `onnx_graphsurgeon`.

## Classes

### ONNXModifier

ONNX model modifier class to optimize and modify the ONNX model.

#### Methods

##### init

```python
def __init__(model_path: Path, output_path: Path, skip_optimization: bool = False, skip_constant_folding: bool = False):
```

Load the ONNX model and prepare it for modification.

Parameters

 * `model_path` (`Path`): Path to the base ONNX model.
 * `output_path` (`Path`): Path to save the modified ONNX model to.
 * `skip_optimization` (`bool`): Whether to skip the graph optimization performed while loading and exporting the model.
 * `skip_constant_folding` (`bool`): Whether to skip constant folding during simplification.

##### compare_outputs

```python
def compare_outputs(from_modelproto: bool = False) -> bool:
```

Compare the outputs of two ONNX models.

Parameters

 * `from_modelproto` (`bool`): If `True`, compare the in-memory model against its previous state instead of comparing the model
   files on disk.

Returns

 * `bool`: `True` if the outputs of both models match, `False` otherwise.

##### modify_onnx

```python
def modify_onnx(substitute_sub_with_add: bool = True, substitute_div_with_mul: bool = True, fuse_add_mul_to_bn: bool = True, fuse_comb_add_mul_to_conv: bool = True, fuse_single_add_mul_to_conv: bool = True, fuse_split_concat_to_conv: bool = True) -> bool:
```

Modify the ONNX model by applying a series of optimizations.

Each flag enables one step. A step that changes the outputs of the model is reverted.

Parameters

 * `substitute_sub_with_add` (`bool`): Whether to substitute `Sub` nodes with `Add` nodes.
 * `substitute_div_with_mul` (`bool`): Whether to substitute `Div` nodes with `Mul` nodes.
 * `fuse_add_mul_to_bn` (`bool`): Whether to fuse `Add` and `Mul` nodes into `BatchNormalization` nodes.
 * `fuse_comb_add_mul_to_conv` (`bool`): Whether to fuse combinations of `Add` and `Mul` nodes into `Conv` nodes.
 * `fuse_single_add_mul_to_conv` (`bool`): Whether to fuse single `Add` and `Mul` nodes into `Conv` nodes.
 * `fuse_split_concat_to_conv` (`bool`): Whether to fuse `Split` and `Concat` nodes into `Conv` nodes.

Returns

 * `bool`: `True` if the model was modified and exported, `False` otherwise.

#### Attributes

##### model_path

Path to the base ONNX model.

##### output_path

Path to save the modified ONNX model.

## Functions

### get_opset_version

```python
def get_opset_version(model: onnx.ModelProto) -> int:
```

Return the default domain opset version of an ONNX model.

Parameters

 * `model` (`onnx.ModelProto`): Model whose `opset_import` is searched.

Returns

 * `int`: Opset version declared for the default (empty) domain.

Raises

 * `ONNXException`: If the model declares no default domain opset.

### onnx_attach_normalization_to_inputs

```python
def onnx_attach_normalization_to_inputs(model_path: Path, save_path: Path, input_configs: dict[str, InputConfig], *, reverse_only: bool = False) -> Path:
```

Bake the input normalization into an ONNX model's graph.

For every input that requires it, channel reversal (`Split` and `Concat`), mean subtraction (`Sub`) and scaling (`Mul` by the
reciprocal of the scale) nodes are inserted in front of the input, so that the graph itself computes

yc = (xc − meanc)⋅(1)/(scalec)

for every channel c. The resulting model is saved and validated with the ONNX checker. Inputs whose layout is neither `"NCHW"` nor
`"NHWC"`, and inputs with a known channel count other than 3, are skipped with a warning.

> **Warning**
> The mean and scale values of an input whose channels are reversed are reversed in place, so the [InputConfig](https://docs.luxonis.com/software-v3/ai-inference/conversion/rvc-conversion/offline/modelconverter/modelconverter-api-reference/utils/config.md) objects the caller passed in are modified.

Parameters

 * `model_path` (`Path`): Path to the source ONNX model.
 * `save_path` (`Path`): Path the modified model is saved to.
 * `input_configs` (`dict[str, InputConfig]`): Input configurations keyed by input name.
 * `reverse_only` (`bool`): If `True`, only the channel reversal is applied and the mean and scale values are ignored.

Returns

 * `Path`: `save_path` if any input required modification, otherwise the unmodified `model_path`.

Raises

 * `ONNXException`: If `input_configs` names a tensor that is not an input of the graph.
