@@ -70,4 +70,89 @@ void convertResizeV10(const onnx::NodeProto &onnx_node, ConverterContext *contex
7070 context->setNodeOutputs (onnx_node, {result});
7171}
7272
73+ void convertResizeV11 (const onnx::NodeProto &onnx_node, ConverterContext *context)
74+ {
75+ std::vector<mir::Operation::Output *> inputs = context->getNodeInputs (onnx_node);
76+ mir::Graph *graph = context->getGraph ();
77+
78+ const auto coordinate_transformation_mode =
79+ getAttributeValue<std::string>(onnx_node, " coordinate_transformation_mode" , " half_pixel" );
80+ // INFO: As of now only 'nearest' mode is supported, so this attribute is not used.
81+ // const auto cubic_coeff_a = getAttributeValue<float>(onnx_node, "cubic_coeff_a", -0.75);
82+ const auto exclude_outside = getAttributeValue<std::int64_t >(onnx_node, " exclude_outside" , 0 );
83+ // INFO: As of now only 'nearest' mode is supported, so this attribute is not used.
84+ // const auto extrapolation_value = getAttributeValue<float>(onnx_node, "extrapolation_value",
85+ // 0.0);
86+ const auto mode = getAttributeValue<std::string>(onnx_node, " mode" , " nearest" );
87+ const auto nearest_mode =
88+ getAttributeValue<std::string>(onnx_node, " nearest_mode" , " round_prefer_floor" );
89+
90+ if (coordinate_transformation_mode != " half_pixel" )
91+ throw std::runtime_error{
92+ " Resize v11: Only 'half_pixel' coordinate transformation is supported" };
93+ if (exclude_outside != 0 )
94+ throw std::runtime_error{" Resize v11: The exclude outside option is not supported" };
95+ const auto resize_method = getResizeMethod (mode);
96+ if (nearest_mode != " round_prefer_floor" )
97+ throw std::runtime_error{" Resize v11: Only 'round_prefer_floor' rounding is supported" };
98+
99+ // Inputs: [0] X, [1] ROI, [2] scales, [3] sizes (optional)
100+ if (inputs.size () < 3 || inputs.size () > 4 )
101+ throw std::runtime_error{" Resize v11: Expected between 3 and 4 inputs" };
102+
103+ int rank = inputs[0 ]->getShape ().rank ();
104+ if (rank != 4 )
105+ throw std::runtime_error (" Resize v11: Only 4-D input is supported" );
106+
107+ auto *scales = dynamic_cast <mir::ops::ConstantOp *>(inputs[2 ]->getNode ());
108+ assert (scales && " Scales could be a constant tensor only" );
109+ auto scales_tensor = mir::Tensor<float >(scales->getValue ());
110+ auto scales_tensor_elements = scales_tensor.getShape ().numElements ();
111+
112+ std::vector<float > scales_vector;
113+
114+ // If scales is empty, use sizes input to calculate scales.
115+ if (scales_tensor_elements == 0 )
116+ {
117+ if (inputs.size () != 4 )
118+ throw std::runtime_error{" Resize v11: Sizes input is required when scales is empty" };
119+
120+ auto *sizes = dynamic_cast <mir::ops::ConstantOp *>(inputs[3 ]->getNode ());
121+ assert (sizes && " Sizes could be a constant tensor only" );
122+ auto sizes_tensor = mir::Tensor<std::int64_t >(scales->getValue ());
123+ auto sizes_tensor_elements = sizes_tensor.getShape ().numElements ();
124+
125+ if (sizes_tensor_elements != rank)
126+ throw std::runtime_error{" Resize v10: The number of elements of 'sizes' should be the same "
127+ " as the rank of input 'X'" };
128+
129+ auto &input_shape = inputs[0 ]->getShape ();
130+ scales_vector.resize (sizes_tensor_elements);
131+
132+ // Calculate scales from sizes
133+ for (int i = 0 ; i < sizes_tensor_elements; i++)
134+ {
135+ if (input_shape.dim (i) == 0 )
136+ throw std::runtime_error{" Resize v11: Input dimension cannot be zero" };
137+ scales_vector[i] = static_cast <float >(sizes_tensor.atOffset (i)) / input_shape.dim (i);
138+ // Verify that the float arithmetic is reversible.
139+ if (input_shape.dim (i) * scales_vector[i] != sizes_tensor.atOffset (i))
140+ throw std::runtime_error{" Resize v11: Invalid sizes to scales conversion" };
141+ }
142+ }
143+ else
144+ {
145+ if (scales_tensor_elements != rank)
146+ throw std::runtime_error{" Resize v10: The number of elements of 'scales' should be the same "
147+ " as the rank of input 'X'" };
148+ scales_vector.resize (scales_tensor_elements);
149+ for (int i = 0 ; i < scales_tensor_elements; i++)
150+ scales_vector[i] = scales_tensor.atOffset (i);
151+ }
152+
153+ auto result =
154+ createOp<mir::ops::ResizeOp>(graph, inputs[0 ], resize_method, scales_vector)->getOutput (0 );
155+ context->setNodeOutputs (onnx_node, {result});
156+ }
157+
73158} // namespace mir_onnx
0 commit comments