1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/core/common_runtime/device_factory.h"
17 #include "tensorflow/core/framework/allocator.h"
18 #include "tensorflow/core/framework/fake_input.h"
19 #include "tensorflow/core/framework/node_def_builder.h"
20 #include "tensorflow/core/framework/op_kernel.h"
21 #include "tensorflow/core/framework/tensor.h"
22 #include "tensorflow/core/framework/tensor_testutil.h"
23 #include "tensorflow/core/framework/types.h"
24 #include "tensorflow/core/framework/types.pb.h"
25 #include "tensorflow/core/kernels/ops_testutil.h"
26 #include "tensorflow/core/kernels/ops_util.h"
27 #include "tensorflow/core/lib/core/status_test_util.h"
28 #include "tensorflow/core/lib/random/random.h"
29 #include "tensorflow/core/lib/strings/str_util.h"
30 #include "tensorflow/core/platform/test.h"
31 #include "tensorflow/core/platform/test_benchmark.h"
32 #include "tensorflow/core/public/session_options.h"
33
34 namespace tensorflow {
35 enum class TestDevice { CPU, GPU };
36
37 class ResizeBilinearOpTestBase
38 : public OpsTestBase,
39 public ::testing::WithParamInterface<TestDevice> {
40 protected:
ResizeBilinearOpTestBase()41 explicit ResizeBilinearOpTestBase()
42 : align_corners_(false), half_pixel_centers_(false) {}
43
SetUp()44 void SetUp() override {
45 if (GetParam() == TestDevice::GPU) {
46 std::unique_ptr<Device> device_gpu(
47 DeviceFactory::NewDevice("GPU", {}, "/job:a/replica:0/task:0"));
48 SetDevice(DEVICE_GPU, std::move(device_gpu));
49 }
50
51 TF_EXPECT_OK(NodeDefBuilder("resize_bilinear_op", "ResizeBilinear")
52 .Input(FakeInput(DT_FLOAT))
53 .Input(FakeInput(DT_INT32))
54 .Attr("align_corners", align_corners_)
55 .Attr("half_pixel_centers", half_pixel_centers_)
56 .Finalize(node_def()));
57 TF_EXPECT_OK(InitOp());
58 }
59
SetRandomImageInput(const TensorShape & shape)60 const Tensor* SetRandomImageInput(const TensorShape& shape) {
61 inputs_.clear();
62
63 CHECK_EQ(shape.dims(), 4) << "All images must have 4 dimensions.";
64 bool is_ref = IsRefType(input_types_[inputs_.size()]);
65 Tensor* input = new Tensor(allocator(), DataTypeToEnum<float>::v(), shape);
66 input->flat<float>().setRandom();
67 tensors_.push_back(input);
68 if (is_ref) {
69 CHECK_EQ(RemoveRefType(input_types_[inputs_.size()]),
70 DataTypeToEnum<float>::v());
71 inputs_.push_back({&lock_for_refs_, input});
72 } else {
73 CHECK_EQ(input_types_[inputs_.size()], DataTypeToEnum<float>::v());
74 inputs_.push_back({nullptr, input});
75 }
76 return input;
77 }
78
79 // This is the straight forward unoptimized implementation of resize bilinear
80 // We use this to confirm that the optimized version is exactly identical.
ResizeBilinearBaseline(TTypes<float,4>::ConstTensor images,TTypes<float,4>::Tensor output)81 void ResizeBilinearBaseline(TTypes<float, 4>::ConstTensor images,
82 TTypes<float, 4>::Tensor output) {
83 const int batch = images.dimension(0);
84 const int64 in_height = images.dimension(1);
85 const int64 in_width = images.dimension(2);
86 const int channels = images.dimension(3);
87
88 ASSERT_EQ(batch, output.dimension(0));
89 ASSERT_EQ(channels, output.dimension(3));
90
91 const int64 out_height = output.dimension(1);
92 const int64 out_width = output.dimension(2);
93
94 const float height_scale = in_height / static_cast<float>(out_height);
95 const float width_scale = in_width / static_cast<float>(out_width);
96
97 for (int b = 0; b < batch; ++b) {
98 for (int64 y = 0; y < out_height; ++y) {
99 const float in_y =
100 half_pixel_centers_
101 ? (static_cast<float>(y) + 0.5f) * height_scale - 0.5f
102 : y * height_scale;
103 const int64 top_y_index =
104 std::max(static_cast<int64>(floorf(in_y)), static_cast<int64>(0));
105 const int64 bottom_y_index =
106 std::min(static_cast<int64>(ceilf(in_y)), in_height - 1);
107 const float y_lerp = in_y - std::floor(in_y);
108 for (int64 x = 0; x < out_width; ++x) {
109 const float in_x =
110 half_pixel_centers_
111 ? (static_cast<float>(x) + 0.5f) * width_scale - 0.5f
112 : x * width_scale;
113 const int64 left_x_index =
114 std::max(static_cast<int64>(floorf(in_x)), static_cast<int64>(0));
115 const int64 right_x_index =
116 std::min(static_cast<int64>(ceilf(in_x)), in_width - 1);
117 const float x_lerp = in_x - std::floor(in_x);
118 for (int c = 0; c < channels; ++c) {
119 const float top_left = images(b, top_y_index, left_x_index, c);
120 const float top_right = images(b, top_y_index, right_x_index, c);
121 const float bottom_left =
122 images(b, bottom_y_index, left_x_index, c);
123 const float bottom_right =
124 images(b, bottom_y_index, right_x_index, c);
125 const float top = top_left + (top_right - top_left) * x_lerp;
126 const float bottom =
127 bottom_left + (bottom_right - bottom_left) * x_lerp;
128 output(b, y, x, c) = top + (bottom - top) * y_lerp;
129 }
130 }
131 }
132 }
133 }
134
TestResize(int batch_size,int input_width,int input_height,int channels,int output_width,int output_height)135 void TestResize(int batch_size, int input_width, int input_height,
136 int channels, int output_width, int output_height) {
137 const TensorShape shape({batch_size, input_width, input_height, channels});
138 const Tensor* input = SetRandomImageInput(shape);
139 AddInputFromArray<int32>(TensorShape({2}), {output_width, output_height});
140 TF_ASSERT_OK(RunOpKernel());
141
142 std::unique_ptr<Tensor> expected(new Tensor(
143 allocator(), DataTypeToEnum<float>::v(),
144 TensorShape({batch_size, output_width, output_height, channels})));
145 ResizeBilinearBaseline(input->tensor<float, 4>(),
146 expected->tensor<float, 4>());
147 test::ExpectClose(*expected, *GetOutput(0), /*atol=*/4e-5);
148 }
149
RunManyRandomTests(int channels)150 void RunManyRandomTests(int channels) {
151 for (int batch_size : {1, 2, 5}) {
152 for (int in_w : {2, 4, 7, 20, 165}) {
153 for (int in_h : {1, 3, 5, 8, 100, 233}) {
154 for (int target_height : {1, 2, 3, 50, 113}) {
155 for (int target_width : {target_height, target_height / 2 + 1}) {
156 TestResize(batch_size, in_w, in_h, channels, target_width,
157 target_height);
158 }
159 }
160 }
161 }
162 }
163 }
164
165 bool align_corners_;
166 bool half_pixel_centers_;
167 };
168
169 class ResizeBilinearOpTest : public ResizeBilinearOpTestBase {
170 public:
ResizeBilinearOpTest()171 ResizeBilinearOpTest() {}
172 };
173
174 class ResizeBilinearHalfPixelCentersOpTest : public ResizeBilinearOpTestBase {
175 public:
ResizeBilinearHalfPixelCentersOpTest()176 ResizeBilinearHalfPixelCentersOpTest() { half_pixel_centers_ = true; }
177 };
178
179 class ResizeBilinearOpAlignCornersTest : public ResizeBilinearOpTestBase {
180 public:
ResizeBilinearOpAlignCornersTest()181 ResizeBilinearOpAlignCornersTest() { align_corners_ = true; }
182 };
183
TEST_P(ResizeBilinearOpTest,TestResizeRandomDataSeveralInputsSizes1Channel)184 TEST_P(ResizeBilinearOpTest, TestResizeRandomDataSeveralInputsSizes1Channel) {
185 RunManyRandomTests(1);
186 }
187
TEST_P(ResizeBilinearOpTest,TestResizeRandomDataSeveralInputsSizes3Channels)188 TEST_P(ResizeBilinearOpTest, TestResizeRandomDataSeveralInputsSizes3Channels) {
189 RunManyRandomTests(3);
190 }
191
TEST_P(ResizeBilinearOpTest,TestResizeRandomDataSeveralInputsSizes4Channels)192 TEST_P(ResizeBilinearOpTest, TestResizeRandomDataSeveralInputsSizes4Channels) {
193 RunManyRandomTests(4);
194 }
195
TEST_P(ResizeBilinearOpTest,TestBilinear2x2To1x1)196 TEST_P(ResizeBilinearOpTest, TestBilinear2x2To1x1) {
197 // Input:
198 // 1, 2
199 // 3, 4
200 AddInputFromArray<float>(TensorShape({1, 2, 2, 1}), {1, 2, 3, 4});
201 AddInputFromArray<int32>(TensorShape({2}), {1, 1});
202 TF_ASSERT_OK(RunOpKernel());
203
204 // When scaling down, we have to arbitrarily pick a pixel from the
205 // original input. In this case, we choose the top/left most pixel.
206 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 1, 1, 1}));
207 test::FillValues<float>(&expected, {1.0});
208 test::ExpectClose(expected, *GetOutput(0));
209 }
210
TEST_P(ResizeBilinearOpTest,TestBilinearRandom2x2To1x1)211 TEST_P(ResizeBilinearOpTest, TestBilinearRandom2x2To1x1) {
212 const Tensor* input = SetRandomImageInput(TensorShape({1, 2, 2, 1}));
213 AddInputFromArray<int32>(TensorShape({2}), {1, 1});
214 TF_ASSERT_OK(RunOpKernel());
215
216 // When scaling down, we have to arbitrarily pick a pixel from the
217 // original input. In this case, we choose the top/left most pixel.
218 Tensor* output = GetOutput(0);
219 std::unique_ptr<Tensor> expected(new Tensor(
220 allocator(), DataTypeToEnum<float>::v(), TensorShape({1, 1, 1, 1})));
221 ResizeBilinearBaseline(input->tensor<float, 4>(),
222 expected->tensor<float, 4>());
223 EXPECT_EQ(input->flat<float>()(0), output->flat<float>()(0));
224 test::ExpectClose(*expected, *output);
225 }
226
TEST_P(ResizeBilinearOpAlignCornersTest,TestBilinearAlignCorners2x2To1x1)227 TEST_P(ResizeBilinearOpAlignCornersTest, TestBilinearAlignCorners2x2To1x1) {
228 // Input:
229 // 1, 2
230 // 3, 4
231 AddInputFromArray<float>(TensorShape({1, 2, 2, 1}), {1, 2, 3, 4});
232 AddInputFromArray<int32>(TensorShape({2}), {1, 1});
233 TF_ASSERT_OK(RunOpKernel());
234
235 // When scaling down, we have to arbitrarily pick a pixel from the
236 // original input. In this case, we choose the top/left most pixel.
237 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 1, 1, 1}));
238 test::FillValues<float>(&expected, {1.0});
239 test::ExpectClose(expected, *GetOutput(0));
240 }
241
TEST_P(ResizeBilinearOpTest,TestBilinear2x2To3x3)242 TEST_P(ResizeBilinearOpTest, TestBilinear2x2To3x3) {
243 // Input:
244 // 1, 2
245 // 3, 4
246 AddInputFromArray<float>(TensorShape({1, 2, 2, 1}), {1, 2, 3, 4});
247 AddInputFromArray<int32>(TensorShape({2}), {3, 3});
248 TF_ASSERT_OK(RunOpKernel());
249
250 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 3, 3, 1}));
251
252 // clang-format off
253 test::FillValues<float>(&expected,
254 {1, 5.0f / 3, 2,
255 7.0f / 3, 3, 10.0f / 3,
256 3, 11.0f / 3, 4});
257
258 // clang-format on
259 test::ExpectClose(expected, *GetOutput(0));
260 }
261
TEST_P(ResizeBilinearOpAlignCornersTest,TestBilinearAlignCorners2x2To3x3)262 TEST_P(ResizeBilinearOpAlignCornersTest, TestBilinearAlignCorners2x2To3x3) {
263 // Input:
264 // 1, 2
265 // 3, 4
266 AddInputFromArray<float>(TensorShape({1, 2, 2, 1}), {1, 2, 3, 4});
267 AddInputFromArray<int32>(TensorShape({2}), {3, 3});
268 TF_ASSERT_OK(RunOpKernel());
269
270 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 3, 3, 1}));
271
272 // The corners exactly align with the original corners, and we bilinear
273 // interpolate the values in between.
274
275 // clang-format off
276 test::FillValues<float>(&expected,
277 {1, 1.5, 2,
278 2, 2.5, 3,
279 3, 3.5, 4});
280
281 // clang-format on
282 test::ExpectClose(expected, *GetOutput(0));
283 }
284
TEST_P(ResizeBilinearOpTest,TestBilinear3x3To2x2)285 TEST_P(ResizeBilinearOpTest, TestBilinear3x3To2x2) {
286 // Input:
287 // 1, 2, 3
288 // 4, 5, 6
289 // 7, 8, 9
290 AddInputFromArray<float>(TensorShape({1, 3, 3, 1}),
291 {1, 2, 3, 4, 5, 6, 7, 8, 9});
292 AddInputFromArray<int32>(TensorShape({2}), {2, 2});
293 TF_ASSERT_OK(RunOpKernel());
294
295 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 2, 2, 1}));
296
297 // clang-format off
298 test::FillValues<float>(&expected,
299 {1, 2.5,
300 5.5, 7});
301
302 // clang-format on
303 test::ExpectClose(expected, *GetOutput(0));
304 }
305
TEST_P(ResizeBilinearOpAlignCornersTest,TestBilinearAlignCorners3x3To2x2)306 TEST_P(ResizeBilinearOpAlignCornersTest, TestBilinearAlignCorners3x3To2x2) {
307 // Input:
308 // 1, 2, 3
309 // 4, 5, 6
310 // 7, 8, 9
311 AddInputFromArray<float>(TensorShape({1, 3, 3, 1}),
312 {1, 2, 3, 4, 5, 6, 7, 8, 9});
313 AddInputFromArray<int32>(TensorShape({2}), {2, 2});
314 TF_ASSERT_OK(RunOpKernel());
315
316 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 2, 2, 1}));
317
318 // clang-format off
319 test::FillValues<float>(&expected,
320 {1, 3,
321 7, 9});
322
323 // clang-format on
324 test::ExpectClose(expected, *GetOutput(0));
325 }
326
TEST_P(ResizeBilinearOpTest,TestBilinear3x3To4x4)327 TEST_P(ResizeBilinearOpTest, TestBilinear3x3To4x4) {
328 // Input:
329 // 1, 2, 3,
330 // 4, 5, 6,
331 // 7, 8, 9
332 AddInputFromArray<float>(TensorShape({1, 3, 3, 1}),
333 {1, 2, 3, 4, 5, 6, 7, 8, 9});
334 AddInputFromArray<int32>(TensorShape({2}), {4, 4});
335 TF_ASSERT_OK(RunOpKernel());
336
337 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 4, 4, 1}));
338 // clang-format off
339 test::FillValues<float>(&expected,
340 {1, 1.75, 2.5, 3,
341 3.25, 4, 4.75, 5.25,
342 5.5, 6.25, 7, 7.5,
343 7, 7.75, 8.5, 9});
344
345 // clang-format on
346 test::ExpectClose(expected, *GetOutput(0));
347 }
348
TEST_P(ResizeBilinearOpTest,TestBilinear4x4To3x3)349 TEST_P(ResizeBilinearOpTest, TestBilinear4x4To3x3) {
350 // Input:
351 // 1, 2, 3, 4
352 // 5, 6, 7, 8
353 // 9, 10, 11, 12
354 // 13, 14, 15, 16
355 AddInputFromArray<float>(
356 TensorShape({1, 4, 4, 1}),
357 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
358 AddInputFromArray<int32>(TensorShape({2}), {3, 3});
359 TF_ASSERT_OK(RunOpKernel());
360
361 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 3, 3, 1}));
362
363 // clang-format off
364 test::FillValues<float>(&expected,
365 {1, 7.0f/3, 11.0f/3,
366 19.0f/3, 23.0f/3, 27.0f/3,
367 35.0f/3, 39.0f/3, 43.0f/3});
368
369 // clang-format on
370 test::ExpectClose(expected, *GetOutput(0));
371 }
372
TEST_P(ResizeBilinearHalfPixelCentersOpTest,TestDownsamples)373 TEST_P(ResizeBilinearHalfPixelCentersOpTest, TestDownsamples) {
374 TestResize(4, 298, 297, 3, 61, 71);
375 }
376
TEST_P(ResizeBilinearHalfPixelCentersOpTest,TestUpsamples)377 TEST_P(ResizeBilinearHalfPixelCentersOpTest, TestUpsamples) {
378 TestResize(4, 61, 71, 3, 298, 297);
379 }
380
TEST_P(ResizeBilinearOpAlignCornersTest,TestBilinearAlignCorners4x4To3x3)381 TEST_P(ResizeBilinearOpAlignCornersTest, TestBilinearAlignCorners4x4To3x3) {
382 // Input:
383 // 1, 2, 3, 4
384 // 5, 6, 7, 8
385 // 9, 10, 11, 12
386 // 13, 14, 15, 16
387 AddInputFromArray<float>(
388 TensorShape({1, 4, 4, 1}),
389 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
390 AddInputFromArray<int32>(TensorShape({2}), {3, 3});
391 TF_ASSERT_OK(RunOpKernel());
392
393 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 3, 3, 1}));
394
395 // clang-format off
396 test::FillValues<float>(&expected,
397 { 1, 2.5, 4,
398 7, 8.5, 10,
399 13, 14.5, 16});
400
401 // clang-format on
402 test::ExpectClose(expected, *GetOutput(0));
403 }
404
TEST_P(ResizeBilinearOpTest,TestBilinear2x2To3x3Batch2)405 TEST_P(ResizeBilinearOpTest, TestBilinear2x2To3x3Batch2) {
406 // Input:
407 // 1, 2
408 // 3, 4
409 //
410 // repeated twice
411 AddInputFromArray<float>(TensorShape({2, 2, 2, 1}), {1, 2, 3, 4, 1, 2, 3, 4});
412 AddInputFromArray<int32>(TensorShape({2}), {3, 3});
413 TF_ASSERT_OK(RunOpKernel());
414
415 Tensor expected(allocator(), DT_FLOAT, TensorShape({2, 3, 3, 1}));
416 // clang-format off
417 test::FillValues<float>(&expected,
418 {1, 5.0f/3, 2, 7.0f/3, 3, 10.0f/3, 3, 11.0f/3, 4,
419 1, 5.0f/3, 2, 7.0f/3, 3, 10.0f/3, 3, 11.0f/3, 4
420 });
421 // clang-format on
422 test::ExpectClose(expected, *GetOutput(0));
423 }
424
TEST_P(ResizeBilinearOpTest,TestBilinear2x2x2To3x3x2)425 TEST_P(ResizeBilinearOpTest, TestBilinear2x2x2To3x3x2) {
426 AddInputFromArray<float>(TensorShape({1, 2, 2, 2}),
427 {1, -1, 2, -2, 3, -3, 4, -4});
428 AddInputFromArray<int32>(TensorShape({2}), {3, 3});
429 TF_ASSERT_OK(RunOpKernel());
430
431 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 3, 3, 2}));
432 // clang-format off
433 test::FillValues<float>(&expected,
434 {
435 1, -1,
436 5.0f/3, -5.0f/3,
437 2, -2,
438 7.0f/3, -7.0f/3,
439 3, -3,
440 10.0f/3, -10.0f/3,
441 3, -3,
442 11.0f/3, -11.0f/3,
443 4, -4
444 });
445 // clang-format on
446 test::ExpectClose(expected, *GetOutput(0));
447 }
448
TEST_P(ResizeBilinearOpTest,TestBilinear2x2To4x4)449 TEST_P(ResizeBilinearOpTest, TestBilinear2x2To4x4) {
450 // Input:
451 // 1, 2
452 // 3, 4
453 AddInputFromArray<float>(TensorShape({1, 2, 2, 1}), {1, 2, 3, 4});
454 AddInputFromArray<int32>(TensorShape({2}), {4, 4});
455 TF_ASSERT_OK(RunOpKernel());
456
457 Tensor expected(allocator(), DT_FLOAT, TensorShape({1, 4, 4, 1}));
458 // clang-format off
459 test::FillValues<float>(&expected,
460 {1, 1.5, 2, 2,
461 2, 2.5, 3, 3,
462 3, 3.5, 4, 4,
463 3, 3.5, 4, 4});
464 // clang-format on
465 test::ExpectClose(expected, *GetOutput(0));
466 }
467
468 // similar_size case
TEST_P(ResizeBilinearOpTest,Test1_1c)469 TEST_P(ResizeBilinearOpTest, Test1_1c) { TestResize(1, 183, 299, 1, 299, 299); }
TEST_P(ResizeBilinearOpTest,Test1_3c)470 TEST_P(ResizeBilinearOpTest, Test1_3c) { TestResize(1, 183, 299, 3, 299, 299); }
471
472 // Significantly smaller: scale_up case
TEST_P(ResizeBilinearOpTest,Test2_1c)473 TEST_P(ResizeBilinearOpTest, Test2_1c) { TestResize(1, 141, 186, 1, 299, 299); }
TEST_P(ResizeBilinearOpTest,Test2_3c)474 TEST_P(ResizeBilinearOpTest, Test2_3c) { TestResize(1, 141, 186, 3, 299, 299); }
475
476 // Significantly larger: scale_down case
TEST_P(ResizeBilinearOpTest,Test3_1c)477 TEST_P(ResizeBilinearOpTest, Test3_1c) { TestResize(1, 749, 603, 1, 299, 299); }
TEST_P(ResizeBilinearOpTest,Test3_3c)478 TEST_P(ResizeBilinearOpTest, Test3_3c) { TestResize(1, 749, 603, 3, 299, 299); }
479
480 // Exactly the same size
TEST_P(ResizeBilinearOpTest,Test4_1c)481 TEST_P(ResizeBilinearOpTest, Test4_1c) { TestResize(1, 299, 299, 1, 299, 299); }
TEST_P(ResizeBilinearOpTest,Test4_3c)482 TEST_P(ResizeBilinearOpTest, Test4_3c) { TestResize(1, 299, 299, 3, 299, 299); }
483
484 // Slightly smaller: similar_size case
TEST_P(ResizeBilinearOpTest,Test5_1c)485 TEST_P(ResizeBilinearOpTest, Test5_1c) { TestResize(1, 298, 297, 1, 299, 299); }
TEST_P(ResizeBilinearOpTest,Test5_3c)486 TEST_P(ResizeBilinearOpTest, Test5_3c) { TestResize(1, 298, 297, 3, 299, 299); }
487
488 // Slightly bigger: similar_size case
TEST_P(ResizeBilinearOpTest,Test6_1c)489 TEST_P(ResizeBilinearOpTest, Test6_1c) { TestResize(1, 304, 303, 1, 299, 299); }
TEST_P(ResizeBilinearOpTest,Test6_3c)490 TEST_P(ResizeBilinearOpTest, Test6_3c) { TestResize(1, 304, 303, 3, 299, 299); }
491
TEST_P(ResizeBilinearOpTest,TestInvalidOutputSize)492 TEST_P(ResizeBilinearOpTest, TestInvalidOutputSize) {
493 AddInputFromArray<float>(TensorShape({1, 2, 2, 1}), {1, 2, 3, 4});
494 AddInputFromArray<int32>(TensorShape({2}), {0, 0});
495 Status s = RunOpKernel();
496 EXPECT_TRUE(absl::StrContains(
497 s.ToString(), "Invalid argument: output dimensions must be positive"))
498 << s;
499 }
500
TEST_P(ResizeBilinearOpTest,TestInvalidInputShape)501 TEST_P(ResizeBilinearOpTest, TestInvalidInputShape) {
502 AddInputFromArray<float>(TensorShape({2, 2, 1}), {1, 2, 3, 4});
503 AddInputFromArray<int32>(TensorShape({2}), {4, 4});
504 Status s = RunOpKernel();
505 EXPECT_TRUE(absl::StrContains(
506 s.ToString(), "Invalid argument: input must be 4-dimensional"))
507 << s;
508 }
509
TEST_P(ResizeBilinearOpTest,TestInvalidSizeDim)510 TEST_P(ResizeBilinearOpTest, TestInvalidSizeDim) {
511 AddInputFromArray<float>(TensorShape({1, 2, 2, 1}), {1, 2, 3, 4});
512 AddInputFromArray<int32>(TensorShape({2, 1}), {4, 4});
513 Status s = RunOpKernel();
514 EXPECT_TRUE(absl::StrContains(
515 s.ToString(), "Invalid argument: shape_t must be 1-dimensional"))
516 << s;
517 }
518
TEST_P(ResizeBilinearOpTest,TestInvalidSizeElements)519 TEST_P(ResizeBilinearOpTest, TestInvalidSizeElements) {
520 AddInputFromArray<float>(TensorShape({1, 2, 2, 1}), {1, 2, 3, 4});
521 AddInputFromArray<int32>(TensorShape({3}), {4, 4, 1});
522 Status s = RunOpKernel();
523 EXPECT_TRUE(absl::StrContains(
524 s.ToString(), "Invalid argument: shape_t must have two elements"))
525 << s;
526 }
527
528 INSTANTIATE_TEST_SUITE_P(ResizeBilinearOpTestCpu, ResizeBilinearOpTest,
529 ::testing::Values(TestDevice::CPU));
530 INSTANTIATE_TEST_SUITE_P(ResizeBilinearHalfPixelCentersOpTestCpu,
531 ResizeBilinearHalfPixelCentersOpTest,
532 ::testing::Values(TestDevice::CPU));
533 INSTANTIATE_TEST_SUITE_P(ResizeBilinearOpAlignCornersTestCpu,
534 ResizeBilinearOpAlignCornersTest,
535 ::testing::Values(TestDevice::CPU));
536 #if GOOGLE_CUDA || TENSORFLOW_USE_ROCM
537 // Instantiate tests for GPU.
538 INSTANTIATE_TEST_SUITE_P(ResizeBilinearOpTestGpu, ResizeBilinearOpTest,
539 ::testing::Values(TestDevice::GPU));
540 INSTANTIATE_TEST_SUITE_P(ResizeBilinearHalfPixelCentersOpTestGpu,
541 ResizeBilinearHalfPixelCentersOpTest,
542 ::testing::Values(TestDevice::GPU));
543 INSTANTIATE_TEST_SUITE_P(ResizeBilinearOpAlignCornersTestGpu,
544 ResizeBilinearOpAlignCornersTest,
545 ::testing::Values(TestDevice::GPU));
546 #endif // GOOGLE_CUDA || TENSORFLOW_USE_ROCM
547
548 class ResizeBM : public ResizeBilinearOpTest {
549 public:
TestBody()550 void TestBody() override {}
SetUpBenchmark(int input_width,int input_height,int num_channels,int output_width,int output_height)551 void SetUpBenchmark(int input_width, int input_height, int num_channels,
552 int output_width, int output_height) {
553 TF_EXPECT_OK(NodeDefBuilder("resize_bilinear_op", "ResizeBilinear")
554 .Input(FakeInput(DT_FLOAT))
555 .Input(FakeInput(DT_INT32))
556 .Attr("align_corners", align_corners_)
557 .Attr("half_pixel_centers", half_pixel_centers_)
558 .Finalize(node_def()));
559 TF_EXPECT_OK(InitOp());
560 const TensorShape shape(
561 {/*batch_size*/ 1, input_width, input_height, num_channels});
562 SetRandomImageInput(shape);
563 AddInputFromArray<int32>(TensorShape({2}), {output_width, output_height});
564 }
565
566 using ResizeBilinearOpTest::RunOpKernel;
567 };
568
569 #ifdef PLATFORM_GOOGLE
570
BM_Resize(benchmark::State & state)571 void BM_Resize(benchmark::State& state) {
572 ResizeBM bench;
573 bench.SetUpBenchmark(640, 480, 3, 1024, 768);
574 for (const auto _ : state) {
575 CHECK(bench.RunOpKernel().ok());
576 }
577 }
578 BENCHMARK(BM_Resize);
579
580 #endif
581
582 } // namespace tensorflow
583