1# Copyright 2018 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"""Tests for resampler ops.""" 16 17from __future__ import absolute_import 18from __future__ import division 19from __future__ import print_function 20 21import numpy as np 22 23from tensorflow.compiler.tests import xla_test 24from tensorflow.contrib import resampler 25from tensorflow.contrib.resampler.ops import gen_resampler_ops 26from tensorflow.python.ops import array_ops 27from tensorflow.python.platform import test 28 29 30class ResamplerOpsTest(xla_test.XLATestCase): 31 32 def _assertForwardOpMatchesExpected(self, image_np, warp_np, expected): 33 with self.test_session() as sess, self.test_scope(): 34 input_image = array_ops.placeholder(image_np.dtype) 35 warp = array_ops.placeholder(warp_np.dtype) 36 resampled = resampler.resampler(input_image, warp, name='resampler') 37 out = sess.run(resampled, {input_image: image_np, warp: warp_np}) 38 39 self.assertAllCloseAccordingToType( 40 expected, out, rtol=5e-3, half_rtol=1e-2, bfloat16_rtol=3e-2) 41 42 def _assertBackwardOpMatchesExpected(self, input_np, warp_np, grad_output_np, 43 expected_grad_data, expected_grad_warp): 44 with self.cached_session() as sess, self.test_scope(): 45 input_image = array_ops.placeholder(input_np.dtype) 46 warp = array_ops.placeholder(warp_np.dtype) 47 grad_output = array_ops.placeholder(grad_output_np.dtype) 48 49 grad_data, grad_warp = gen_resampler_ops.resampler_grad( 50 input_image, warp, grad_output) 51 52 grad_data_tf, grad_warp_tf = sess.run([grad_data, grad_warp], { 53 input_image: input_np, 54 warp: warp_np, 55 grad_output: grad_output_np 56 }) 57 58 self.assertAllCloseAccordingToType( 59 expected_grad_warp, grad_warp_tf, half_rtol=1e-2, bfloat16_rtol=3e-2) 60 self.assertAllCloseAccordingToType( 61 expected_grad_data, grad_data_tf, half_rtol=1e-2, bfloat16_rtol=3e-2) 62 63 def testSimple(self): 64 for dtype in self.float_types: 65 input_shape = [1, 2, 2, 1] 66 input_data = [0, 5, 13, 54] 67 input_np = np.array(input_data, dtype=dtype).reshape(input_shape) 68 69 warp_shape = [1, 2] 70 warp_data = [0.7, 0.6] 71 warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) 72 expected = [[26.42]] 73 self._assertForwardOpMatchesExpected(input_np, warp_np, expected) 74 75 grad_output = np.ones([1, 1], dtype=dtype) 76 77 expected_grad_data = [[[[0.12], [0.27999997]], [[0.18000001], 78 [0.42000002]]]] 79 80 expected_grad_warp = [[26.60000038, 38.20000076]] 81 82 self._assertBackwardOpMatchesExpected(input_np, warp_np, grad_output, 83 expected_grad_data, 84 expected_grad_warp) 85 86 def testMultiChannel(self): 87 for dtype in self.float_types: 88 input_shape = [1, 2, 2, 3] 89 input_rgb_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 90 input_np = np.array(input_rgb_data, dtype=dtype).reshape(input_shape) 91 92 warp_shape = [1, 2] 93 warp_data = [0.7, 0.6] 94 warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) 95 expected = [[59.58000183, 146.94000244, 107.37999725]] 96 self._assertForwardOpMatchesExpected(input_np, warp_np, expected) 97 98 grad_output = np.ones([1, 3], dtype=dtype) 99 100 expected_grad_data = [[[[0.12, 0.12, 0.12], 101 [0.27999997, 0.27999997, 0.27999997]], 102 [[0.18000001, 0.18000001, 0.18000001], 103 [0.42000002, 0.42000002, 0.42000002]]]] 104 105 expected_grad_warp = [[199, 30]] 106 107 self._assertBackwardOpMatchesExpected(input_np, warp_np, grad_output, 108 expected_grad_data, 109 expected_grad_warp) 110 111 def testBatch2Height3byWidth3RGB(self): 112 for dtype in self.float_types: 113 input_shape = [2, 3, 3, 3] 114 input_rgb_data = [ 115 0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1, 30, 105, 2, 40, 115, 116 3, 50, 125, 4, 60, 135, 5, 70, 145, 6, 0, 5, 13, 54, 135, 226, 37, 8, 117 234, 90, 255, 1, 30, 105, 2, 40, 115, 3, 50, 125, 4, 60, 135, 5, 70, 118 145, 6 119 ] 120 input_np = np.array(input_rgb_data, dtype=dtype).reshape(input_shape) 121 122 # 2 batches and 2 samples for each batch. 123 warp_shape = [2, 2, 2] 124 warp_data = [0.7, 0.6, 1, 0.7, 0.9, 1.2, 1.3, 1.6] 125 warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) 126 127 expected_forward = [[[43.92, 128.4, 65.86], [37.2, 114., 69.2]], 128 [[40.6, 122.8, 2.5], [51., 126, 4.1]]] 129 130 self._assertForwardOpMatchesExpected(input_np, warp_np, expected_forward) 131 132 expected_grad_data = [[[[0.12, 0.12, 0.12], 133 [0.57999998, 0.57999998, 0.57999998], 134 [0., 0., 0.]], 135 [[0.18000001, 0.18000001, 0.18000001], 136 [1.12, 1.12, 1.12], [0., 0., 0.]], 137 [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]], 138 [[[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]], 139 [[0.08000001, 0.08000001, 0.08000001], 140 [0.99999988, 0.99999988, 0.99999988], 141 [0.11999997, 0.11999997, 0.11999997]], 142 [[0.02000001, 0.02000001, 0.02000001], 143 [0.60000008, 0.60000008, 0.60000008], 144 [0.17999998, 0.17999998, 0.17999998]]]] 145 expected_grad_warp = [[[33.39999008, -96.20000458], [-26.10000229, 146 -278.]], 147 [[-162.99998474, 39.99999619], [21., 63.]]] 148 149 grad_output = np.ones([2, 2, 3], dtype=dtype) 150 self._assertBackwardOpMatchesExpected(input_np, warp_np, grad_output, 151 expected_grad_data, 152 expected_grad_warp) 153 154 def testOutOfBoundWarps(self): 155 # (x, y) are both less than 0. 156 for dtype in self.float_types: 157 input_shape = [1, 2, 2, 1] 158 input_data = [10, 5, 13, 54] 159 input_np = np.array(input_data, dtype=dtype).reshape(input_shape) 160 161 warp_shape = [1, 2, 2] 162 warp_data = [-1, -1, 0.7, 0.6] 163 warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) 164 expected = [[[0.0], [27.62]]] 165 self._assertForwardOpMatchesExpected(input_np, warp_np, expected) 166 167 expected_grad_data = [[[[0.12], [0.27999997]], [[0.18000001], 168 [0.42000002]]]] 169 expected_grad_warp = [[[0., 0.], [22.60000038, 35.20000076]]] 170 171 grad_output = np.ones([1, 2, 1], dtype=dtype) 172 self._assertBackwardOpMatchesExpected(input_np, warp_np, grad_output, 173 expected_grad_data, 174 expected_grad_warp) 175 176 # One of (x, y) is less than 0. 177 for dtype in self.float_types: 178 input_shape = [1, 2, 2, 1] 179 input_data = [10, 5, 13, 54] 180 input_np = np.array(input_data, dtype=dtype).reshape(input_shape) 181 182 warp_shape = [1, 2, 2] 183 # -1 is out of bound for grad_warp. 184 warp_data = [-1, 0.1, 0.7, 0.6] 185 warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) 186 expected = [[[0.0], [27.62]]] 187 self._assertForwardOpMatchesExpected(input_np, warp_np, expected) 188 189 expected_grad_data = [[[[0.12], [0.27999997]], [[0.18000001], 190 [0.42000002]]]] 191 expected_grad_warp = [[[0., 0.], [22.60000038, 35.20000076]]] 192 193 grad_output = np.ones([1, 2, 1], dtype=dtype) 194 self._assertBackwardOpMatchesExpected(input_np, warp_np, grad_output, 195 expected_grad_data, 196 expected_grad_warp) 197 198 # Both of (x, y) are greater than image size. 199 for dtype in self.float_types: 200 input_shape = [1, 2, 2, 1] 201 input_data = [10, 5, 13, 54] 202 input_np = np.array(input_data, dtype=dtype).reshape(input_shape) 203 204 warp_shape = [1, 2, 2] 205 # -0.1 is *inbound* for grad_warp and grad_data, 2.1 is out of bound. 206 warp_data = [-0.1, 0.1, 1.2, 2.1] 207 warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) 208 expected = [[[0.0], [0.0]]] 209 self._assertForwardOpMatchesExpected(input_np, warp_np, expected) 210 211 expected_grad_data = [[[[0.81], [0.0]], [[0.09], [0.0]]]] 212 expected_grad_warp = [[[10.30, 2.7], [0.0, 0.0]]] 213 214 grad_output = np.ones([1, 2, 1], dtype=dtype) 215 self._assertBackwardOpMatchesExpected(input_np, warp_np, grad_output, 216 expected_grad_data, 217 expected_grad_warp) 218 219 # One of (x, y) is greater than image size. 220 for dtype in self.float_types: 221 input_shape = [1, 2, 2, 1] 222 input_data = [10, 5, 13, 54] 223 input_np = np.array(input_data, dtype=dtype).reshape(input_shape) 224 225 warp_shape = [1, 2, 2] 226 warp_data = [0.1, -0.1, 1.2, 0.1] 227 warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) 228 expected = [[[0.0], [0.0]]] 229 self._assertForwardOpMatchesExpected(input_np, warp_np, expected) 230 231 expected_grad_data = [[[[0.81], [0.81]], [[0.0], [0.08]]]] 232 expected_grad_warp = [[[-4.5, 9.5], [-9.9, 39.20]]] 233 234 grad_output = np.ones([1, 2, 1], dtype=dtype) 235 self._assertBackwardOpMatchesExpected(input_np, warp_np, grad_output, 236 expected_grad_data, 237 expected_grad_warp) 238 239 240if __name__ == '__main__': 241 test.main() 242