Skip to content

Commit 18a53a6

Browse files
authored
AC: enable preprocessing for GAPI launcher (#3452)
1 parent 035f6fe commit 18a53a6

File tree

8 files changed

+229
-55
lines changed

8 files changed

+229
-55
lines changed

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

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,17 @@ def from_configs(cls, model_config, delayed_annotation_loading=False):
7171
dataset = Dataset(dataset_config) if not delayed_annotation_loading else None
7272
dataset_metadata = dataset.metadata if dataset is not None else {}
7373
launcher_kwargs = {'delayed_model_loading': postpone_model_loading}
74-
enable_ie_preprocessing = (
75-
dataset_config.get('_ie_preprocessing', False)
76-
if launcher_config['framework'] == 'dlsdk' else False
77-
)
78-
enable_ov_preprocessing = (
79-
dataset_config.get('_ie_preprocessing', False)
80-
if launcher_config['framework'] == 'openvino' else False
81-
)
74+
runtime_framework = launcher_config['framework']
75+
enable_runtime_preprocessing = False
76+
if runtime_framework in ['dlsdk', 'gapi', 'openvino']:
77+
enable_runtime_preprocessing = dataset_config.get('_ie_preprocessing', False)
8278
preprocessor = PreprocessingExecutor(
8379
dataset_config.get('preprocessing'), dataset_name, dataset_metadata,
84-
enable_ie_preprocessing=enable_ie_preprocessing, enable_ov_preprocessing=enable_ov_preprocessing
80+
enable_runtime_preprocessing=enable_runtime_preprocessing, runtime_framework=runtime_framework
8581
)
8682
input_precision = launcher_config.get('_input_precision', [])
8783
input_layouts = launcher_config.get('_input_layout', '')
88-
if enable_ie_preprocessing or enable_ov_preprocessing:
84+
if enable_runtime_preprocessing:
8985
launcher_kwargs['preprocessor'] = preprocessor
9086
if launcher_config['framework'] == 'dummy' and launcher_config.get('provide_identifiers', False):
9187
launcher_kwargs = {'identifiers': dataset.identifiers if dataset is not None else []}

tools/accuracy_checker/openvino/tools/accuracy_checker/launcher/gapi_launcher.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def parameters(cls):
115115

116116
return parameters
117117

118-
def __init__(self, config_entry: dict, *args, **kwargs):
118+
def __init__(self, config_entry: dict, *args, preprocessor=None, **kwargs):
119119
super().__init__(config_entry, *args, **kwargs)
120120
self._delayed_model_loading = kwargs.get('delayed_model_loading', False)
121121
self.validate_config(config_entry, delayed_model_loading=self._delayed_model_loading)
@@ -128,6 +128,7 @@ def __init__(self, config_entry: dict, *args, **kwargs):
128128
self._inputs_shapes, self._const_inputs = self.get_inputs_from_config(self.config)
129129
multi_input = (len(self._inputs_shapes) - len(self.const_inputs)) > 1
130130
self.non_image_inputs = False
131+
self.preprocessor = preprocessor
131132
if multi_input:
132133
for name, shape in self._inputs_shapes.items():
133134
if name in self.const_inputs:
@@ -177,6 +178,10 @@ def prepare_net(self):
177178
pp = cv2.gapi.ie.params(*args)
178179
else:
179180
pp = cv2.gapi.mx.params('net', str(self.model))
181+
if self.preprocessor:
182+
steps = [step.value for step in self.preprocessor.ie_preprocess_steps]
183+
if steps:
184+
pp.cfgPreprocList(steps)
180185
for input_name, value in self._const_inputs.items():
181186
pp.constInput(input_name, value)
182187
if self.backend == 'ie':
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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 .ie_preprocessor import IEPreprocessor, ie_preprocess_available
18+
from .ov_preprocessor import OVPreprocessor, ov_preprocess_available
19+
from .gapi_preprocessor import GAPIPreprocessor, gapi_preprocess_available
20+
21+
__all__ = [
22+
'preprocessing_available',
23+
'get_preprocessor'
24+
]
25+
26+
FRAMEWORK_PREPROCESSINGS = {
27+
'gapi': GAPIPreprocessor,
28+
'openvino': OVPreprocessor,
29+
'dlsdk': IEPreprocessor
30+
}
31+
32+
AVAILABILITY_CHECK = {
33+
'gapi': gapi_preprocess_available,
34+
'openvino': ov_preprocess_available,
35+
'dlsdk': ie_preprocess_available
36+
}
37+
38+
39+
def preprocessing_available(framework):
40+
if framework not in AVAILABILITY_CHECK:
41+
return False
42+
return AVAILABILITY_CHECK[framework]()
43+
44+
45+
def get_preprocessor(framework):
46+
return FRAMEWORK_PREPROCESSINGS[framework]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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+
import cv2
21+
try:
22+
from cv2.gapi.mx.pp import Resize, Crop, Padding
23+
_preprocessing_available = True
24+
except ImportError:
25+
Resize, Crop, Padding = None, None, None
26+
_preprocessing_available = False
27+
from ...utils import get_size_from_config, string_to_tuple
28+
29+
30+
def gapi_preprocess_available():
31+
return _preprocessing_available
32+
33+
34+
PreprocessingOp = namedtuple('PreprocessingOp', ['name', 'value'])
35+
36+
37+
class GAPIPreprocessor:
38+
39+
def __init__(self, config):
40+
self.SUPPORTED_PREPROCESSING_OPS = {
41+
'resize': self.get_resize_op,
42+
'crop': self.get_crop_op,
43+
'padding': self.get_padding_op
44+
}
45+
if _preprocessing_available:
46+
self.RESIZE_INTERPOLATIONS = {
47+
'LINEAR': cv2.gapi.mx.pp.Resize_Interpolation_BILINEAR,
48+
'BILINEAR': cv2.gapi.mx.pp.Resize_Interpolation_BILINEAR,
49+
'BICUBIC': cv2.gapi.mx.pp.Resize_Interpolation_BICUBIC,
50+
}
51+
self.RESIZE_ASPECT_RATIO = {
52+
'greater': cv2.gapi.mx.pp.Resize_AspectRatioScale_GREATER,
53+
'fit_to_window': cv2.gapi.mx.pp.Resize_AspectRatioScale_FIT_TO_WINDOW,
54+
'height': cv2.gapi.mx.pp.Resize_AspectRatioScale_HEIGHT,
55+
'width': cv2.gapi.mx.pp.Resize_AspectRatioScale_WIDTH,
56+
}
57+
self.PADDING_TYPE = {
58+
'center': cv2.gapi.mx.pp.Padding_PadType_CENTER,
59+
'right_bottom': cv2.gapi.mx.pp.Padding_PadType_RIGHT_BOTTOM,
60+
'left_top': cv2.gapi.mx.pp.Padding_PadType_LEFT_TOP,
61+
}
62+
else:
63+
self.RESIZE_ASPECT_RATIO = {}
64+
self.RESIZE_INTERPOLATIONS = {}
65+
self.PADDING_TYPE = {}
66+
67+
self.config = config or []
68+
self.configure()
69+
70+
def configure(self):
71+
steps = []
72+
step_names = set()
73+
keep_preprocessing_config = deepcopy(self.config)
74+
for preprocessor in reversed(self.config):
75+
if preprocessor['type'] not in self.SUPPORTED_PREPROCESSING_OPS:
76+
break
77+
ie_ops = self.get_op(preprocessor)
78+
if not ie_ops:
79+
break
80+
if ie_ops.name in step_names:
81+
break
82+
step_names.add(ie_ops.name)
83+
steps.append(ie_ops)
84+
keep_preprocessing_config = keep_preprocessing_config[:-1]
85+
self.steps = steps
86+
self.keep_preprocessing_info = keep_preprocessing_config
87+
if not steps:
88+
warnings.warn('no preprocessing steps for transition to PreProcessInfo')
89+
90+
def get_op(self, preprocessing_config):
91+
preprocessing_getter = self.SUPPORTED_PREPROCESSING_OPS[preprocessing_config['type']]
92+
return preprocessing_getter(preprocessing_config)
93+
94+
def get_resize_op(self, config):
95+
aspect_ratio_cfg = config.get('aspect_ratio_scale')
96+
if aspect_ratio_cfg is not None and aspect_ratio_cfg not in self.RESIZE_ASPECT_RATIO:
97+
return None
98+
aspect_ratio = self.RESIZE_ASPECT_RATIO.get(aspect_ratio_cfg, cv2.gapi.mx.pp.Resize_AspectRatioScale_UNKNOWN)
99+
cfg_interpolation = config.get('interpolation', 'BILINEAR').upper()
100+
if cfg_interpolation not in self.RESIZE_INTERPOLATIONS:
101+
return None
102+
interpolation = self.RESIZE_INTERPOLATIONS[cfg_interpolation]
103+
height, width = get_size_from_config(config)
104+
return PreprocessingOp(
105+
'resize_algorithm', Resize((width, height), interpolation=interpolation, aspect_ratio_scale=aspect_ratio)
106+
)
107+
108+
def has_resize(self):
109+
preprocessor_names = [step.name for step in self.steps]
110+
return 'resize_algorithm' in preprocessor_names
111+
112+
@staticmethod
113+
def get_crop_op(config):
114+
if 'max_square' in config:
115+
return PreprocessingOp('crop', Crop(cv2.gapi.mx.pp.MaxSquare()))
116+
if 'central_fraction' in config:
117+
ratio = float(config['central_fraction'])
118+
return PreprocessingOp('crop', Crop(cv2.gapi.mx.pp.CentralFraction(ratio)))
119+
height, width = get_size_from_config(config)
120+
return PreprocessingOp('crop', Crop((width, height)))
121+
122+
def get_padding_op(self, config):
123+
if 'numpy_pad_mode' in config and config['numpy_pad_mode'] != 'constant':
124+
return None
125+
height, width = get_size_from_config(config, allow_none=True)
126+
# gapi dos not support fully strided padding right now
127+
if height is None or width is None:
128+
return None
129+
pad_type = config.get('pad_type', 'center')
130+
if pad_type not in self.PADDING_TYPE:
131+
return None
132+
pad_t = self.PADDING_TYPE[pad_type]
133+
pad_val = config.get('pad_value', [0, 0, 0])
134+
if isinstance(pad_val, str):
135+
pad_val = string_to_tuple(pad_val, int)
136+
if isinstance(pad_val, int):
137+
pad_val = [pad_val] * 3
138+
if isinstance(pad_val, tuple):
139+
pad_val = list(pad_val)
140+
return PreprocessingOp('padding', Padding((width, height), pad_val, pad_type=pad_t))

tools/accuracy_checker/openvino/tools/accuracy_checker/preprocessor/ie_preprocessor.py renamed to tools/accuracy_checker/openvino/tools/accuracy_checker/preprocessor/launcher_preprocessing/ie_preprocessor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
from openvino.inference_engine import ResizeAlgorithm, PreProcessInfo, ColorFormat, MeanVariant # pylint:disable=W9902
2222
except ImportError:
2323
ResizeAlgorithm, PreProcessInfo, ColorFormat, MeanVariant = None, None, None, None
24-
from ..utils import get_or_parse_value
25-
from ..config import ConfigError
24+
from ...utils import get_or_parse_value
25+
from ...config import ConfigError
2626

2727

2828
def ie_preprocess_available():

tools/accuracy_checker/openvino/tools/accuracy_checker/preprocessor/ov_preprocessor.py renamed to tools/accuracy_checker/openvino/tools/accuracy_checker/preprocessor/launcher_preprocessing/ov_preprocessor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from openvino.preprocess import ResizeAlgorithm, ColorFormat # pylint:disable=W9902
2222
except ImportError:
2323
ResizeAlgorithm = None
24-
from ..utils import get_or_parse_value
24+
from ...utils import get_or_parse_value
2525

2626

2727
def ov_preprocess_available():
@@ -89,7 +89,7 @@ def get_resize_op(config):
8989
'NEAREST': ResizeAlgorithm.RESIZE_NEAREST,
9090
'CUBIC': ResizeAlgorithm.RESIZE_CUBIC
9191
}
92-
if 'aspect_ratio' in config:
92+
if 'aspect_ratio_scale' in config:
9393
return None
9494
interpolation = config.get('interpolation', 'BILINEAR').upper()
9595
if interpolation not in supported_interpolations:

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

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,38 +18,25 @@
1818
from ..config import ConfigValidator, StringField
1919
from ..utils import get_data_shapes
2020
from .preprocessor import Preprocessor, MULTI_INFER_PREPROCESSORS
21-
from .ie_preprocessor import IEPreprocessor, ie_preprocess_available
22-
from .ov_preprocessor import OVPreprocessor, ov_preprocess_available
21+
from .launcher_preprocessing import preprocessing_available, get_preprocessor
2322

2423

2524
class PreprocessingExecutor:
2625
def __init__(
2726
self, processors=None, dataset_name='custom', dataset_meta=None,
28-
input_shapes=None,
29-
enable_ie_preprocessing=False,
30-
enable_ov_preprocessing=False
27+
input_shapes=None, enable_runtime_preprocessing=False, runtime_framework=None
3128
):
3229
self.processors = []
3330
self.dataset_meta = dataset_meta
3431
self._multi_infer_transformations = False
3532
self.ie_processor = None
36-
if enable_ie_preprocessing:
37-
if not ie_preprocess_available():
33+
if enable_runtime_preprocessing:
34+
if not preprocessing_available(runtime_framework):
3835
warnings.warn(
39-
'PreProcessInfo is not available in your InferenceEngine version or openvino is not installed'
40-
'--ie_preprocessing key will be ignored'
41-
)
42-
else:
43-
self.ie_processor = IEPreprocessor(processors)
44-
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-
)
36+
f'Preprocessing for {runtime_framework} is not available, '
37+
'specified in command line parameter will be ignored')
5138
else:
52-
self.ie_processor = OVPreprocessor(processors)
39+
self.ie_processor = get_preprocessor(runtime_framework)(processors)
5340
processors = self.ie_processor.keep_preprocessing_info
5441

5542
if not processors:

0 commit comments

Comments
 (0)