import copy import numpy as np import tensorflow as tf from onnx_tf.common import exception from onnx_tf.handlers.backend_handler import BackendHandler from onnx_tf.handlers.handler import onnx_op from onnx_tf.handlers.handler import partial_support from onnx_tf.handlers.handler import ps_description from onnx_tf.handlers.handler import tf_func from onnx_tf.common.tf_helper import tf_shape @onnx_op("Upsample") @tf_func(tf.image.resize_images) @partial_support(True) @ps_description("Upsample required 4D input in Tensorflow.") class Upsample(BackendHandler): @classmethod def args_check(cls, node, **kwargs): x = kwargs["tensor_dict"][node.inputs[0]] x_shape = x.get_shape().as_list() if len(x_shape) != 4: exception.OP_UNSUPPORTED_EXCEPT("Upsample without 4D input", "Tensorflow") if node.attrs.get("mode", "nearest").lower() not in ["nearest", "bilinear", "linear"]: exception.OP_UNSUPPORTED_EXCEPT("Upsample without nearest or bilinear", "Tensorflow") @classmethod def version_7(cls, node, **kwargs): x = kwargs["tensor_dict"][node.inputs[0]] x_shape = x.get_shape().as_list() attrs = copy.deepcopy(node.attrs) scales = attrs["scales"] new_height = np.floor(x_shape[2] * scales[2]) new_weight = np.floor(x_shape[3] * scales[3]) mode = attrs.get("mode", "nearest") if mode.lower() == "bilinear" or mode.lower() == "linear": mode = tf.image.ResizeMethod.BILINEAR else: mode = tf.image.ResizeMethod.NEAREST_NEIGHBOR attrs["size"] = np.array((new_height, new_weight), dtype=np.int32) attrs["method"] = mode return [ cls.make_tensor_from_onnx_node( node, attrs=attrs, c_last_only=True, **kwargs) ] @classmethod def version_9(cls, node, **kwargs): x = kwargs["tensor_dict"][node.inputs[0]] x_shape = tf_shape(x) attrs = copy.deepcopy(node.attrs) scales = kwargs["tensor_dict"][node.inputs[1]] assert_n_c_scale_is_one = tf.Assert( tf.logical_and(tf.equal(scales[0], 1), tf.equal(scales[1], 1)), [scales]) with tf.control_dependencies([assert_n_c_scale_is_one]): h_w_scale = scales[2:] h_w_shape = x_shape[2:] new_h_w_shape = tf.cast(h_w_scale * tf.cast(h_w_shape, scales.dtype), tf.int32) mode = attrs.get("mode", "nearest") if mode.lower() == "bilinear" or mode.lower() == "linear": mode = tf.image.ResizeMethod.BILINEAR else: mode = tf.image.ResizeMethod.NEAREST_NEIGHBOR attrs["size"] = new_h_w_shape attrs["method"] = mode # Remove scale. upsample_node = copy.deepcopy(node) del upsample_node.inputs[1] return [ cls.make_tensor_from_onnx_node( upsample_node, attrs=attrs, c_last_only=True, **kwargs) ]