test_nearest_interp_op.py 16.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#   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.

from __future__ import print_function

import unittest
import numpy as np
19
from op_test import OpTest
20
import paddle.fluid.core as core
21
import paddle.fluid as fluid
22 23


24 25 26 27
def nearest_neighbor_interp_np(X,
                               out_h,
                               out_w,
                               out_size=None,
28
                               actual_shape=None,
29 30
                               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
T
tink2123 已提交
43 44 45 46 47 48 49 50 51 52
    if (out_h > 1):
        if (align_corners):
            ratio_h = (in_h - 1.0) / (out_h - 1.0)
        else:
            ratio_h = 1.0 * in_h / out_h
    if (out_w > 1):
        if (align_corners):
            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
        input_np = np.random.random(self.input_shape).astype("float64")
83

84 85 86 87 88 89 90
        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 已提交
91
        if self.scale > 0:
92 93
            out_h = int(in_h * self.scale)
            out_w = int(in_w * self.scale)
D
dengkaipeng 已提交
94 95 96 97
        else:
            out_h = self.out_h
            out_w = self.out_w

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

    def test_check_output(self):
        self.check_output()

    def test_check_grad(self):
        self.check_grad(['X'], 'Out', in_place=True)

    def init_test_case(self):
123
        self.interp_method = 'nearest'
124
        self.input_shape = [2, 3, 4, 5]
125 126
        self.out_h = 2
        self.out_w = 2
D
dengkaipeng 已提交
127
        self.scale = 0.
128
        self.out_size = np.array([3, 3]).astype("int32")
129
        self.align_corners = True
130 131


132
class TestNearestNeighborInterpCase1(TestNearestInterpOp):
133
    def init_test_case(self):
134
        self.interp_method = 'nearest'
135 136 137
        self.input_shape = [4, 1, 7, 8]
        self.out_h = 1
        self.out_w = 1
D
dengkaipeng 已提交
138
        self.scale = 0.
T
tink2123 已提交
139
        self.align_corners = True
140 141


142
class TestNearestNeighborInterpCase2(TestNearestInterpOp):
143
    def init_test_case(self):
144
        self.interp_method = 'nearest'
145 146 147
        self.input_shape = [3, 3, 9, 6]
        self.out_h = 12
        self.out_w = 12
D
dengkaipeng 已提交
148
        self.scale = 0.
149
        self.align_corners = True
150 151


152
class TestNearestNeighborInterpCase3(TestNearestInterpOp):
153
    def init_test_case(self):
154
        self.interp_method = 'nearest'
155
        self.input_shape = [1, 1, 32, 64]
156
        self.out_h = 64
157
        self.out_w = 32
D
dengkaipeng 已提交
158
        self.scale = 0.
159
        self.align_corners = True
160 161


162
class TestNearestNeighborInterpCase4(TestNearestInterpOp):
163
    def init_test_case(self):
164
        self.interp_method = 'nearest'
165 166 167
        self.input_shape = [4, 1, 7, 8]
        self.out_h = 1
        self.out_w = 1
D
dengkaipeng 已提交
168
        self.scale = 0.
169
        self.out_size = np.array([2, 2]).astype("int32")
170
        self.align_corners = True
171 172


173
class TestNearestNeighborInterpCase5(TestNearestInterpOp):
174
    def init_test_case(self):
175
        self.interp_method = 'nearest'
176 177 178
        self.input_shape = [3, 3, 9, 6]
        self.out_h = 12
        self.out_w = 12
D
dengkaipeng 已提交
179
        self.scale = 0.
180
        self.out_size = np.array([11, 11]).astype("int32")
181
        self.align_corners = True
182 183


184
class TestNearestNeighborInterpCase6(TestNearestInterpOp):
185
    def init_test_case(self):
186
        self.interp_method = 'nearest'
187
        self.input_shape = [1, 1, 32, 64]
188
        self.out_h = 64
189
        self.out_w = 32
D
dengkaipeng 已提交
190
        self.scale = 0.
191
        self.out_size = np.array([65, 129]).astype("int32")
192
        self.align_corners = True
193 194


K
Kaipeng Deng 已提交
195 196 197
class TestNearestNeighborInterpSame(TestNearestInterpOp):
    def init_test_case(self):
        self.interp_method = 'nearest'
198 199
        self.input_shape = [2, 3, 32, 64]
        self.out_h = 32
K
Kaipeng Deng 已提交
200 201 202 203 204
        self.out_w = 64
        self.scale = 0.
        self.align_corners = True


205
class TestNearestNeighborInterpActualShape(TestNearestInterpOp):
206
    def init_test_case(self):
207
        self.interp_method = 'nearest'
208 209 210
        self.input_shape = [3, 2, 32, 16]
        self.out_h = 64
        self.out_w = 32
D
dengkaipeng 已提交
211
        self.scale = 0.
212
        self.out_size = np.array([66, 40]).astype("int32")
213
        self.align_corners = True
214 215


216 217 218 219 220 221 222 223 224 225 226 227
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
        self.scale = 0.
        self.out_size = np.array([3, 8]).astype("int32")
        self.align_corners = True
        self.data_layout = "NHWC"


228
class TestNearestInterpOpUint8(OpTest):
229 230
    def setUp(self):
        self.out_size = None
231
        self.actual_shape = None
232
        self.init_test_case()
233
        self.op_type = "nearest_interp"
234 235
        input_np = np.random.randint(
            low=0, high=256, size=self.input_shape).astype("uint8")
D
dengkaipeng 已提交
236 237 238 239 240 241 242 243 244

        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

        output_np = nearest_neighbor_interp_np(input_np, out_h, out_w,
245 246
                                               self.out_size, self.actual_shape,
                                               self.align_corners)
247 248 249 250 251 252
        self.inputs = {'X': input_np}
        if self.out_size is not None:
            self.inputs['OutSize'] = self.out_size
        self.attrs = {
            'out_h': self.out_h,
            'out_w': self.out_w,
D
dengkaipeng 已提交
253
            'scale': self.scale,
254 255
            'interp_method': self.interp_method,
            'align_corners': self.align_corners
256 257 258 259 260 261 262
        }
        self.outputs = {'Out': output_np}

    def test_check_output(self):
        self.check_output_with_place(place=core.CPUPlace(), atol=1)

    def init_test_case(self):
263
        self.interp_method = 'nearest'
264 265 266
        self.input_shape = [1, 3, 9, 6]
        self.out_h = 10
        self.out_w = 9
D
dengkaipeng 已提交
267
        self.scale = 0.
268
        self.align_corners = True
269 270


271
class TestNearestNeighborInterpCase1Uint8(TestNearestInterpOpUint8):
272 273
    def init_test_case(self):
        self.interp_method = 'nearest'
274 275 276
        self.input_shape = [2, 3, 32, 64]
        self.out_h = 80
        self.out_w = 40
D
dengkaipeng 已提交
277
        self.scale = 0.
T
tink2123 已提交
278
        self.align_corners = True
279 280


281
class TestNearestNeighborInterpCase2Uint8(TestNearestInterpOpUint8):
282 283 284 285 286
    def init_test_case(self):
        self.interp_method = 'nearest'
        self.input_shape = [4, 1, 7, 8]
        self.out_h = 5
        self.out_w = 13
D
dengkaipeng 已提交
287
        self.scale = 0.
288
        self.out_size = np.array([6, 15]).astype("int32")
289 290 291 292 293 294
        self.align_corners = True


class TestNearestInterpWithoutCorners(TestNearestInterpOp):
    def set_align_corners(self):
        self.align_corners = False
295 296


D
dengkaipeng 已提交
297 298 299
class TestNearestNeighborInterpScale1(TestNearestInterpOp):
    def init_test_case(self):
        self.interp_method = 'nearest'
300
        self.input_shape = [3, 2, 7, 5]
D
dengkaipeng 已提交
301 302 303 304 305 306 307 308 309 310
        self.out_h = 64
        self.out_w = 32
        self.scale = 2.
        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'
311
        self.input_shape = [3, 2, 5, 7]
D
dengkaipeng 已提交
312 313 314 315 316 317 318 319 320 321
        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'
322
        self.input_shape = [3, 2, 7, 5]
D
dengkaipeng 已提交
323 324 325 326 327 328 329
        self.out_h = 64
        self.out_w = 32
        self.scale = 1.
        self.out_size = np.array([66, 40]).astype("int32")
        self.align_corners = True


330 331 332 333 334 335 336 337 338 339 340 341 342
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,
        }

343
        input_np = np.random.random(self.input_shape).astype("float64")
344 345 346
        self.inputs = {'X': input_np}

        if self.scale_by_1Dtensor:
347
            self.inputs['Scale'] = np.array([self.scale]).astype("float64")
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
        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
        elif self.out_size is not None:
            size_tensor = []
            for index, ele in enumerate(self.out_size):
                size_tensor.append(("x" + str(index), np.ones(
                    (1)).astype('int32') * ele))
            self.inputs['SizeTensor'] = size_tensor

        self.attrs['out_h'] = self.out_h
        self.attrs['out_w'] = self.out_w
        output_np = nearest_neighbor_interp_np(input_np, out_h, out_w,
                                               self.out_size, self.actual_shape,
                                               self.align_corners)
        self.outputs = {'Out': output_np}

    def test_check_output(self):
        self.check_output()

    def test_check_grad(self):
        self.check_grad(['X'], 'Out', in_place=True)

    def init_test_case(self):
        self.interp_method = 'nearest'
        self.input_shape = [2, 3, 4, 4]
        self.out_h = 3
        self.out_w = 3
        self.scale = 0.
        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
        self.scale = 0.
        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
        self.scale = 0.
        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


426
class TestNearestAPI(unittest.TestCase):
427
    def test_case(self):
428 429
        x = fluid.data(name="x", shape=[2, 3, 6, 6], dtype="float32")
        y = fluid.data(name="y", shape=[2, 6, 6, 3], dtype="float32")
430 431 432 433 434 435

        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")
        scale_tensor = fluid.data(
            name="scale_tensor", shape=[1], dtype="float32")
436

437 438
        out1 = fluid.layers.resize_nearest(
            y, out_shape=[12, 12], data_format='NHWC')
439 440 441 442 443 444
        out2 = fluid.layers.resize_nearest(x, out_shape=[12, dim])
        out3 = fluid.layers.resize_nearest(x, out_shape=shape_tensor)
        out4 = fluid.layers.resize_nearest(
            x, out_shape=[4, 4], actual_shape=actual_size)
        out5 = fluid.layers.resize_nearest(x, scale=scale_tensor)

445
        x_data = np.random.random((2, 3, 6, 6)).astype("float32")
446 447 448 449 450
        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")

451 452 453 454
        if core.is_compiled_with_cuda():
            place = core.CUDAPlace(0)
        else:
            place = core.CPUPlace()
455
        exe = fluid.Executor(place)
456
        exe.run(fluid.default_startup_program())
457 458 459
        results = exe.run(fluid.default_main_program(),
                          feed={
                              "x": x_data,
460
                              "y": np.transpose(x_data, (0, 2, 3, 1)),
461 462 463 464 465 466 467 468 469 470
                              "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)
471 472 473 474 475
        self.assertTrue(
            np.allclose(results[0], np.transpose(expect_res, (0, 2, 3, 1))))
        for i in range(len(results) - 1):
            self.assertTrue(np.allclose(results[i + 1], expect_res))

476

477
class TestNearestInterpException(unittest.TestCase):
478
    def test_exception(self):
479 480 481 482
        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
483 484
            out = fluid.layers.resize_nearest(
                input, out_shape=[4, 8], data_format='NDHWC')
485 486 487 488 489 490 491 492 493 494

        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)
495 496


497 498
if __name__ == "__main__":
    unittest.main()