From 5864a59de870dffa3c9bb94e503d88b5e44d10d4 Mon Sep 17 00:00:00 2001 From: klemen1999 Date: Fri, 12 Jun 2026 15:38:51 +0200 Subject: [PATCH] ONNX modifications with no op exit early --- modelconverter/utils/config.py | 15 ++++++ modelconverter/utils/metadata.py | 12 +++-- modelconverter/utils/onnx_tools.py | 15 ++++-- tests/test_utils/test_config.py | 76 +++++++++++++++++++++--------- 4 files changed, 86 insertions(+), 32 deletions(-) diff --git a/modelconverter/utils/config.py b/modelconverter/utils/config.py index 06055f2f..e779f59e 100644 --- a/modelconverter/utils/config.py +++ b/modelconverter/utils/config.py @@ -222,6 +222,21 @@ def _parse_values( return [value, value, value] return value + def requires_onnx_input_modification( + self, *, reverse_only: bool = False + ) -> bool: + if self.encoding_mismatch: + return True + if reverse_only: + return False + return ( + self.mean_values is not None + and any(v != 0 for v in self.mean_values) + ) or ( + self.scale_values is not None + and any(v != 1 for v in self.scale_values) + ) + class TargetConfig(BaseModelExtraForbid): disable_calibration: bool = False diff --git a/modelconverter/utils/metadata.py b/modelconverter/utils/metadata.py index 3798d82f..5f8cb81b 100644 --- a/modelconverter/utils/metadata.py +++ b/modelconverter/utils/metadata.py @@ -45,10 +45,14 @@ def _get_metadata_dlc(path: Path) -> Metadata: if path.suffix == ".csv": csv_path = path else: - csv_path = Path("info.csv") - subprocess_run( - ["snpe-dlc-info", "-i", path, "-s", csv_path], silent=True - ) + csv_path = path.with_suffix(".info.csv") + if ( + not csv_path.exists() + or csv_path.stat().st_mtime < path.stat().st_mtime + ): + subprocess_run( + ["snpe-dlc-info", "-i", path, "-s", csv_path], silent=True + ) content = csv_path.read_text() metadata = {} diff --git a/modelconverter/utils/onnx_tools.py b/modelconverter/utils/onnx_tools.py index 65b76edb..3ffa46f3 100644 --- a/modelconverter/utils/onnx_tools.py +++ b/modelconverter/utils/onnx_tools.py @@ -111,6 +111,15 @@ def onnx_attach_normalization_to_inputs( *, reverse_only: bool = False, ) -> Path: + if not any( + cfg.requires_onnx_input_modification(reverse_only=reverse_only) + for cfg in input_configs.values() + ): + logger.info( + "No ONNX input normalization changes requested; using original model." + ) + return model_path + model = onnx.load(str(model_path)) if model_path.with_suffix(".onnx_data").exists(): model_data_path = str(model_path).replace(".onnx", ".onnx_data") @@ -136,11 +145,7 @@ def onnx_attach_normalization_to_inputs( if input_name not in input_configs: continue cfg = input_configs[input_name] - if ( - cfg.encoding.from_ == cfg.encoding.to - and cfg.mean_values is None - and cfg.scale_values is None - ): + if not cfg.requires_onnx_input_modification(reverse_only=reverse_only): continue shape = cfg.shape diff --git a/tests/test_utils/test_config.py b/tests/test_utils/test_config.py index 28a19a99..a9b8cc7a 100644 --- a/tests/test_utils/test_config.py +++ b/tests/test_utils/test_config.py @@ -4,6 +4,7 @@ import tarfile import tempfile from pathlib import Path +from textwrap import dedent import numpy as np import onnx @@ -248,29 +249,34 @@ def create_json( def create_yaml(append: str = "") -> str: config = ( - f""" -input_model: "{DATA_DIR}/dummy_model.onnx" -mean_values: "imagenet" -data_type: float32 -shape: [ 1, 3, 256, 256 ] - -calibration: - path: "{CALIBRATION_DATA_DIR_1}" - max_images: 20 - -hailo: - optimization_level: 3 - compression_level: 3 - batch_size: 4 - -inputs: - - name: "input0" - scale_values: [255,255,255] - shape: [1, 3, 64, 64] - layout: "NCHW" - calibration: - max_images: 100 -""" + dedent( + """ + input_model: "{data_dir}/dummy_model.onnx" + mean_values: "imagenet" + data_type: float32 + shape: [ 1, 3, 256, 256 ] + + calibration: + path: "{calibration_data_dir_1}" + max_images: 20 + + hailo: + optimization_level: 3 + compression_level: 3 + batch_size: 4 + + inputs: + - name: "input0" + scale_values: [255,255,255] + shape: [1, 3, 64, 64] + layout: "NCHW" + calibration: + max_images: 100 + """ + ).format( + data_dir=DATA_DIR, + calibration_data_dir_1=CALIBRATION_DATA_DIR_1, + ) + append ) @@ -834,6 +840,30 @@ def test_modified_onnx(keys: list[str], values: list[str]): assert input_configs[inp].scale_values is None or [1, 1, 1] +def test_modified_onnx_noop_returns_original_model(): + model_path = DATA_DIR / "dummy_model.onnx" + modified_path = DATA_DIR / "dummy_model_noop_modified.onnx" + config = Config.get_config( + None, + { + "input_model": str(model_path), + "encoding": "NONE", + }, + ) + input_configs = { + inp.name: inp for inp in next(iter(config.stages.values())).inputs + } + + result = onnx_attach_normalization_to_inputs( + model_path, + modified_path, + input_configs, + ) + + assert result == model_path + assert not modified_path.exists() + + @pytest.mark.parametrize( ("keys", "values", "nn_preprocess", "expected"), [