inline void ResizeBilinear(const float* input_data, const Dims<4>& input_dims,
const int32* output_size_data,
const Dims<4>& output_size_dims, float* output_data,
- const Dims<4>& output_dims) {
+ const Dims<4>& output_dims, bool align_corners) {
gemmlowp::ScopedProfilingLabel label("ResizeBilinear");
int32 batches = MatchingArraySize(input_dims, 3, output_dims, 3);
int32 input_height = ArraySize(input_dims, 2);
int32 output_width = output_size_data[Offset(output_size_dims, 1, 0, 0, 0)];
// Specialize for 2x2 upsample.
- if (output_height == 2 * input_height && output_width == 2 * input_width) {
+ if (!align_corners && output_height == 2 * input_height &&
+ output_width == 2 * input_width) {
ResizeBilinear2x2(input_data, input_dims, output_data, output_dims, batches,
input_height, input_width, depth, output_height,
output_width);
} else {
float height_scale = static_cast<float>(input_height) / output_height;
float width_scale = static_cast<float>(input_width) / output_width;
+ if (align_corners && output_height > 1) {
+ height_scale = static_cast<float>(input_height - 1) / (output_height - 1);
+ }
+ if (align_corners && output_width > 1) {
+ width_scale = static_cast<float>(input_width - 1) / (output_width - 1);
+ }
ResizeBilinearGeneric(input_data, input_dims, output_data, output_dims,
batches, input_height, input_width, depth,
}
}
+// legacy, for compatibility with old checked-in code
+inline void ResizeBilinear(const float* input_data, const Dims<4>& input_dims,
+ const int32* output_size_data,
+ const Dims<4>& output_size_dims, float* output_data,
+ const Dims<4>& output_dims) {
+ ResizeBilinear(input_data, input_dims, output_size_data, output_size_dims,
+ output_data, output_dims, /*align_corners=*/false);
+}
+
template <typename T>
inline void SpaceToBatchND(const T* input_data, const Dims<4>& input_dims,
const int32* block_shape_data,
inline void ResizeBilinear(const float* input_data, const Dims<4>& input_dims,
const int32* output_size_data,
const Dims<4>& output_size_dims, float* output_data,
- const Dims<4>& output_dims) {
+ const Dims<4>& output_dims, bool align_corners) {
int32 batches = MatchingArraySize(input_dims, 3, output_dims, 3);
int32 input_height = ArraySize(input_dims, 2);
int32 input_width = ArraySize(input_dims, 1);
int32 output_width = output_size_data[Offset(output_size_dims, 1, 0, 0, 0)];
float height_scale = static_cast<float>(input_height) / output_height;
float width_scale = static_cast<float>(input_width) / output_width;
+ if (align_corners && output_height > 1) {
+ height_scale = static_cast<float>(input_height - 1) / (output_height - 1);
+ }
+ if (align_corners && output_width > 1) {
+ width_scale = static_cast<float>(input_width - 1) / (output_width - 1);
+ }
for (int b = 0; b < batches; ++b) {
for (int y = 0; y < output_height; ++y) {
}
}
+// legacy, for compatibility with old checked-in code
+inline void ResizeBilinear(const float* input_data, const Dims<4>& input_dims,
+ const int32* output_size_data,
+ const Dims<4>& output_size_dims, float* output_data,
+ const Dims<4>& output_dims) {
+ ResizeBilinear(input_data, input_dims, output_size_data, output_size_dims,
+ output_data, output_dims, /*align_corners=*/false);
+}
+
template <typename T>
inline void SpaceToBatchND(const T* input_data, const Dims<4>& input_dims,
const int32* block_shape_data,
*resize_op->add_input() = src_op.inputs[0];
*resize_op->add_input() = src_op.inputs[1];
(*resize_op->mutable_attr())["T"].set_type(DT_FLOAT);
+ (*resize_op->mutable_attr())["align_corners"].set_b(src_op.align_corners);
}
namespace {
CHECK_EQ(node.op(), "ResizeBilinear");
CheckInputsCount(node, tf_import_flags, 2);
auto* op = new ResizeBilinearOperator;
+
+ op->align_corners = false;
+ if (HasAttr(node, "align_corners")) {
+ op->align_corners = GetBoolAttr(node, "align_corners");
+ }
+
op->inputs.push_back(node.input(0));
op->inputs.push_back(node.input(1));
op->outputs.push_back(node.name());
// TensorFlow equivalent: ResizeBilinear
struct ResizeBilinearOperator : Operator {
ResizeBilinearOperator() : Operator(OperatorType::kResizeBilinear) {}
+
+ bool align_corners = false;
};
// SpaceToBatchND operator. It divides spatial dimensions into a grid of