openvino/model-optimizer/extensions/back/InterpolateToInterpOrResamp...

119 lines
4.9 KiB
Python

"""
Copyright (C) 2018-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from extensions.back.ShapeOfToShape import ShapeOfToShape
from extensions.ops.interp import InterpOp
from extensions.ops.resample import ResampleOp
from extensions.ops.resize_factor_utils import factor_update
from mo.back.replacement import BackReplacementPattern
from mo.graph.graph import Graph
from mo.ops.shape import Shape
from mo.utils.shape import node_to_get_batch_value, node_to_get_features_dimension_value, \
new_shape_node_from_shape_nodes
class InterpolateToInterpOrResample(BackReplacementPattern):
enabled = True
graph_condition = [lambda graph: not graph.graph['cmd_params'].generate_experimental_IR_V10]
force_clean_up = True
type_map = {
'linear': 'caffe.ResampleParameter.LINEAR',
'nearest': 'caffe.ResampleParameter.NEAREST',
'cubic': 'caffe.ResampleParameter.CUBIC',
'area': 'caffe.ResampleParameter.AREA',
}
def run_before(self):
return [ShapeOfToShape]
@staticmethod
def pattern():
return dict(
nodes=[('interpolate', {'type': 'Interpolate'})],
edges=[],
)
@staticmethod
def replace_pattern(graph: Graph, match: dict):
node = match['interpolate']
assert 1 in node.in_ports() and not node.in_port(1).disconnected() and \
node.in_port(1).data.get_value() is not None, 'Interpolate node {} is corrupted: no 1-port input found'
# common
mode = node.mode
assert mode in ['linear', 'nearest', 'cubic', 'area']
in_shape = node.in_port(0).data.get_shape()
assert in_shape is not None and len(in_shape) in [4, 5]
out_shape = node.out_port(0).data.get_shape()
assert out_shape is not None and len(out_shape) in [4, 5]
in_height, in_width = in_shape[2], in_shape[3]
out_height, out_width = out_shape[2], out_shape[3]
factor = factor_update(
None if not node.has_valid('factor') else node.factor,
[float(out_height) / in_height, float(out_width) / in_width],
[in_height, in_width],
[out_height, out_width],
node.soft_get('name')
)
update_attrs = {
'width': out_width,
'height': out_height,
'factor': factor,
}
if (node.has_valid('shrink_factor') and node.has_valid('zoom_factor')) or factor is None:
del update_attrs['factor']
if node.has('factor'):
del node['factor']
if ((node.has_valid('shrink_factor') and node.shrink_factor != 1) or
(node.has_valid('zoom_factor') and node.zoom_factor != 1) or 'factor' in update_attrs) \
and ((not node.has_valid('width') or node.width == 0) and
(not node.has_valid('height') or node.height == 0)):
update_attrs['width'] = 0
update_attrs['height'] = 0
# specific
if mode in ['nearest', 'cubic', 'area'] or node.has_and_set('convert_to_resample'):
assert not node.align_corners
assert node.pads_begin == 0 and node.pads_end == 0
update_attrs['resample_type'] = InterpolateToInterpOrResample.type_map[mode]
ResampleOp.update_node_stat(node, update_attrs)
if not graph.graph['cmd_params'].keep_shape_ops or graph.graph['fw'] != 'tf':
node.in_port(1).disconnect()
else:
# we avoid making resample non-reshapable for tf version
shape = Shape(graph, {}).create_node()
node.in_port(0).get_source().connect(shape.in_port(0))
batch = node_to_get_batch_value(shape)
features = node_to_get_features_dimension_value(shape)
full_shape = new_shape_node_from_shape_nodes([batch, features, node.in_port(1).get_source().node])
node.in_port(1).get_connection().set_source(full_shape.out_port(0))
full_shape['override_output_shape'] = True
elif mode == 'linear':
assert len(in_shape) == 4, 'Interp does not support 5D input'
update_attrs.update({
'pad_beg': node.pads_begin,
'pad_end': node.pads_end,
'align_corners': node.align_corners,
})
InterpOp.update_node_stat(node, update_attrs)
node.in_port(1).disconnect()