Add support for half_pixel_centers in resize ops w/ Hexagon

PiperOrigin-RevId: 323638839
Change-Id: Ic927930989d6bdc362642f111f028d7153d759ec
This commit is contained in:
Sachin Joglekar 2020-07-28 13:15:45 -07:00 committed by TensorFlower Gardener
parent 36f3e515a4
commit 68b5f1defd
5 changed files with 107 additions and 17 deletions

View File

@ -56,7 +56,7 @@ TfLiteStatus ResizeBilinearOpBuilder::PopulateSubGraph(
AddInput(TensorID(input_min_const->GetID(), 0));
AddInput(TensorID(input_max_const->GetID(), 0));
// Align Corners
// Align Corners & half-pixel-centers.
const TfLiteResizeBilinearParams* params =
reinterpret_cast<const TfLiteResizeBilinearParams*>(builtin_data_);
int align_corners = params->align_corners ? 1 : 0;
@ -64,6 +64,11 @@ TfLiteStatus ResizeBilinearOpBuilder::PopulateSubGraph(
kScalarShape, reinterpret_cast<char*>(&align_corners),
sizeof(align_corners));
AddInput(TensorID(align_corners_const->GetID(), 0));
int half_pixel_centers = params->half_pixel_centers ? 1 : 0;
auto* half_pixel_centers_const = graph_builder_->AddConstNodeWithData(
kScalarShape, reinterpret_cast<char*>(&half_pixel_centers),
sizeof(half_pixel_centers));
AddInput(TensorID(half_pixel_centers_const->GetID(), 0));
// Output
int output_batch_size, output_height_size, output_width_size,

View File

@ -59,11 +59,16 @@ TfLiteStatus ResizeNearestNeighborOpBuilder::PopulateSubGraph(
// Align corners.
const TfLiteResizeNearestNeighborParams* params =
reinterpret_cast<const TfLiteResizeNearestNeighborParams*>(builtin_data_);
align_corners_ = params->align_corners;
int align_corners = params->align_corners ? 1 : 0;
auto* align_corners_const = graph_builder_->AddConstNodeWithData(
kScalarShape, reinterpret_cast<char*>(&align_corners_),
sizeof(align_corners_));
kScalarShape, reinterpret_cast<char*>(&align_corners),
sizeof(align_corners));
AddInput(TensorID(align_corners_const->GetID(), 0));
int half_pixel_centers = params->half_pixel_centers ? 1 : 0;
auto* half_pixel_centers_const = graph_builder_->AddConstNodeWithData(
kScalarShape, reinterpret_cast<char*>(&half_pixel_centers),
sizeof(half_pixel_centers));
AddInput(TensorID(half_pixel_centers_const->GetID(), 0));
// Hexagon outputs for this node.
int output_batch_size, output_height_size, output_width_size,

View File

@ -40,7 +40,6 @@ class ResizeNearestNeighborOpBuilder : public OpBuilder {
private:
TensorID node_output_;
float input_min_, input_max_;
bool align_corners_;
};
} // namespace hexagon

View File

@ -22,17 +22,24 @@ class ResizeOpModel : public SingleOpModelWithHexagon {
public:
explicit ResizeOpModel(BuiltinOperator op_type, const TensorData& input,
std::initializer_list<int> size_data,
const TensorData& output) {
const TensorData& output, bool align_corners = false,
bool half_pixel_centers = false) {
input_ = AddInput(input);
size_ = AddConstInput(TensorType_INT32, size_data, {2});
output_ = AddOutput(output);
if (op_type == BuiltinOperator_RESIZE_NEAREST_NEIGHBOR) {
SetBuiltinOp(BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
BuiltinOptions_ResizeNearestNeighborOptions,
CreateResizeNearestNeighborOptions(builder_).Union());
CreateResizeNearestNeighborOptions(
builder_, /*align_corners*/ align_corners,
/*half_pixel_centers*/ half_pixel_centers)
.Union());
} else {
SetBuiltinOp(op_type, BuiltinOptions_ResizeBilinearOptions,
CreateResizeBilinearOptions(builder_).Union());
CreateResizeBilinearOptions(
builder_, /**align_corners**/ align_corners,
/**half_pixel_centers**/ half_pixel_centers)
.Union());
}
BuildInterpreter({GetShape(input_)});
}
@ -66,9 +73,6 @@ class ResizeOpModel : public SingleOpModelWithHexagon {
int output_;
};
// TODO(b/154007913): Investigate why NearestNeighbor does not provide the same
// output always, requiring high allowed error.
TEST(ResizeOpModel, HorizontalResizeBiliear_UInt8) {
ResizeOpModel m(BuiltinOperator_RESIZE_BILINEAR,
{TensorType_UINT8, {1, 1, 2, 1}, -2.0, 10}, {1, 3},
@ -87,7 +91,7 @@ TEST(ResizeOpModel, HorizontalResizeNearestNeighbor_Int8) {
m.ApplyDelegateAndInvoke();
EXPECT_THAT(m.GetDequantizedOutput<int8_t>(),
ElementsAreArray(ArrayFloatNear({3.01176, 3.01176, 6.02353},
/*max_abs_error=*/4)));
/*max_abs_error=*/1)));
}
TEST(ResizeOpModel, VerticalResizeBiliear_Int8) {
@ -108,7 +112,7 @@ TEST(ResizeOpModel, VerticalResizeNearestNeighbor_UInt8) {
m.ApplyDelegateAndInvoke();
EXPECT_THAT(m.GetDequantizedOutput<uint8_t>(),
ElementsAreArray(ArrayFloatNear({3.01961, 3.01961, 8.97255},
/*max_abs_error=*/6)));
/*max_abs_error=*/1)));
}
TEST(ResizeOpModel, ThreeDimensionalResizeBiliear_UInt8) {
@ -146,7 +150,7 @@ TEST(ResizeOpModel, ThreeDimensionalResizeNearestNeighbor_Int8) {
3.01177, 4.01569, 3.01177, 4.01569, 6.02353, 10.0392, //
10.0392, 12.0471, 10.0392, 12.0471, 14.0549, 16.0627, //
},
/*max_abs_error=*/13)));
/*max_abs_error=*/1)));
}
TEST(ResizeOpModel, TwoDimensionalResizeBilinearWithTwoBatches_Int8) {
@ -193,7 +197,84 @@ TEST(ResizeOpModel, TwoDimensionalResizeNNWithTwoBatches_UInt8) {
4.01569, 4.01569, 10.0392, //
12.0471, 12.0471, 16.0627, //
},
/*max_abs_error=*/13)));
/*max_abs_error=*/1)));
}
TEST(ResizeOpModel, TwoDimResizeBilinearWithTwoBatches_HalfPixelCenters_UInt8) {
ResizeOpModel m(BuiltinOperator_RESIZE_BILINEAR,
{TensorType_UINT8, {2, 2, 2, 1}, -2.0, 20}, {3, 3},
{TensorType_UINT8, {}, -2.0, 20}, /**align_corners**/ false,
/**half_pixel_centers**/ true);
m.SetQuantizedInput<uint8_t>({
3, 6, //
9, 12, //
4, 10, //
12, 16 //
});
m.ApplyDelegateAndInvoke();
EXPECT_THAT(m.GetDequantizedOutput<uint8_t>(),
ElementsAreArray(ArrayFloatNear({2, 4, 6, //
6, 7, 9, //
9, 10, 12, //
4, 7, 10, //
8, 10, 13, //
12, 14, 16},
/*max_abs_error=*/2)));
}
TEST(ResizeOpModel, TwoDimResizeBilinearWithTwoBatches_AlignCorners_UInt8) {
ResizeOpModel m(BuiltinOperator_RESIZE_BILINEAR,
{TensorType_UINT8, {2, 2, 2, 1}, -2.0, 20}, {3, 3},
{TensorType_UINT8, {}, -2.0, 20}, /**align_corners**/ true,
/**half_pixel_centers**/ false);
m.SetQuantizedInput<uint8_t>({
3, 6, //
9, 12, //
4, 10, //
12, 16 //
});
m.ApplyDelegateAndInvoke();
EXPECT_THAT(m.GetDequantizedOutput<uint8_t>(),
ElementsAreArray(ArrayFloatNear({3, 5, 6, //
7, 9, 10, //
9, 11, 12, //
4, 8, 10, //
9, 12, 13, //
12, 15, 16},
/*max_abs_error=*/2)));
}
TEST(ResizeOpModel, ThreeDimensionalResizeNN_AlignCorners_UInt8) {
ResizeOpModel m(BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
{TensorType_UINT8, {1, 2, 2, 2}, -2.0, 20}, {3, 3},
{TensorType_UINT8, {}, -2.0, 20}, /**align_corners**/ true);
m.SetQuantizedInput<uint8_t>({
3, 4, 6, 10, //
10, 12, 14, 16, //
});
m.ApplyDelegateAndInvoke();
EXPECT_THAT(m.GetDequantizedOutput<uint8_t>(),
ElementsAreArray(ArrayFloatNear({3, 4, 6, 10, 6, 10, //
10, 12, 14, 16, 14, 16, //
10, 12, 14, 16, 14, 16},
/*max_abs_error=*/1)));
}
TEST(ResizeOpModel, ThreeDimensionalResizeNN_HalfPixelCenters_UInt8) {
ResizeOpModel m(BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
{TensorType_UINT8, {1, 2, 2, 2}, -2.0, 20}, {3, 3},
{TensorType_UINT8, {}, -2.0, 20}, /**align_corners**/ false,
/**half_pixel_centers**/ true);
m.SetQuantizedInput<uint8_t>({
3, 4, 6, 10, //
10, 12, 14, 16, //
});
m.ApplyDelegateAndInvoke();
EXPECT_THAT(m.GetDequantizedOutput<uint8_t>(),
ElementsAreArray(ArrayFloatNear({3, 4, 6, 10, 6, 10, //
10, 12, 14, 16, 14, 16, //
10, 12, 14, 16, 14, 16},
/*max_abs_error=*/1)));
}
} // namespace tflite

View File

@ -91,8 +91,6 @@ bool CheckOpVersion(const TfLiteRegistration* registration) {
case kTfLiteBuiltinPad:
case kTfLiteBuiltinQuantize:
case kTfLiteBuiltinRelu6:
case kTfLiteBuiltinResizeBilinear:
case kTfLiteBuiltinResizeNearestNeighbor:
case kTfLiteBuiltinSlice:
case kTfLiteBuiltinSoftmax:
case kTfLiteBuiltinSpaceToDepth:
@ -107,6 +105,8 @@ bool CheckOpVersion(const TfLiteRegistration* registration) {
return registration->version == 2;
case kTfLiteBuiltinConv2d:
case kTfLiteBuiltinDepthwiseConv2d:
case kTfLiteBuiltinResizeBilinear:
case kTfLiteBuiltinResizeNearestNeighbor:
return registration->version <= 3;
case kTfLiteBuiltinFullyConnected:
return registration->version <= 4;