Skip to content

Commit cd29560

Browse files
authored
AC: fix input blob info (#3416)
* AC: fix input blob info * properly enable input precision setting * preprocessing setting
1 parent 46db87e commit cd29560

File tree

4 files changed

+185
-41
lines changed

4 files changed

+185
-41
lines changed

tools/accuracy_checker/openvino/tools/accuracy_checker/evaluators/model_evaluator.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,17 @@ def from_configs(cls, model_config, delayed_annotation_loading=False):
7575
dataset_config.get('_ie_preprocessing', False)
7676
if launcher_config['framework'] == 'dlsdk' else False
7777
)
78+
enable_ov_preprocessing = (
79+
dataset_config.get('_ie_preprocessing', False)
80+
if launcher_config['framework'] == 'openvino' else False
81+
)
7882
preprocessor = PreprocessingExecutor(
7983
dataset_config.get('preprocessing'), dataset_name, dataset_metadata,
80-
enable_ie_preprocessing=enable_ie_preprocessing
84+
enable_ie_preprocessing=enable_ie_preprocessing, enable_ov_preprocessing=enable_ov_preprocessing
8185
)
8286
input_precision = launcher_config.get('_input_precision', [])
8387
input_layouts = launcher_config.get('_input_layout', '')
84-
if enable_ie_preprocessing:
88+
if enable_ie_preprocessing or enable_ov_preprocessing:
8589
launcher_kwargs['preprocessor'] = preprocessor
8690
if launcher_config['framework'] == 'dummy' and launcher_config.get('provide_identifiers', False):
8791
launcher_kwargs = {'identifiers': dataset.identifiers if dataset is not None else []}
@@ -705,12 +709,13 @@ def _resolve_undefined_shapes(self):
705709
if self.launcher.dyn_batch_only:
706710
self.launcher.resolve_undefined_batch()
707711
return
708-
if (
709-
(self.preprocessor.dynamic_shapes or not self.preprocessor.has_shape_modifications)
710-
and self.launcher.dynamic_shapes_policy != 'static'):
711-
self._initialize_input_shape_with_data_range()
712-
return
713-
self._initialize_input_shape()
712+
if getattr(self.launcher, 'need_dyn_resolving', True):
713+
if (
714+
(self.preprocessor.dynamic_shapes or not self.preprocessor.has_shape_modifications)
715+
and self.launcher.dynamic_shapes_policy != 'static'):
716+
self._initialize_input_shape_with_data_range()
717+
return
718+
self._initialize_input_shape()
714719

715720
def _initialize_input_shape_with_data_range(self):
716721
input_shapes = []

tools/accuracy_checker/openvino/tools/accuracy_checker/launcher/openvino_launcher.py

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import warnings
2323
import numpy as np
2424
from openvino.runtime import Core, AsyncInferQueue, get_version, PartialShape, Type, Dimension
25+
from openvino.preprocess import PrePostProcessor
2526
from .dlsdk_launcher_config import (
2627
HETERO_KEYWORD, MULTI_DEVICE_KEYWORD, NIREQ_REGEX, VPU_PLUGINS,
2728
get_cpu_extension,
@@ -499,7 +500,7 @@ def _create_network(self, input_shapes=None):
499500
with open(str(self._model), 'rb') as f: #pylint:disable=unspecified-encoding
500501
self.exec_network = self.ie_core.import_model(io.BytesIO(f.read()), self._device)
501502
self.original_outputs = self.exec_network.outputs
502-
model_batch = self._get_model_batch_size()
503+
model_batch = self._get_remodel_batch_size()
503504
self._batch = model_batch if model_batch is not None else 1
504505
return
505506
if self._weights is None and self._model.suffix != '.onnx':
@@ -587,8 +588,10 @@ def load_network(self, network=None, log=False, preprocessing=None):
587588
self.network = network
588589
if self.network is not None:
589590
self.dyn_input_layers, self._partial_shapes = self.get_dynamic_inputs(self.network)
590-
self.input_to_tensor_name = self.get_input_tensor_name_mapping(self.network)
591-
self.input_to_index = {inp.get_node().friendly_name: idx for idx, inp in enumerate(self.network.inputs)}
591+
self.input_to_tensor_name = self.get_input_tensor_name_mapping(
592+
self.network if self.network is not None else self.exec_network)
593+
network_inputs = self.network.inputs if self.network is not None else self.exec_network.inputs
594+
self.input_to_index = {inp.get_node().friendly_name: idx for idx, inp in enumerate(network_inputs)}
592595
if not self._postpone_input_configuration:
593596
self._set_precision()
594597
self._set_input_shape()
@@ -597,12 +600,13 @@ def load_network(self, network=None, log=False, preprocessing=None):
597600
self.print_input_output_info(self.network if self.network is not None else self.exec_network)
598601
if preprocessing:
599602
self._set_preprocess(preprocessing)
603+
self.dyn_input_layers, self._partial_shapes = self.get_dynamic_inputs(self.network)
600604
model_batch = self._get_model_batch_size()
601605
model_batch = 1 if model_batch is None else model_batch
602606
self._batch = self.config.get('batch', model_batch)
603607
self._set_batch_size(self._batch)
604608
self.try_to_set_default_layout()
605-
if self.network and not preprocessing and (not self.dyn_input_layers or self.is_dynamic):
609+
if self.network and (not self.dyn_input_layers or self.is_dynamic or self.disable_resize_to_input):
606610
self.exec_network = self.ie_core.compile_model(self.network, self._device)
607611
self.infer_request = self.exec_network.create_infer_request()
608612

@@ -838,11 +842,15 @@ def _data_to_blob(self, layer_shape, data, layout): # pylint:disable=R0911,R091
838842

839843
def _set_precision(self):
840844
config_inputs = self.config.get('inputs', [])
841-
for input_config in config_inputs:
842-
if 'precision' in input_config:
843-
if self.network:
844-
self.inputs[input_config['name']].set_element_type(
845-
PRECISION_STR_TO_TYPE[input_config['precision'].upper()])
845+
has_precisions = ['precision' in inp for inp in config_inputs]
846+
if has_precisions and self.network:
847+
preprocessor = PrePostProcessor(self.network)
848+
for input_config in config_inputs:
849+
if 'precision' in input_config:
850+
name = input_config['name']
851+
element_type = PRECISION_STR_TO_TYPE[input_config['precision'].upper()]
852+
preprocessor.input(self.input_to_index[name]).tensor().set_element_type(element_type)
853+
self.network = preprocessor.build()
846854

847855
def _set_input_shape(self):
848856
if not self.network:
@@ -914,33 +922,28 @@ def _set_preprocess(self, preprocess):
914922
preprocess_steps = preprocess.ie_preprocess_steps
915923
if not preprocess_steps:
916924
return
917-
for input_name, input_info in self.network.input_info.items():
925+
preprocessor = PrePostProcessor(self.network)
926+
for input_name in self.inputs:
918927
if input_name in self.const_inputs + self.image_info_inputs:
919928
continue
929+
input_id = self.input_to_index[input_name]
920930
for (name, value) in preprocess_steps:
921-
setattr(input_info.preprocess_info, name, value)
922-
if preprocess.ie_processor.has_normalization():
923-
channel_id = input_info.layout.find('C')
924-
if channel_id != -1:
925-
num_channels = input_info.input_data.shape[channel_id]
926-
preprocess.ie_processor.set_normalization(num_channels, input_info.preprocess_info)
927-
self.disable_resize_to_input = preprocess.ie_processor.has_resize()
928-
self._use_set_blob = self.disable_resize_to_input
929-
self.load_network(self.network)
931+
if name == 'resize_algorithm':
932+
preprocessor.input(input_id).tensor().set_spatial_dynamic_shape()
933+
preprocessor.input(input_id).preprocess().resize(value)
934+
self.need_dyn_resolving = False
935+
if name == 'convert_color_format':
936+
src, dst = value
937+
preprocessor.input(input_id).tensor().set_color_format(src)
938+
preprocessor.input(input_id).preprocess().convert_color(dst)
939+
if name == 'mean_variant':
940+
mean, scale = value
941+
if mean is not None:
942+
preprocessor.input(input_id).preprocess().mean(mean)
943+
if scale is not None:
944+
preprocessor.input(input_id).preprocess().scale(scale)
945+
self.network = preprocessor.build()
930946
self._preprocess_steps = preprocess_steps
931-
return
932-
preprocess_info_by_input = {}
933-
preprocess_info = preprocess.preprocess_info
934-
for input_name in self.inputs:
935-
if input_name in self.const_inputs + self.image_info_inputs:
936-
continue
937-
if preprocess.ie_processor.has_normalization():
938-
channel_id = self.inputs[input_name].layout.find('C')
939-
if channel_id != -1:
940-
num_channels = self.inputs[input_name].shape[channel_id]
941-
preprocess.ie_processor.set_normalization(num_channels, preprocess_info)
942-
preprocess_info_by_input[input_name] = preprocess_info
943-
self._preprocess_info = preprocess_info_by_input
944947
self.disable_resize_to_input = preprocess.ie_processor.has_resize()
945948

946949
def get_model_file_type(self):
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
"""
2+
Copyright (c) 2018-2022 Intel Corporation
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
"""
16+
17+
from copy import deepcopy
18+
from collections import namedtuple
19+
import warnings
20+
try:
21+
from openvino.preprocess import ResizeAlgorithm, ColorFormat # pylint:disable=W9902
22+
except ImportError:
23+
ResizeAlgorithm = None
24+
from ..utils import get_or_parse_value
25+
26+
27+
def ov_preprocess_available():
28+
return ResizeAlgorithm is not None
29+
30+
31+
PreprocessingOp = namedtuple('PreprocessingOp', ['name', 'value'])
32+
33+
34+
class OVPreprocessor:
35+
PRECOMPUTED_MEANS = {
36+
'imagenet': (104.00698793, 116.66876762, 122.67891434),
37+
'cifar10': (125.307, 122.961, 113.8575),
38+
}
39+
40+
PRECOMPUTED_STDS = {
41+
'imagenet': (104.00698793, 116.66876762, 122.67891434),
42+
'cifar10': (125.307, 122.961, 113.8575),
43+
}
44+
45+
def __init__(self, config):
46+
self.SUPPORTED_PREPROCESSING_OPS = {
47+
'resize': self.get_resize_op,
48+
'auto_resize': self.get_resize_op,
49+
'bgr_to_rgb': self.get_color_format_op,
50+
'rgb_to_bgr': self.get_color_format_op,
51+
'nv12_to_bgr': self.get_color_format_op,
52+
'nv12_to_rgb': self.get_color_format_op,
53+
'normalization': self.get_normalization_op
54+
}
55+
self.mean_values = None
56+
self.std_values = None
57+
self.config = config or []
58+
self.configure()
59+
60+
def configure(self):
61+
steps = []
62+
step_names = set()
63+
keep_preprocessing_config = deepcopy(self.config)
64+
for preprocessor in reversed(self.config):
65+
if preprocessor['type'] not in self.SUPPORTED_PREPROCESSING_OPS:
66+
break
67+
ie_ops = self.get_op(preprocessor)
68+
if not ie_ops:
69+
break
70+
if ie_ops.name in step_names:
71+
break
72+
step_names.add(ie_ops.name)
73+
steps.append(ie_ops)
74+
keep_preprocessing_config = keep_preprocessing_config[:-1]
75+
self.steps = steps
76+
self.keep_preprocessing_info = keep_preprocessing_config
77+
if not steps:
78+
warnings.warn('no preprocessing steps for transition to PreProcessInfo')
79+
80+
def get_op(self, preprocessing_config):
81+
preprocessing_getter = self.SUPPORTED_PREPROCESSING_OPS[preprocessing_config['type']]
82+
return preprocessing_getter(preprocessing_config)
83+
84+
@staticmethod
85+
def get_resize_op(config):
86+
supported_interpolations = {
87+
'LINEAR': ResizeAlgorithm.RESIZE_LINEAR,
88+
'BILINEAR': ResizeAlgorithm.RESIZE_LINEAR,
89+
'NEAREST': ResizeAlgorithm.RESIZE_NEAREST,
90+
'CUBIC': ResizeAlgorithm.RESIZE_CUBIC
91+
}
92+
if 'aspect_ratio' in config:
93+
return None
94+
interpolation = config.get('interpolation', 'BILINEAR').upper()
95+
if interpolation not in supported_interpolations:
96+
return None
97+
return PreprocessingOp('resize_algorithm', supported_interpolations[interpolation])
98+
99+
@staticmethod
100+
def get_color_format_op(config):
101+
supported_color_formats = {
102+
'bgr': ColorFormat.BGR,
103+
'rgb': ColorFormat.RGB,
104+
'nv12': ColorFormat.NV12_SINGLE_PLANE
105+
}
106+
src_format = config['type'].split('_')[0]
107+
dst_format = config['type'].split('_')[-1]
108+
src_color = supported_color_formats.get(src_format)
109+
dst_color = supported_color_formats.get(dst_format)
110+
if dst_color is None or src_color is None:
111+
return None
112+
return PreprocessingOp('convert_color_format', (src_color, dst_color))
113+
114+
def get_normalization_op(self, config):
115+
mean_values = get_or_parse_value(config.get('mean'), self.PRECOMPUTED_MEANS)
116+
std_values = get_or_parse_value(config.get('std'), self.PRECOMPUTED_STDS)
117+
return PreprocessingOp('mean_variant', (mean_values, std_values))
118+
119+
def has_resize(self):
120+
preprocessor_names = [step.name for step in self.steps]
121+
return 'resize_algorithm' in preprocessor_names
122+
123+
def has_normalization(self):
124+
preprocessor_names = [step.name for step in self.steps]
125+
return 'mean_variant' in preprocessor_names

tools/accuracy_checker/openvino/tools/accuracy_checker/preprocessor/preprocessing_executor.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
from ..utils import get_data_shapes
2020
from .preprocessor import Preprocessor, MULTI_INFER_PREPROCESSORS
2121
from .ie_preprocessor import IEPreprocessor, ie_preprocess_available
22+
from .ov_preprocessor import OVPreprocessor, ov_preprocess_available
2223

2324

2425
class PreprocessingExecutor:
2526
def __init__(
2627
self, processors=None, dataset_name='custom', dataset_meta=None,
2728
input_shapes=None,
28-
enable_ie_preprocessing=False
29+
enable_ie_preprocessing=False,
30+
enable_ov_preprocessing=False
2931
):
3032
self.processors = []
3133
self.dataset_meta = dataset_meta
@@ -40,6 +42,15 @@ def __init__(
4042
else:
4143
self.ie_processor = IEPreprocessor(processors)
4244
processors = self.ie_processor.keep_preprocessing_info
45+
if enable_ov_preprocessing:
46+
if not ov_preprocess_available():
47+
warnings.warn(
48+
'PreProcessInfo is not available in your InferenceEngine version or openvino is not installed'
49+
'--ie_preprocessing key will be ignored'
50+
)
51+
else:
52+
self.ie_processor = OVPreprocessor(processors)
53+
processors = self.ie_processor.keep_preprocessing_info
4354

4455
if not processors:
4556
return

0 commit comments

Comments
 (0)