test_nearest_interp_op.py 16.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest
import numpy as np
17
from op_test import OpTest
18
import paddle.fluid.core as core
19
import paddle.fluid as fluid
20 21


22 23 24 25 26 27 28 29 30
def nearest_neighbor_interp_np(
    X,
    out_h,
    out_w,
    out_size=None,
    actual_shape=None,
    align_corners=True,
    data_layout='NCHW',
):
31
    """nearest neighbor interpolation implement in shape [N, C, H, W]"""
32 33
    if data_layout == "NHWC":
        X = np.transpose(X, (0, 3, 1, 2))  # NHWC => NCHW
34 35 36
    if out_size is not None:
        out_h = out_size[0]
        out_w = out_size[1]
37 38 39
    if actual_shape is not None:
        out_h = actual_shape[0]
        out_w = actual_shape[1]
40 41 42
    n, c, in_h, in_w = X.shape

    ratio_h = ratio_w = 0.0
43 44
    if out_h > 1:
        if align_corners:
T
tink2123 已提交
45 46 47
            ratio_h = (in_h - 1.0) / (out_h - 1.0)
        else:
            ratio_h = 1.0 * in_h / out_h
48 49
    if out_w > 1:
        if align_corners:
T
tink2123 已提交
50 51 52
            ratio_w = (in_w - 1.0) / (out_w - 1.0)
        else:
            ratio_w = 1.0 * in_w / out_w
53 54

    out = np.zeros((n, c, out_h, out_w))
55 56 57 58 59 60 61 62 63 64 65 66 67

    if align_corners:
        for i in range(out_h):
            in_i = int(ratio_h * i + 0.5)
            for j in range(out_w):
                in_j = int(ratio_w * j + 0.5)
                out[:, :, i, j] = X[:, :, in_i, in_j]
    else:
        for i in range(out_h):
            in_i = int(ratio_h * i)
            for j in range(out_w):
                in_j = int(ratio_w * j)
                out[:, :, i, j] = X[:, :, in_i, in_j]
68

69 70 71
    if data_layout == "NHWC":
        out = np.transpose(out, (0, 2, 3, 1))  # NCHW => NHWC

72 73 74
    return out.astype(X.dtype)


75
class TestNearestInterpOp(OpTest):
76 77
    def setUp(self):
        self.out_size = None
78
        self.actual_shape = None
79
        self.data_layout = 'NCHW'
80
        self.init_test_case()
81
        self.op_type = "nearest_interp"
82
        self.check_eager = True
83
        input_np = np.random.random(self.input_shape).astype("float64")
84

85 86 87 88 89 90 91
        if self.data_layout == "NCHW":
            in_h = self.input_shape[2]
            in_w = self.input_shape[3]
        else:
            in_h = self.input_shape[1]
            in_w = self.input_shape[2]

D
dengkaipeng 已提交
92
        if self.scale > 0:
93 94
            out_h = int(in_h * self.scale)
            out_w = int(in_w * self.scale)
D
dengkaipeng 已提交
95 96 97 98
        else:
            out_h = self.out_h
            out_w = self.out_w

99 100 101 102 103 104 105 106 107
        output_np = nearest_neighbor_interp_np(
            input_np,
            out_h,
            out_w,
            self.out_size,
            self.actual_shape,
            self.align_corners,
            self.data_layout,
        )
108 109 110
        self.inputs = {'X': input_np}
        if self.out_size is not None:
            self.inputs['OutSize'] = self.out_size
111
            self.check_eager = False
112 113
        if self.actual_shape is not None:
            self.inputs['OutSize'] = self.actual_shape
114
            self.check_eager = False
115 116 117
        self.attrs = {
            'out_h': self.out_h,
            'out_w': self.out_w,
D
dengkaipeng 已提交
118
            'scale': self.scale,
119 120
            'interp_method': self.interp_method,
            'align_corners': self.align_corners,
121
            'data_layout': self.data_layout,
122 123 124 125
        }
        self.outputs = {'Out': output_np}

    def test_check_output(self):
126
        self.check_output(check_eager=self.check_eager)
127 128

    def test_check_grad(self):
129 130 131
        self.check_grad(
            ['X'], 'Out', in_place=True, check_eager=self.check_eager
        )
132 133

    def init_test_case(self):
134
        self.interp_method = 'nearest'
135
        self.input_shape = [2, 3, 4, 5]
136 137
        self.out_h = 2
        self.out_w = 2
138
        self.scale = 0.0
139
        self.out_size = np.array([3, 3]).astype("int32")
140
        self.align_corners = True
141 142


143
class TestNearestNeighborInterpCase1(TestNearestInterpOp):
144
    def init_test_case(self):
145
        self.interp_method = 'nearest'
146 147 148
        self.input_shape = [4, 1, 7, 8]
        self.out_h = 1
        self.out_w = 1
149
        self.scale = 0.0
T
tink2123 已提交
150
        self.align_corners = True
151 152


153
class TestNearestNeighborInterpCase2(TestNearestInterpOp):
154
    def init_test_case(self):
155
        self.interp_method = 'nearest'
156 157 158
        self.input_shape = [3, 3, 9, 6]
        self.out_h = 12
        self.out_w = 12
159
        self.scale = 0.0
160
        self.align_corners = True
161 162


163
class TestNearestNeighborInterpCase3(TestNearestInterpOp):
164
    def init_test_case(self):
165
        self.interp_method = 'nearest'
166
        self.input_shape = [1, 1, 32, 64]
167
        self.out_h = 64
168
        self.out_w = 32
169
        self.scale = 0.0
170
        self.align_corners = True
171 172


173
class TestNearestNeighborInterpCase4(TestNearestInterpOp):
174
    def init_test_case(self):
175
        self.interp_method = 'nearest'
176 177 178
        self.input_shape = [4, 1, 7, 8]
        self.out_h = 1
        self.out_w = 1
179
        self.scale = 0.0
180
        self.out_size = np.array([2, 2]).astype("int32")
181
        self.align_corners = True
182 183


184
class TestNearestNeighborInterpCase5(TestNearestInterpOp):
185
    def init_test_case(self):
186
        self.interp_method = 'nearest'
187 188 189
        self.input_shape = [3, 3, 9, 6]
        self.out_h = 12
        self.out_w = 12
190
        self.scale = 0.0
191
        self.out_size = np.array([11, 11]).astype("int32")
192
        self.align_corners = True
193 194


195
class TestNearestNeighborInterpCase6(TestNearestInterpOp):
196
    def init_test_case(self):
197
        self.interp_method = 'nearest'
198
        self.input_shape = [1, 1, 32, 64]
199
        self.out_h = 64
200
        self.out_w = 32
201
        self.scale = 0.0
202
        self.out_size = np.array([65, 129]).astype("int32")
203
        self.align_corners = True
204 205


K
Kaipeng Deng 已提交
206 207 208
class TestNearestNeighborInterpSame(TestNearestInterpOp):
    def init_test_case(self):
        self.interp_method = 'nearest'
209 210
        self.input_shape = [2, 3, 32, 64]
        self.out_h = 32
K
Kaipeng Deng 已提交
211
        self.out_w = 64
212
        self.scale = 0.0
K
Kaipeng Deng 已提交
213 214 215
        self.align_corners = True


216
class TestNearestNeighborInterpActualShape(TestNearestInterpOp):
217
    def init_test_case(self):
218
        self.interp_method = 'nearest'
219 220 221
        self.input_shape = [3, 2, 32, 16]
        self.out_h = 64
        self.out_w = 32
222
        self.scale = 0.0
223
        self.out_size = np.array([66, 40]).astype("int32")
224
        self.align_corners = True
225 226


227 228 229 230 231 232
class TestNearestNeighborInterpDataLayout(TestNearestInterpOp):
    def init_test_case(self):
        self.interp_method = 'nearest'
        self.input_shape = [2, 4, 4, 5]
        self.out_h = 2
        self.out_w = 2
233
        self.scale = 0.0
234 235 236 237 238
        self.out_size = np.array([3, 8]).astype("int32")
        self.align_corners = True
        self.data_layout = "NHWC"


239
class TestNearestInterpOpUint8(OpTest):
240 241
    def setUp(self):
        self.out_size = None
242
        self.actual_shape = None
243
        self.init_test_case()
244
        self.op_type = "nearest_interp"
245
        self.check_eager = True
246 247 248
        input_np = np.random.randint(
            low=0, high=256, size=self.input_shape
        ).astype("uint8")
D
dengkaipeng 已提交
249 250 251 252 253 254 255 256

        if self.scale > 0:
            out_h = int(self.input_shape[2] * self.scale)
            out_w = int(self.input_shape[3] * self.scale)
        else:
            out_h = self.out_h
            out_w = self.out_w

257 258 259 260 261 262 263 264
        output_np = nearest_neighbor_interp_np(
            input_np,
            out_h,
            out_w,
            self.out_size,
            self.actual_shape,
            self.align_corners,
        )
265 266 267
        self.inputs = {'X': input_np}
        if self.out_size is not None:
            self.inputs['OutSize'] = self.out_size
268
            self.check_eager = False
269 270 271
        self.attrs = {
            'out_h': self.out_h,
            'out_w': self.out_w,
D
dengkaipeng 已提交
272
            'scale': self.scale,
273
            'interp_method': self.interp_method,
274
            'align_corners': self.align_corners,
275 276 277 278
        }
        self.outputs = {'Out': output_np}

    def test_check_output(self):
279 280 281
        self.check_output_with_place(
            place=core.CPUPlace(), atol=1, check_eager=self.check_eager
        )
282 283

    def init_test_case(self):
284
        self.interp_method = 'nearest'
285 286 287
        self.input_shape = [1, 3, 9, 6]
        self.out_h = 10
        self.out_w = 9
288
        self.scale = 0.0
289
        self.align_corners = True
290 291


292
class TestNearestNeighborInterpCase1Uint8(TestNearestInterpOpUint8):
293 294
    def init_test_case(self):
        self.interp_method = 'nearest'
295 296 297
        self.input_shape = [2, 3, 32, 64]
        self.out_h = 80
        self.out_w = 40
298
        self.scale = 0.0
T
tink2123 已提交
299
        self.align_corners = True
300 301


302
class TestNearestNeighborInterpCase2Uint8(TestNearestInterpOpUint8):
303 304 305 306 307
    def init_test_case(self):
        self.interp_method = 'nearest'
        self.input_shape = [4, 1, 7, 8]
        self.out_h = 5
        self.out_w = 13
308
        self.scale = 0.0
309
        self.out_size = np.array([6, 15]).astype("int32")
310 311 312 313 314 315
        self.align_corners = True


class TestNearestInterpWithoutCorners(TestNearestInterpOp):
    def set_align_corners(self):
        self.align_corners = False
316 317


D
dengkaipeng 已提交
318 319 320
class TestNearestNeighborInterpScale1(TestNearestInterpOp):
    def init_test_case(self):
        self.interp_method = 'nearest'
321
        self.input_shape = [3, 2, 7, 5]
D
dengkaipeng 已提交
322 323
        self.out_h = 64
        self.out_w = 32
324
        self.scale = 2.0
D
dengkaipeng 已提交
325 326 327 328 329 330 331
        self.out_size = np.array([66, 40]).astype("int32")
        self.align_corners = True


class TestNearestNeighborInterpScale2(TestNearestInterpOp):
    def init_test_case(self):
        self.interp_method = 'nearest'
332
        self.input_shape = [3, 2, 5, 7]
D
dengkaipeng 已提交
333 334 335 336 337 338 339 340 341 342
        self.out_h = 64
        self.out_w = 32
        self.scale = 1.5
        self.out_size = np.array([66, 40]).astype("int32")
        self.align_corners = True


class TestNearestNeighborInterpScale3(TestNearestInterpOp):
    def init_test_case(self):
        self.interp_method = 'nearest'
343
        self.input_shape = [3, 2, 7, 5]
D
dengkaipeng 已提交
344 345
        self.out_h = 64
        self.out_w = 32
346
        self.scale = 1.0
D
dengkaipeng 已提交
347 348 349 350
        self.out_size = np.array([66, 40]).astype("int32")
        self.align_corners = True


351 352 353 354 355 356 357 358 359 360 361 362
class TestNearestInterpOp_attr_tensor(OpTest):
    def setUp(self):
        self.out_size = None
        self.actual_shape = None
        self.init_test_case()
        self.op_type = "nearest_interp"
        self.shape_by_1Dtensor = False
        self.scale_by_1Dtensor = False
        self.attrs = {
            'interp_method': self.interp_method,
            'align_corners': self.align_corners,
        }
363 364 365
        # NOTE(dev): some AsDispensible input is not used under imperative mode.
        # Skip check_eager while found them in Inputs.
        self.check_eager = True
366

367
        input_np = np.random.random(self.input_shape).astype("float64")
368 369 370
        self.inputs = {'X': input_np}

        if self.scale_by_1Dtensor:
371
            self.inputs['Scale'] = np.array([self.scale]).astype("float64")
372 373 374 375 376 377 378 379 380 381
        elif self.scale > 0:
            out_h = int(self.input_shape[2] * self.scale)
            out_w = int(self.input_shape[3] * self.scale)
            self.attrs['scale'] = self.scale
        else:
            out_h = self.out_h
            out_w = self.out_w

        if self.shape_by_1Dtensor:
            self.inputs['OutSize'] = self.out_size
382
            self.check_eager = False
383 384 385
        elif self.out_size is not None:
            size_tensor = []
            for index, ele in enumerate(self.out_size):
386 387 388
                size_tensor.append(
                    ("x" + str(index), np.ones((1)).astype('int32') * ele)
                )
389
            self.inputs['SizeTensor'] = size_tensor
390
            self.check_eager = False
391 392 393

        self.attrs['out_h'] = self.out_h
        self.attrs['out_w'] = self.out_w
394 395 396 397 398 399 400 401
        output_np = nearest_neighbor_interp_np(
            input_np,
            out_h,
            out_w,
            self.out_size,
            self.actual_shape,
            self.align_corners,
        )
402 403 404
        self.outputs = {'Out': output_np}

    def test_check_output(self):
405
        self.check_output(check_eager=self.check_eager)
406 407

    def test_check_grad(self):
408 409 410
        self.check_grad(
            ['X'], 'Out', in_place=True, check_eager=self.check_eager
        )
411 412 413

    def init_test_case(self):
        self.interp_method = 'nearest'
Z
zhupengyang 已提交
414
        self.input_shape = [2, 5, 4, 4]
415 416
        self.out_h = 3
        self.out_w = 3
417
        self.scale = 0.0
418 419 420 421 422 423 424 425 426 427 428
        self.out_size = [3, 3]
        self.align_corners = True


# out_size is a tensor list
class TestNearestInterp_attr_tensor_Case1(TestNearestInterpOp_attr_tensor):
    def init_test_case(self):
        self.interp_method = 'nearest'
        self.input_shape = [3, 3, 9, 6]
        self.out_h = 12
        self.out_w = 12
429
        self.scale = 0.0
430 431 432 433 434 435 436 437 438 439 440
        self.out_size = [8, 12]
        self.align_corners = True


# out_size is a 1-D tensor
class TestNearestInterp_attr_tensor_Case2(TestNearestInterpOp_attr_tensor):
    def init_test_case(self):
        self.interp_method = 'nearest'
        self.input_shape = [3, 2, 32, 16]
        self.out_h = 64
        self.out_w = 32
441
        self.scale = 0.0
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
        self.out_size = np.array([66, 40]).astype("int32")
        self.align_corners = True
        self.shape_by_1Dtensor = True


# scale is a 1-D tensor
class TestNearestInterp_attr_tensor_Case3(TestNearestInterpOp_attr_tensor):
    def init_test_case(self):
        self.interp_method = 'nearest'
        self.input_shape = [3, 2, 32, 16]
        self.out_h = 64
        self.out_w = 32
        self.scale = 2.0
        self.out_size = None
        self.align_corners = True
        self.scale_by_1Dtensor = True


460
class TestNearestAPI(unittest.TestCase):
461
    def test_case(self):
462 463
        x = fluid.data(name="x", shape=[2, 3, 6, 6], dtype="float32")
        y = fluid.data(name="y", shape=[2, 6, 6, 3], dtype="float32")
464 465 466 467

        dim = fluid.data(name="dim", shape=[1], dtype="int32")
        shape_tensor = fluid.data(name="shape_tensor", shape=[2], dtype="int32")
        actual_size = fluid.data(name="actual_size", shape=[2], dtype="int32")
468 469 470
        scale_tensor = fluid.data(
            name="scale_tensor", shape=[1], dtype="float32"
        )
471

472 473 474
        out1 = fluid.layers.resize_nearest(
            y, out_shape=[12, 12], data_format='NHWC'
        )
475 476
        out2 = fluid.layers.resize_nearest(x, out_shape=[12, dim])
        out3 = fluid.layers.resize_nearest(x, out_shape=shape_tensor)
477 478 479
        out4 = fluid.layers.resize_nearest(
            x, out_shape=[4, 4], actual_shape=actual_size
        )
480 481
        out5 = fluid.layers.resize_nearest(x, scale=scale_tensor)

482
        x_data = np.random.random((2, 3, 6, 6)).astype("float32")
483 484 485 486 487
        dim_data = np.array([12]).astype("int32")
        shape_data = np.array([12, 12]).astype("int32")
        actual_size_data = np.array([12, 12]).astype("int32")
        scale_data = np.array([2.0]).astype("float32")

488 489 490 491
        if core.is_compiled_with_cuda():
            place = core.CUDAPlace(0)
        else:
            place = core.CPUPlace()
492
        exe = fluid.Executor(place)
493
        exe.run(fluid.default_startup_program())
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
        results = exe.run(
            fluid.default_main_program(),
            feed={
                "x": x_data,
                "y": np.transpose(x_data, (0, 2, 3, 1)),
                "dim": dim_data,
                "shape_tensor": shape_data,
                "actual_size": actual_size_data,
                "scale_tensor": scale_data,
            },
            fetch_list=[out1, out2, out3, out4, out5],
            return_numpy=True,
        )

        expect_res = nearest_neighbor_interp_np(
            x_data, out_h=12, out_w=12, align_corners=True
        )
        np.testing.assert_allclose(
            results[0], np.transpose(expect_res, (0, 2, 3, 1)), rtol=1e-05
        )
514
        for i in range(len(results) - 1):
515
            np.testing.assert_allclose(results[i + 1], expect_res, rtol=1e-05)
516

517

518
class TestNearestInterpException(unittest.TestCase):
519
    def test_exception(self):
520 521 522 523
        input = fluid.data(name="input", shape=[1, 3, 6, 6], dtype="float32")

        def attr_data_format():
            # for 4-D input, data_format can only be NCHW or NHWC
524 525 526
            out = fluid.layers.resize_nearest(
                input, out_shape=[4, 8], data_format='NDHWC'
            )
527 528 529 530 531 532 533 534 535 536

        def attr_scale_type():
            out = fluid.layers.resize_nearest(input, scale='scale')

        def attr_scale_value():
            out = fluid.layers.resize_nearest(input, scale=-0.3)

        self.assertRaises(ValueError, attr_data_format)
        self.assertRaises(TypeError, attr_scale_type)
        self.assertRaises(ValueError, attr_scale_value)
537 538


539
if __name__ == "__main__":
540
    import paddle
541

542
    paddle.enable_static()
543
    unittest.main()