Skip to content

Commit 82d22bc

Browse files
committed
[mir] Add Resize v11 operator to ONNX importer
This commit adds support for importing a subset of Resize v11 operator. As of now only nearest interpolation mode is supported with half down rounding method. ONE-DCO-1.0-Signed-off-by: Arkadiusz Bokowy <a.bokowy@samsung.com>
1 parent c0df241 commit 82d22bc

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

compiler/mir/src/mir_onnx_importer/ONNXOpRegistration.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ inline void registerSupportedOps()
206206
UNSUPPORTED(Reshape, firstUnknownOpset);
207207

208208
REG(Resize, 10);
209-
UNSUPPORTED(Resize, 11);
209+
REG(Resize, 11);
210210
UNSUPPORTED(Resize, firstUnknownOpset);
211211

212212
REG(Shape, 1);

compiler/mir/src/mir_onnx_importer/Op/Resize.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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>(sizes->getValue());
123+
auto sizes_tensor_elements = sizes_tensor.getShape().numElements();
124+
125+
if (sizes_tensor_elements != rank)
126+
throw std::runtime_error{"Resize v11: 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 v11: 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

compiler/mir/src/mir_onnx_importer/Op/Resize.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace mir_onnx
2323
{
2424

2525
void convertResizeV10(const onnx::NodeProto &onnx_node, ConverterContext *context);
26+
void convertResizeV11(const onnx::NodeProto &onnx_node, ConverterContext *context);
2627

2728
} // namespace mir_onnx
2829

0 commit comments

Comments
 (0)