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 """Tests for tensorflow.ops.image_ops.""" 16 17 from __future__ import absolute_import 18 from __future__ import division 19 from __future__ import print_function 20 21 import colorsys 22 import functools 23 import math 24 import os 25 import time 26 27 import numpy as np 28 from six.moves import xrange # pylint: disable=redefined-builtin 29 30 from tensorflow.core.protobuf import config_pb2 31 from tensorflow.python.client import session 32 from tensorflow.python.framework import constant_op 33 from tensorflow.python.framework import dtypes 34 from tensorflow.python.framework import errors 35 from tensorflow.python.framework import ops 36 from tensorflow.python.framework import test_util 37 from tensorflow.python.ops import array_ops 38 from tensorflow.python.ops import control_flow_ops 39 from tensorflow.python.ops import gen_image_ops 40 from tensorflow.python.ops import image_ops 41 from tensorflow.python.ops import io_ops 42 from tensorflow.python.ops import math_ops 43 from tensorflow.python.ops import random_ops 44 from tensorflow.python.ops import variables 45 from tensorflow.python.platform import googletest 46 from tensorflow.python.platform import test 47 48 49 class RGBToHSVTest(test_util.TensorFlowTestCase): 50 51 def testBatch(self): 52 # Build an arbitrary RGB image 53 np.random.seed(7) 54 batch_size = 5 55 shape = (batch_size, 2, 7, 3) 56 57 for nptype in [np.float32, np.float64]: 58 inp = np.random.rand(*shape).astype(nptype) 59 60 # Convert to HSV and back, as a batch and individually 61 with self.test_session(use_gpu=True) as sess: 62 batch0 = constant_op.constant(inp) 63 batch1 = image_ops.rgb_to_hsv(batch0) 64 batch2 = image_ops.hsv_to_rgb(batch1) 65 split0 = array_ops.unstack(batch0) 66 split1 = list(map(image_ops.rgb_to_hsv, split0)) 67 split2 = list(map(image_ops.hsv_to_rgb, split1)) 68 join1 = array_ops.stack(split1) 69 join2 = array_ops.stack(split2) 70 batch1, batch2, join1, join2 = sess.run([batch1, batch2, join1, join2]) 71 72 # Verify that processing batch elements together is the same as separate 73 self.assertAllClose(batch1, join1) 74 self.assertAllClose(batch2, join2) 75 self.assertAllClose(batch2, inp) 76 77 def testRGBToHSVRoundTrip(self): 78 data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 79 for nptype in [np.float32, np.float64]: 80 rgb_np = np.array(data, dtype=nptype).reshape([2, 2, 3]) / 255. 81 with self.test_session(use_gpu=True): 82 hsv = image_ops.rgb_to_hsv(rgb_np) 83 rgb = image_ops.hsv_to_rgb(hsv) 84 rgb_tf = rgb.eval() 85 self.assertAllClose(rgb_tf, rgb_np) 86 87 88 class RGBToYIQTest(test_util.TensorFlowTestCase): 89 90 def testBatch(self): 91 # Build an arbitrary RGB image 92 np.random.seed(7) 93 batch_size = 5 94 shape = (batch_size, 2, 7, 3) 95 96 for nptype in [np.float32, np.float64]: 97 inp = np.random.rand(*shape).astype(nptype) 98 99 # Convert to YIQ and back, as a batch and individually 100 with self.test_session(use_gpu=True) as sess: 101 batch0 = constant_op.constant(inp) 102 batch1 = image_ops.rgb_to_yiq(batch0) 103 batch2 = image_ops.yiq_to_rgb(batch1) 104 split0 = array_ops.unstack(batch0) 105 split1 = list(map(image_ops.rgb_to_yiq, split0)) 106 split2 = list(map(image_ops.yiq_to_rgb, split1)) 107 join1 = array_ops.stack(split1) 108 join2 = array_ops.stack(split2) 109 batch1, batch2, join1, join2 = sess.run([batch1, batch2, join1, join2]) 110 111 # Verify that processing batch elements together is the same as separate 112 self.assertAllClose(batch1, join1, rtol=1e-4, atol=1e-4) 113 self.assertAllClose(batch2, join2, rtol=1e-4, atol=1e-4) 114 self.assertAllClose(batch2, inp, rtol=1e-4, atol=1e-4) 115 116 117 class RGBToYUVTest(test_util.TensorFlowTestCase): 118 119 def testBatch(self): 120 # Build an arbitrary RGB image 121 np.random.seed(7) 122 batch_size = 5 123 shape = (batch_size, 2, 7, 3) 124 125 for nptype in [np.float32, np.float64]: 126 inp = np.random.rand(*shape).astype(nptype) 127 128 # Convert to YUV and back, as a batch and individually 129 with self.test_session(use_gpu=True) as sess: 130 batch0 = constant_op.constant(inp) 131 batch1 = image_ops.rgb_to_yuv(batch0) 132 batch2 = image_ops.yuv_to_rgb(batch1) 133 split0 = array_ops.unstack(batch0) 134 split1 = list(map(image_ops.rgb_to_yuv, split0)) 135 split2 = list(map(image_ops.yuv_to_rgb, split1)) 136 join1 = array_ops.stack(split1) 137 join2 = array_ops.stack(split2) 138 batch1, batch2, join1, join2 = sess.run([batch1, batch2, join1, join2]) 139 140 # Verify that processing batch elements together is the same as separate 141 self.assertAllClose(batch1, join1, rtol=1e-4, atol=1e-4) 142 self.assertAllClose(batch2, join2, rtol=1e-4, atol=1e-4) 143 self.assertAllClose(batch2, inp, rtol=1e-4, atol=1e-4) 144 145 146 class GrayscaleToRGBTest(test_util.TensorFlowTestCase): 147 148 def _RGBToGrayscale(self, images): 149 is_batch = True 150 if len(images.shape) == 3: 151 is_batch = False 152 images = np.expand_dims(images, axis=0) 153 out_shape = images.shape[0:3] + (1,) 154 out = np.zeros(shape=out_shape, dtype=np.uint8) 155 for batch in xrange(images.shape[0]): 156 for y in xrange(images.shape[1]): 157 for x in xrange(images.shape[2]): 158 red = images[batch, y, x, 0] 159 green = images[batch, y, x, 1] 160 blue = images[batch, y, x, 2] 161 gray = 0.2989 * red + 0.5870 * green + 0.1140 * blue 162 out[batch, y, x, 0] = int(gray) 163 if not is_batch: 164 out = np.squeeze(out, axis=0) 165 return out 166 167 def _TestRGBToGrayscale(self, x_np): 168 y_np = self._RGBToGrayscale(x_np) 169 170 with self.test_session(use_gpu=True): 171 x_tf = constant_op.constant(x_np, shape=x_np.shape) 172 y = image_ops.rgb_to_grayscale(x_tf) 173 y_tf = y.eval() 174 self.assertAllEqual(y_tf, y_np) 175 176 def testBasicRGBToGrayscale(self): 177 # 4-D input with batch dimension. 178 x_np = np.array( 179 [[1, 2, 3], [4, 10, 1]], dtype=np.uint8).reshape([1, 1, 2, 3]) 180 self._TestRGBToGrayscale(x_np) 181 182 # 3-D input with no batch dimension. 183 x_np = np.array([[1, 2, 3], [4, 10, 1]], dtype=np.uint8).reshape([1, 2, 3]) 184 self._TestRGBToGrayscale(x_np) 185 186 def testBasicGrayscaleToRGB(self): 187 # 4-D input with batch dimension. 188 x_np = np.array([[1, 2]], dtype=np.uint8).reshape([1, 1, 2, 1]) 189 y_np = np.array( 190 [[1, 1, 1], [2, 2, 2]], dtype=np.uint8).reshape([1, 1, 2, 3]) 191 192 with self.test_session(use_gpu=True): 193 x_tf = constant_op.constant(x_np, shape=x_np.shape) 194 y = image_ops.grayscale_to_rgb(x_tf) 195 y_tf = y.eval() 196 self.assertAllEqual(y_tf, y_np) 197 198 # 3-D input with no batch dimension. 199 x_np = np.array([[1, 2]], dtype=np.uint8).reshape([1, 2, 1]) 200 y_np = np.array([[1, 1, 1], [2, 2, 2]], dtype=np.uint8).reshape([1, 2, 3]) 201 202 with self.test_session(use_gpu=True): 203 x_tf = constant_op.constant(x_np, shape=x_np.shape) 204 y = image_ops.grayscale_to_rgb(x_tf) 205 y_tf = y.eval() 206 self.assertAllEqual(y_tf, y_np) 207 208 def testShapeInference(self): 209 # Shape inference works and produces expected output where possible 210 rgb_shape = [7, None, 19, 3] 211 gray_shape = rgb_shape[:-1] + [1] 212 with self.test_session(use_gpu=True): 213 rgb_tf = array_ops.placeholder(dtypes.uint8, shape=rgb_shape) 214 gray = image_ops.rgb_to_grayscale(rgb_tf) 215 self.assertEqual(gray_shape, gray.get_shape().as_list()) 216 217 with self.test_session(use_gpu=True): 218 gray_tf = array_ops.placeholder(dtypes.uint8, shape=gray_shape) 219 rgb = image_ops.grayscale_to_rgb(gray_tf) 220 self.assertEqual(rgb_shape, rgb.get_shape().as_list()) 221 222 # Shape inference does not break for unknown shapes 223 with self.test_session(use_gpu=True): 224 rgb_tf_unknown = array_ops.placeholder(dtypes.uint8) 225 gray_unknown = image_ops.rgb_to_grayscale(rgb_tf_unknown) 226 self.assertFalse(gray_unknown.get_shape()) 227 228 with self.test_session(use_gpu=True): 229 gray_tf_unknown = array_ops.placeholder(dtypes.uint8) 230 rgb_unknown = image_ops.grayscale_to_rgb(gray_tf_unknown) 231 self.assertFalse(rgb_unknown.get_shape()) 232 233 234 class AdjustGamma(test_util.TensorFlowTestCase): 235 236 def test_adjust_gamma_one(self): 237 """Same image should be returned for gamma equal to one""" 238 with self.test_session(): 239 x_data = np.random.uniform(0, 255, (8, 8)) 240 x_np = np.array(x_data, dtype=np.float32) 241 242 x = constant_op.constant(x_np, shape=x_np.shape) 243 y = image_ops.adjust_gamma(x, gamma=1) 244 245 y_tf = y.eval() 246 y_np = x_np 247 248 self.assertAllClose(y_tf, y_np, 1e-6) 249 250 def test_adjust_gamma_less_zero(self): 251 """White image should be returned for gamma equal to zero""" 252 with self.test_session(): 253 x_data = np.random.uniform(0, 255, (8, 8)) 254 x_np = np.array(x_data, dtype=np.float32) 255 256 x = constant_op.constant(x_np, shape=x_np.shape) 257 258 err_msg = "Gamma should be a non-negative real number." 259 260 try: 261 image_ops.adjust_gamma(x, gamma=-1) 262 except Exception as e: 263 if err_msg not in str(e): 264 raise 265 else: 266 raise AssertionError("Exception not raised: %s" % err_msg) 267 268 def test_adjust_gamma_less_zero_tensor(self): 269 """White image should be returned for gamma equal to zero""" 270 with self.test_session(): 271 x_data = np.random.uniform(0, 255, (8, 8)) 272 x_np = np.array(x_data, dtype=np.float32) 273 274 x = constant_op.constant(x_np, shape=x_np.shape) 275 y = constant_op.constant(-1.0, dtype=dtypes.float32) 276 277 image = image_ops.adjust_gamma(x, gamma=y) 278 279 err_msg = "Gamma should be a non-negative real number." 280 try: 281 image.eval() 282 except Exception as e: 283 if err_msg not in str(e): 284 raise 285 else: 286 raise AssertionError("Exception not raised: %s" % err_msg) 287 288 def test_adjust_gamma_zero(self): 289 """White image should be returned for gamma equal to zero""" 290 with self.test_session(): 291 x_data = np.random.uniform(0, 255, (8, 8)) 292 x_np = np.array(x_data, dtype=np.float32) 293 294 x = constant_op.constant(x_np, shape=x_np.shape) 295 y = image_ops.adjust_gamma(x, gamma=0) 296 297 y_tf = y.eval() 298 299 dtype = x.dtype.as_numpy_dtype 300 y_np = np.array([dtypes.dtype_range[dtype][1]] * x_np.size) 301 y_np = y_np.reshape((8, 8)) 302 303 self.assertAllClose(y_tf, y_np, 1e-6) 304 305 def test_adjust_gamma_less_one(self): 306 """Verifying the output with expected results for gamma 307 correction with gamma equal to half""" 308 with self.test_session(): 309 x_np = np.arange(0, 255, 4, np.uint8).reshape(8, 8) 310 y = image_ops.adjust_gamma(x_np, gamma=0.5) 311 y_tf = np.trunc(y.eval()) 312 313 y_np = np.array( 314 [[0, 31, 45, 55, 63, 71, 78, 84], [ 315 90, 95, 100, 105, 110, 115, 119, 123 316 ], [127, 131, 135, 139, 142, 146, 149, 153], [ 317 156, 159, 162, 165, 168, 171, 174, 177 318 ], [180, 183, 186, 188, 191, 194, 196, 199], [ 319 201, 204, 206, 209, 211, 214, 216, 218 320 ], [221, 223, 225, 228, 230, 232, 234, 236], 321 [238, 241, 243, 245, 247, 249, 251, 253]], 322 dtype=np.float32) 323 324 self.assertAllClose(y_tf, y_np, 1e-6) 325 326 def test_adjust_gamma_greater_one(self): 327 """Verifying the output with expected results for gamma 328 correction with gamma equal to two""" 329 with self.test_session(): 330 x_np = np.arange(0, 255, 4, np.uint8).reshape(8, 8) 331 y = image_ops.adjust_gamma(x_np, gamma=2) 332 y_tf = np.trunc(y.eval()) 333 334 y_np = np.array( 335 [[0, 0, 0, 0, 1, 1, 2, 3], [4, 5, 6, 7, 9, 10, 12, 14], [ 336 16, 18, 20, 22, 25, 27, 30, 33 337 ], [36, 39, 42, 45, 49, 52, 56, 60], [64, 68, 72, 76, 81, 85, 90, 95], 338 [100, 105, 110, 116, 121, 127, 132, 138], [ 339 144, 150, 156, 163, 169, 176, 182, 189 340 ], [196, 203, 211, 218, 225, 233, 241, 249]], 341 dtype=np.float32) 342 343 self.assertAllClose(y_tf, y_np, 1e-6) 344 345 346 class AdjustHueTest(test_util.TensorFlowTestCase): 347 348 def testAdjustNegativeHue(self): 349 x_shape = [2, 2, 3] 350 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 351 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 352 353 delta = -0.25 354 y_data = [0, 13, 1, 54, 226, 59, 8, 234, 150, 255, 39, 1] 355 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 356 357 with self.test_session(use_gpu=True): 358 x = constant_op.constant(x_np, shape=x_shape) 359 y = image_ops.adjust_hue(x, delta) 360 y_tf = y.eval() 361 self.assertAllEqual(y_tf, y_np) 362 363 def testAdjustPositiveHue(self): 364 x_shape = [2, 2, 3] 365 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 366 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 367 368 delta = 0.25 369 y_data = [13, 0, 11, 226, 54, 221, 234, 8, 92, 1, 217, 255] 370 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 371 372 with self.test_session(use_gpu=True): 373 x = constant_op.constant(x_np, shape=x_shape) 374 y = image_ops.adjust_hue(x, delta) 375 y_tf = y.eval() 376 self.assertAllEqual(y_tf, y_np) 377 378 def testBatchAdjustHue(self): 379 x_shape = [2, 1, 2, 3] 380 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 381 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 382 383 delta = 0.25 384 y_data = [13, 0, 11, 226, 54, 221, 234, 8, 92, 1, 217, 255] 385 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 386 387 with self.test_session(use_gpu=True): 388 x = constant_op.constant(x_np, shape=x_shape) 389 y = image_ops.adjust_hue(x, delta) 390 y_tf = y.eval() 391 self.assertAllEqual(y_tf, y_np) 392 393 def _adjustHueNp(self, x_np, delta_h): 394 self.assertEqual(x_np.shape[-1], 3) 395 x_v = x_np.reshape([-1, 3]) 396 y_v = np.ndarray(x_v.shape, dtype=x_v.dtype) 397 channel_count = x_v.shape[0] 398 for i in xrange(channel_count): 399 r = x_v[i][0] 400 g = x_v[i][1] 401 b = x_v[i][2] 402 h, s, v = colorsys.rgb_to_hsv(r, g, b) 403 h += delta_h 404 h = math.fmod(h + 10.0, 1.0) 405 r, g, b = colorsys.hsv_to_rgb(h, s, v) 406 y_v[i][0] = r 407 y_v[i][1] = g 408 y_v[i][2] = b 409 return y_v.reshape(x_np.shape) 410 411 def _adjustHueTf(self, x_np, delta_h): 412 with self.test_session(use_gpu=True): 413 x = constant_op.constant(x_np) 414 y = image_ops.adjust_hue(x, delta_h) 415 y_tf = y.eval() 416 return y_tf 417 418 def testAdjustRandomHue(self): 419 x_shapes = [ 420 [2, 2, 3], 421 [4, 2, 3], 422 [2, 4, 3], 423 [2, 5, 3], 424 [1000, 1, 3], 425 ] 426 test_styles = [ 427 "all_random", 428 "rg_same", 429 "rb_same", 430 "gb_same", 431 "rgb_same", 432 ] 433 for x_shape in x_shapes: 434 for test_style in test_styles: 435 x_np = np.random.rand(*x_shape) * 255. 436 delta_h = np.random.rand() * 2.0 - 1.0 437 if test_style == "all_random": 438 pass 439 elif test_style == "rg_same": 440 x_np[..., 1] = x_np[..., 0] 441 elif test_style == "rb_same": 442 x_np[..., 2] = x_np[..., 0] 443 elif test_style == "gb_same": 444 x_np[..., 2] = x_np[..., 1] 445 elif test_style == "rgb_same": 446 x_np[..., 1] = x_np[..., 0] 447 x_np[..., 2] = x_np[..., 0] 448 else: 449 raise AssertionError("Invalid test style: %s" % (test_style)) 450 y_np = self._adjustHueNp(x_np, delta_h) 451 y_tf = self._adjustHueTf(x_np, delta_h) 452 self.assertAllClose(y_tf, y_np, rtol=2e-5, atol=1e-5) 453 454 def testInvalidShapes(self): 455 fused = False 456 if not fused: 457 # The tests are known to pass with the fused adjust_hue. We will enable 458 # them when the fused implementation is the default. 459 return 460 x_np = np.random.rand(2, 3) * 255. 461 delta_h = np.random.rand() * 2.0 - 1.0 462 fused = False 463 with self.assertRaisesRegexp(ValueError, "Shape must be at least rank 3"): 464 self._adjustHueTf(x_np, delta_h) 465 x_np = np.random.rand(4, 2, 4) * 255. 466 delta_h = np.random.rand() * 2.0 - 1.0 467 with self.assertRaisesOpError("input must have 3 channels"): 468 self._adjustHueTf(x_np, delta_h) 469 470 471 class FlipImageBenchmark(test.Benchmark): 472 473 def _benchmarkFlipLeftRight(self, device, cpu_count): 474 image_shape = [299, 299, 3] 475 warmup_rounds = 100 476 benchmark_rounds = 1000 477 config = config_pb2.ConfigProto() 478 if cpu_count is not None: 479 config.inter_op_parallelism_threads = 1 480 config.intra_op_parallelism_threads = cpu_count 481 with session.Session("", graph=ops.Graph(), config=config) as sess: 482 with ops.device(device): 483 inputs = variables.Variable( 484 random_ops.random_uniform(image_shape, dtype=dtypes.float32) * 255, 485 trainable=False, 486 dtype=dtypes.float32) 487 run_op = image_ops.flip_left_right(inputs) 488 sess.run(variables.global_variables_initializer()) 489 for i in xrange(warmup_rounds + benchmark_rounds): 490 if i == warmup_rounds: 491 start = time.time() 492 sess.run(run_op) 493 end = time.time() 494 step_time = (end - start) / benchmark_rounds 495 tag = device + "_%s" % (cpu_count if cpu_count is not None else "_all") 496 print("benchmarkFlipLeftRight_299_299_3_%s step_time: %.2f us" % 497 (tag, step_time * 1e6)) 498 self.report_benchmark( 499 name="benchmarkFlipLeftRight_299_299_3_%s" % (tag), 500 iters=benchmark_rounds, 501 wall_time=step_time) 502 503 def _benchmarkRandomFlipLeftRight(self, device, cpu_count): 504 image_shape = [299, 299, 3] 505 warmup_rounds = 100 506 benchmark_rounds = 1000 507 config = config_pb2.ConfigProto() 508 if cpu_count is not None: 509 config.inter_op_parallelism_threads = 1 510 config.intra_op_parallelism_threads = cpu_count 511 with session.Session("", graph=ops.Graph(), config=config) as sess: 512 with ops.device(device): 513 inputs = variables.Variable( 514 random_ops.random_uniform(image_shape, dtype=dtypes.float32) * 255, 515 trainable=False, 516 dtype=dtypes.float32) 517 run_op = image_ops.random_flip_left_right(inputs) 518 sess.run(variables.global_variables_initializer()) 519 for i in xrange(warmup_rounds + benchmark_rounds): 520 if i == warmup_rounds: 521 start = time.time() 522 sess.run(run_op) 523 end = time.time() 524 step_time = (end - start) / benchmark_rounds 525 tag = device + "_%s" % (cpu_count if cpu_count is not None else "_all") 526 print("benchmarkRandomFlipLeftRight_299_299_3_%s step_time: %.2f us" % 527 (tag, step_time * 1e6)) 528 self.report_benchmark( 529 name="benchmarkRandomFlipLeftRight_299_299_3_%s" % (tag), 530 iters=benchmark_rounds, 531 wall_time=step_time) 532 533 def benchmarkFlipLeftRightCpu1(self): 534 self._benchmarkFlipLeftRight("/cpu:0", 1) 535 536 def benchmarkFlipLeftRightCpuAll(self): 537 self._benchmarkFlipLeftRight("/cpu:0", None) 538 539 def benchmarkFlipLeftRightGpu(self): 540 self._benchmarkFlipLeftRight(test.gpu_device_name(), None) 541 542 def benchmarkRandomFlipLeftRightCpu1(self): 543 self._benchmarkRandomFlipLeftRight("/cpu:0", 1) 544 545 def benchmarkRandomFlipLeftRightCpuAll(self): 546 self._benchmarkRandomFlipLeftRight("/cpu:0", None) 547 548 def benchmarkRandomFlipLeftRightGpu(self): 549 self._benchmarkRandomFlipLeftRight(test.gpu_device_name(), None) 550 551 552 class AdjustHueBenchmark(test.Benchmark): 553 554 def _benchmarkAdjustHue(self, device, cpu_count): 555 image_shape = [299, 299, 3] 556 warmup_rounds = 100 557 benchmark_rounds = 1000 558 config = config_pb2.ConfigProto() 559 if cpu_count is not None: 560 config.inter_op_parallelism_threads = 1 561 config.intra_op_parallelism_threads = cpu_count 562 with session.Session("", graph=ops.Graph(), config=config) as sess: 563 with ops.device(device): 564 inputs = variables.Variable( 565 random_ops.random_uniform(image_shape, dtype=dtypes.float32) * 255, 566 trainable=False, 567 dtype=dtypes.float32) 568 delta = constant_op.constant(0.1, dtype=dtypes.float32) 569 outputs = image_ops.adjust_hue(inputs, delta) 570 run_op = control_flow_ops.group(outputs) 571 sess.run(variables.global_variables_initializer()) 572 for i in xrange(warmup_rounds + benchmark_rounds): 573 if i == warmup_rounds: 574 start = time.time() 575 sess.run(run_op) 576 end = time.time() 577 step_time = (end - start) / benchmark_rounds 578 tag = device + "_%s" % (cpu_count if cpu_count is not None else "_all") 579 print("benchmarkAdjustHue_299_299_3_%s step_time: %.2f us" % 580 (tag, step_time * 1e6)) 581 self.report_benchmark( 582 name="benchmarkAdjustHue_299_299_3_%s" % (tag), 583 iters=benchmark_rounds, 584 wall_time=step_time) 585 586 def benchmarkAdjustHueCpu1(self): 587 self._benchmarkAdjustHue("/cpu:0", 1) 588 589 def benchmarkAdjustHueCpuAll(self): 590 self._benchmarkAdjustHue("/cpu:0", None) 591 592 def benchmarkAdjustHueGpu(self): 593 self._benchmarkAdjustHue(test.gpu_device_name(), None) 594 595 596 class AdjustSaturationBenchmark(test.Benchmark): 597 598 def _benchmarkAdjustSaturation(self, device, cpu_count): 599 image_shape = [299, 299, 3] 600 warmup_rounds = 100 601 benchmark_rounds = 1000 602 config = config_pb2.ConfigProto() 603 if cpu_count is not None: 604 config.inter_op_parallelism_threads = 1 605 config.intra_op_parallelism_threads = cpu_count 606 with session.Session("", graph=ops.Graph(), config=config) as sess: 607 with ops.device(device): 608 inputs = variables.Variable( 609 random_ops.random_uniform(image_shape, dtype=dtypes.float32) * 255, 610 trainable=False, 611 dtype=dtypes.float32) 612 delta = constant_op.constant(0.1, dtype=dtypes.float32) 613 outputs = image_ops.adjust_saturation(inputs, delta) 614 run_op = control_flow_ops.group(outputs) 615 sess.run(variables.global_variables_initializer()) 616 for _ in xrange(warmup_rounds): 617 sess.run(run_op) 618 start = time.time() 619 for _ in xrange(benchmark_rounds): 620 sess.run(run_op) 621 end = time.time() 622 step_time = (end - start) / benchmark_rounds 623 tag = device + "_%s" % (cpu_count if cpu_count is not None else "_all") 624 print("benchmarkAdjustSaturation_299_299_3_%s step_time: %.2f us" % 625 (tag, step_time * 1e6)) 626 self.report_benchmark( 627 name="benchmarkAdjustSaturation_299_299_3_%s" % (tag), 628 iters=benchmark_rounds, 629 wall_time=step_time) 630 631 def benchmarkAdjustSaturationCpu1(self): 632 self._benchmarkAdjustSaturation("/cpu:0", 1) 633 634 def benchmarkAdjustSaturationCpuAll(self): 635 self._benchmarkAdjustSaturation("/cpu:0", None) 636 637 def benchmarkAdjustSaturationGpu(self): 638 self._benchmarkAdjustSaturation(test.gpu_device_name(), None) 639 640 641 class ResizeBilinearBenchmark(test.Benchmark): 642 643 def _benchmarkResize(self, image_size, num_channels): 644 batch_size = 1 645 num_ops = 1000 646 img = variables.Variable( 647 random_ops.random_normal( 648 [batch_size, image_size[0], image_size[1], num_channels]), 649 name="img") 650 651 deps = [] 652 for _ in xrange(num_ops): 653 with ops.control_dependencies(deps): 654 resize_op = image_ops.resize_bilinear( 655 img, [299, 299], align_corners=False) 656 deps = [resize_op] 657 benchmark_op = control_flow_ops.group(*deps) 658 659 with session.Session() as sess: 660 sess.run(variables.global_variables_initializer()) 661 results = self.run_op_benchmark( 662 sess, 663 benchmark_op, 664 name=("resize_bilinear_%s_%s_%s" % (image_size[0], image_size[1], 665 num_channels))) 666 print("%s : %.2f ms/img" % 667 (results["name"], 668 1000 * results["wall_time"] / (batch_size * num_ops))) 669 670 def benchmarkSimilar3Channel(self): 671 self._benchmarkResize((183, 229), 3) 672 673 def benchmarkScaleUp3Channel(self): 674 self._benchmarkResize((141, 186), 3) 675 676 def benchmarkScaleDown3Channel(self): 677 self._benchmarkResize((749, 603), 3) 678 679 def benchmarkSimilar1Channel(self): 680 self._benchmarkResize((183, 229), 1) 681 682 def benchmarkScaleUp1Channel(self): 683 self._benchmarkResize((141, 186), 1) 684 685 def benchmarkScaleDown1Channel(self): 686 self._benchmarkResize((749, 603), 1) 687 688 689 class ResizeBicubicBenchmark(test.Benchmark): 690 691 def _benchmarkResize(self, image_size, num_channels): 692 batch_size = 1 693 num_ops = 1000 694 img = variables.Variable( 695 random_ops.random_normal( 696 [batch_size, image_size[0], image_size[1], num_channels]), 697 name="img") 698 699 deps = [] 700 for _ in xrange(num_ops): 701 with ops.control_dependencies(deps): 702 resize_op = image_ops.resize_bicubic( 703 img, [299, 299], align_corners=False) 704 deps = [resize_op] 705 benchmark_op = control_flow_ops.group(*deps) 706 707 with session.Session() as sess: 708 sess.run(variables.global_variables_initializer()) 709 results = self.run_op_benchmark( 710 sess, 711 benchmark_op, 712 min_iters=20, 713 name=("resize_bicubic_%s_%s_%s" % (image_size[0], image_size[1], 714 num_channels))) 715 print("%s : %.2f ms/img" % 716 (results["name"], 717 1000 * results["wall_time"] / (batch_size * num_ops))) 718 719 def benchmarkSimilar3Channel(self): 720 self._benchmarkResize((183, 229), 3) 721 722 def benchmarkScaleUp3Channel(self): 723 self._benchmarkResize((141, 186), 3) 724 725 def benchmarkScaleDown3Channel(self): 726 self._benchmarkResize((749, 603), 3) 727 728 def benchmarkSimilar1Channel(self): 729 self._benchmarkResize((183, 229), 1) 730 731 def benchmarkScaleUp1Channel(self): 732 self._benchmarkResize((141, 186), 1) 733 734 def benchmarkScaleDown1Channel(self): 735 self._benchmarkResize((749, 603), 1) 736 737 def benchmarkSimilar4Channel(self): 738 self._benchmarkResize((183, 229), 4) 739 740 def benchmarkScaleUp4Channel(self): 741 self._benchmarkResize((141, 186), 4) 742 743 def benchmarkScaleDown4Channel(self): 744 self._benchmarkResize((749, 603), 4) 745 746 747 class ResizeAreaBenchmark(test.Benchmark): 748 749 def _benchmarkResize(self, image_size, num_channels): 750 batch_size = 1 751 num_ops = 1000 752 img = variables.Variable( 753 random_ops.random_normal( 754 [batch_size, image_size[0], image_size[1], num_channels]), 755 name="img") 756 757 deps = [] 758 for _ in xrange(num_ops): 759 with ops.control_dependencies(deps): 760 resize_op = image_ops.resize_area(img, [299, 299], align_corners=False) 761 deps = [resize_op] 762 benchmark_op = control_flow_ops.group(*deps) 763 764 with session.Session() as sess: 765 sess.run(variables.global_variables_initializer()) 766 results = self.run_op_benchmark( 767 sess, 768 benchmark_op, 769 name=("resize_area_%s_%s_%s" % (image_size[0], image_size[1], 770 num_channels))) 771 print("%s : %.2f ms/img" % 772 (results["name"], 773 1000 * results["wall_time"] / (batch_size * num_ops))) 774 775 def benchmarkSimilar3Channel(self): 776 self._benchmarkResize((183, 229), 3) 777 778 def benchmarkScaleUp3Channel(self): 779 self._benchmarkResize((141, 186), 3) 780 781 def benchmarkScaleDown3Channel(self): 782 self._benchmarkResize((749, 603), 3) 783 784 def benchmarkSimilar1Channel(self): 785 self._benchmarkResize((183, 229), 1) 786 787 def benchmarkScaleUp1Channel(self): 788 self._benchmarkResize((141, 186), 1) 789 790 def benchmarkScaleDown1Channel(self): 791 self._benchmarkResize((749, 603), 1) 792 793 794 class AdjustSaturationTest(test_util.TensorFlowTestCase): 795 796 def testHalfSaturation(self): 797 x_shape = [2, 2, 3] 798 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 799 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 800 801 saturation_factor = 0.5 802 y_data = [6, 9, 13, 140, 180, 226, 135, 121, 234, 172, 255, 128] 803 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 804 805 with self.test_session(use_gpu=True): 806 x = constant_op.constant(x_np, shape=x_shape) 807 y = image_ops.adjust_saturation(x, saturation_factor) 808 y_tf = y.eval() 809 self.assertAllEqual(y_tf, y_np) 810 811 def testTwiceSaturation(self): 812 x_shape = [2, 2, 3] 813 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 814 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 815 816 saturation_factor = 2.0 817 y_data = [0, 5, 13, 0, 106, 226, 30, 0, 234, 89, 255, 0] 818 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 819 820 with self.test_session(use_gpu=True): 821 x = constant_op.constant(x_np, shape=x_shape) 822 y = image_ops.adjust_saturation(x, saturation_factor) 823 y_tf = y.eval() 824 self.assertAllEqual(y_tf, y_np) 825 826 def testBatchSaturation(self): 827 x_shape = [2, 1, 2, 3] 828 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 829 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 830 831 saturation_factor = 0.5 832 y_data = [6, 9, 13, 140, 180, 226, 135, 121, 234, 172, 255, 128] 833 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 834 835 with self.test_session(use_gpu=True): 836 x = constant_op.constant(x_np, shape=x_shape) 837 y = image_ops.adjust_saturation(x, saturation_factor) 838 y_tf = y.eval() 839 self.assertAllEqual(y_tf, y_np) 840 841 def _adjust_saturation(self, image, saturation_factor): 842 image = ops.convert_to_tensor(image, name="image") 843 orig_dtype = image.dtype 844 flt_image = image_ops.convert_image_dtype(image, dtypes.float32) 845 saturation_adjusted_image = gen_image_ops.adjust_saturation( 846 flt_image, saturation_factor) 847 return image_ops.convert_image_dtype(saturation_adjusted_image, orig_dtype) 848 849 def testHalfSaturationFused(self): 850 x_shape = [2, 2, 3] 851 x_rgb_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 852 x_np = np.array(x_rgb_data, dtype=np.uint8).reshape(x_shape) 853 854 saturation_factor = 0.5 855 y_rgb_data = [6, 9, 13, 140, 180, 226, 135, 121, 234, 172, 255, 128] 856 y_np = np.array(y_rgb_data, dtype=np.uint8).reshape(x_shape) 857 858 with self.test_session(use_gpu=True): 859 x = constant_op.constant(x_np, shape=x_shape) 860 y = self._adjust_saturation(x, saturation_factor) 861 y_tf = y.eval() 862 self.assertAllEqual(y_tf, y_np) 863 864 def testTwiceSaturationFused(self): 865 x_shape = [2, 2, 3] 866 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 867 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 868 869 saturation_factor = 2.0 870 y_data = [0, 5, 13, 0, 106, 226, 30, 0, 234, 89, 255, 0] 871 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 872 873 with self.test_session(use_gpu=True): 874 x = constant_op.constant(x_np, shape=x_shape) 875 y = self._adjust_saturation(x, saturation_factor) 876 y_tf = y.eval() 877 self.assertAllEqual(y_tf, y_np) 878 879 def _adjustSaturationNp(self, x_np, scale): 880 self.assertEqual(x_np.shape[-1], 3) 881 x_v = x_np.reshape([-1, 3]) 882 y_v = np.ndarray(x_v.shape, dtype=x_v.dtype) 883 channel_count = x_v.shape[0] 884 for i in xrange(channel_count): 885 r = x_v[i][0] 886 g = x_v[i][1] 887 b = x_v[i][2] 888 h, s, v = colorsys.rgb_to_hsv(r, g, b) 889 s *= scale 890 s = min(1.0, max(0.0, s)) 891 r, g, b = colorsys.hsv_to_rgb(h, s, v) 892 y_v[i][0] = r 893 y_v[i][1] = g 894 y_v[i][2] = b 895 return y_v.reshape(x_np.shape) 896 897 def testAdjustRandomSaturation(self): 898 x_shapes = [ 899 [2, 2, 3], 900 [4, 2, 3], 901 [2, 4, 3], 902 [2, 5, 3], 903 [1000, 1, 3], 904 ] 905 test_styles = [ 906 "all_random", 907 "rg_same", 908 "rb_same", 909 "gb_same", 910 "rgb_same", 911 ] 912 with self.test_session(use_gpu=True): 913 for x_shape in x_shapes: 914 for test_style in test_styles: 915 x_np = np.random.rand(*x_shape) * 255. 916 scale = np.random.rand() 917 if test_style == "all_random": 918 pass 919 elif test_style == "rg_same": 920 x_np[..., 1] = x_np[..., 0] 921 elif test_style == "rb_same": 922 x_np[..., 2] = x_np[..., 0] 923 elif test_style == "gb_same": 924 x_np[..., 2] = x_np[..., 1] 925 elif test_style == "rgb_same": 926 x_np[..., 1] = x_np[..., 0] 927 x_np[..., 2] = x_np[..., 0] 928 else: 929 raise AssertionError("Invalid test style: %s" % (test_style)) 930 y_baseline = self._adjustSaturationNp(x_np, scale) 931 y_fused = self._adjust_saturation(x_np, scale).eval() 932 self.assertAllClose(y_fused, y_baseline, rtol=2e-5, atol=1e-5) 933 934 935 class FlipTransposeRotateTest(test_util.TensorFlowTestCase): 936 937 def testInvolutionLeftRight(self): 938 x_np = np.array([[1, 2, 3], [1, 2, 3]], dtype=np.uint8).reshape([2, 3, 1]) 939 with self.test_session(use_gpu=True): 940 x_tf = constant_op.constant(x_np, shape=x_np.shape) 941 y = image_ops.flip_left_right(image_ops.flip_left_right(x_tf)) 942 y_tf = y.eval() 943 self.assertAllEqual(y_tf, x_np) 944 945 def testInvolutionLeftRightWithBatch(self): 946 x_np = np.array([[[1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3]]], 947 dtype=np.uint8).reshape([2, 2, 3, 1]) 948 with self.test_session(use_gpu=True): 949 x_tf = constant_op.constant(x_np, shape=x_np.shape) 950 y = image_ops.flip_left_right(image_ops.flip_left_right(x_tf)) 951 y_tf = y.eval() 952 self.assertAllEqual(y_tf, x_np) 953 954 def testLeftRight(self): 955 x_np = np.array([[1, 2, 3], [1, 2, 3]], dtype=np.uint8).reshape([2, 3, 1]) 956 y_np = np.array([[3, 2, 1], [3, 2, 1]], dtype=np.uint8).reshape([2, 3, 1]) 957 958 with self.test_session(use_gpu=True): 959 x_tf = constant_op.constant(x_np, shape=x_np.shape) 960 y = image_ops.flip_left_right(x_tf) 961 self.assertTrue(y.op.name.startswith("flip_left_right")) 962 y_tf = y.eval() 963 self.assertAllEqual(y_tf, y_np) 964 965 def testLeftRightWithBatch(self): 966 x_np = np.array([[[1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3]]], 967 dtype=np.uint8).reshape([2, 2, 3, 1]) 968 y_np = np.array([[[3, 2, 1], [3, 2, 1]], [[3, 2, 1], [3, 2, 1]]], 969 dtype=np.uint8).reshape([2, 2, 3, 1]) 970 971 with self.test_session(use_gpu=True): 972 x_tf = constant_op.constant(x_np, shape=x_np.shape) 973 y = image_ops.flip_left_right(x_tf) 974 y_tf = y.eval() 975 self.assertAllEqual(y_tf, y_np) 976 977 978 def testRandomFlipLeftRight(self): 979 x_np = np.array([[1, 2, 3], [1, 2, 3]], dtype=np.uint8).reshape([2, 3, 1]) 980 y_np = np.array([[3, 2, 1], [3, 2, 1]], dtype=np.uint8).reshape([2, 3, 1]) 981 seed = 42 982 983 with self.test_session(use_gpu=True): 984 x_tf = constant_op.constant(x_np, shape=x_np.shape) 985 y = image_ops.random_flip_left_right(x_tf) 986 self.assertTrue(y.op.name.startswith("random_flip_left_right")) 987 988 count_flipped = 0 989 count_unflipped = 0 990 for _ in range(100): 991 y_tf = y.eval() 992 if y_tf[0][0] == 1: 993 self.assertAllEqual(y_tf, x_np) 994 count_unflipped += 1 995 else: 996 self.assertAllEqual(y_tf, y_np) 997 count_flipped += 1 998 999 # 100 trials 1000 # Mean: 50 1001 # Std Dev: ~5 1002 # Six Sigma: 50 - (5 * 6) = 20 1003 self.assertGreaterEqual(count_flipped, 20) 1004 self.assertGreaterEqual(count_unflipped, 20) 1005 1006 def testInvolutionUpDown(self): 1007 x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint8).reshape([2, 3, 1]) 1008 1009 with self.test_session(use_gpu=True): 1010 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1011 y = image_ops.flip_up_down(image_ops.flip_up_down(x_tf)) 1012 y_tf = y.eval() 1013 self.assertAllEqual(y_tf, x_np) 1014 1015 def testInvolutionUpDownWithBatch(self): 1016 x_np = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]], 1017 dtype=np.uint8).reshape([2, 2, 3, 1]) 1018 1019 with self.test_session(use_gpu=True): 1020 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1021 y = image_ops.flip_up_down(image_ops.flip_up_down(x_tf)) 1022 y_tf = y.eval() 1023 self.assertAllEqual(y_tf, x_np) 1024 1025 def testUpDown(self): 1026 x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint8).reshape([2, 3, 1]) 1027 y_np = np.array([[4, 5, 6], [1, 2, 3]], dtype=np.uint8).reshape([2, 3, 1]) 1028 1029 with self.test_session(use_gpu=True): 1030 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1031 y = image_ops.flip_up_down(x_tf) 1032 self.assertTrue(y.op.name.startswith("flip_up_down")) 1033 y_tf = y.eval() 1034 self.assertAllEqual(y_tf, y_np) 1035 1036 def testUpDownWithBatch(self): 1037 x_np = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]], 1038 dtype=np.uint8).reshape([2, 2, 3, 1]) 1039 y_np = np.array([[[4, 5, 6], [1, 2, 3]], [[10, 11, 12], [7, 8, 9]]], 1040 dtype=np.uint8).reshape([2, 2, 3, 1]) 1041 1042 with self.test_session(use_gpu=True): 1043 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1044 y = image_ops.flip_up_down(x_tf) 1045 y_tf = y.eval() 1046 self.assertAllEqual(y_tf, y_np) 1047 1048 def testRandomFlipUpDown(self): 1049 x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint8).reshape([2, 3, 1]) 1050 y_np = np.array([[4, 5, 6], [1, 2, 3]], dtype=np.uint8).reshape([2, 3, 1]) 1051 1052 with self.test_session(use_gpu=True): 1053 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1054 y = image_ops.random_flip_up_down(x_tf, seed=42) 1055 self.assertTrue(y.op.name.startswith("random_flip_up_down")) 1056 count_flipped = 0 1057 count_unflipped = 0 1058 for _ in range(100): 1059 y_tf = y.eval() 1060 if y_tf[0][0] == 1: 1061 self.assertAllEqual(y_tf, x_np) 1062 count_unflipped += 1 1063 else: 1064 self.assertAllEqual(y_tf, y_np) 1065 count_flipped += 1 1066 1067 # 100 trials 1068 # Mean: 50 1069 # Std Dev: ~5 1070 # Six Sigma: 50 - (5 * 6) = 20 1071 self.assertGreaterEqual(count_flipped, 20) 1072 self.assertGreaterEqual(count_unflipped, 20) 1073 1074 def testInvolutionTranspose(self): 1075 x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint8).reshape([2, 3, 1]) 1076 1077 with self.test_session(use_gpu=True): 1078 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1079 y = image_ops.transpose_image(image_ops.transpose_image(x_tf)) 1080 y_tf = y.eval() 1081 self.assertAllEqual(y_tf, x_np) 1082 1083 def testInvolutionTransposeWithBatch(self): 1084 x_np = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]], 1085 dtype=np.uint8).reshape([2, 2, 3, 1]) 1086 1087 with self.test_session(use_gpu=True): 1088 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1089 y = image_ops.transpose_image(image_ops.transpose_image(x_tf)) 1090 y_tf = y.eval() 1091 self.assertAllEqual(y_tf, x_np) 1092 1093 def testTranspose(self): 1094 x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint8).reshape([2, 3, 1]) 1095 y_np = np.array([[1, 4], [2, 5], [3, 6]], dtype=np.uint8).reshape([3, 2, 1]) 1096 1097 with self.test_session(use_gpu=True): 1098 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1099 y = image_ops.transpose_image(x_tf) 1100 self.assertTrue(y.op.name.startswith("transpose_image")) 1101 y_tf = y.eval() 1102 self.assertAllEqual(y_tf, y_np) 1103 1104 def testTransposeWithBatch(self): 1105 x_np = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]], 1106 dtype=np.uint8).reshape([2, 2, 3, 1]) 1107 1108 y_np = np.array([[[1, 4], [2, 5], [3, 6]], [[7, 10], [8, 11], [9, 12]]], 1109 dtype=np.uint8).reshape([2, 3, 2, 1]) 1110 1111 with self.test_session(use_gpu=True): 1112 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1113 y = image_ops.transpose_image(x_tf) 1114 y_tf = y.eval() 1115 self.assertAllEqual(y_tf, y_np) 1116 1117 def testPartialShapes(self): 1118 p_unknown_rank = array_ops.placeholder(dtypes.uint8) 1119 p_unknown_dims_3 = array_ops.placeholder( 1120 dtypes.uint8, shape=[None, None, None]) 1121 p_unknown_dims_4 = array_ops.placeholder( 1122 dtypes.uint8, shape=[None, None, None, None]) 1123 p_unknown_width = array_ops.placeholder(dtypes.uint8, shape=[64, None, 3]) 1124 p_unknown_batch = array_ops.placeholder(dtypes.uint8, 1125 shape=[None, 64, 64, 3]) 1126 p_wrong_rank = array_ops.placeholder(dtypes.uint8, shape=[None, None]) 1127 p_zero_dim = array_ops.placeholder(dtypes.uint8, shape=[64, 0, 3]) 1128 1129 #Ops that support 3D input 1130 for op in [ 1131 image_ops.flip_left_right, image_ops.flip_up_down, 1132 image_ops.random_flip_left_right, image_ops.random_flip_up_down, 1133 image_ops.transpose_image, image_ops.rot90 1134 ]: 1135 transformed_unknown_rank = op(p_unknown_rank) 1136 self.assertEqual(3, transformed_unknown_rank.get_shape().ndims) 1137 transformed_unknown_dims_3 = op(p_unknown_dims_3) 1138 self.assertEqual(3, transformed_unknown_dims_3.get_shape().ndims) 1139 transformed_unknown_width = op(p_unknown_width) 1140 self.assertEqual(3, transformed_unknown_width.get_shape().ndims) 1141 1142 with self.assertRaisesRegexp(ValueError, "must be > 0"): 1143 op(p_zero_dim) 1144 1145 #Ops that support 4D input 1146 for op in [ 1147 image_ops.flip_left_right, image_ops.flip_up_down, 1148 image_ops.transpose_image, image_ops.rot90 1149 ]: 1150 transformed_unknown_dims_4 = op(p_unknown_dims_4) 1151 self.assertEqual(4, transformed_unknown_dims_4.get_shape().ndims) 1152 transformed_unknown_batch = op(p_unknown_batch) 1153 self.assertEqual(4, transformed_unknown_batch.get_shape().ndims) 1154 with self.assertRaisesRegexp(ValueError, 1155 "must be at least three-dimensional"): 1156 op(p_wrong_rank) 1157 1158 for op in [ 1159 image_ops.random_flip_left_right, image_ops.random_flip_up_down, 1160 ]: 1161 with self.assertRaisesRegexp(ValueError, "must be three-dimensional"): 1162 op(p_wrong_rank) 1163 1164 1165 def testRot90GroupOrder(self): 1166 image = np.arange(24, dtype=np.uint8).reshape([2, 4, 3]) 1167 with self.test_session(use_gpu=True): 1168 rotated = image 1169 for _ in xrange(4): 1170 rotated = image_ops.rot90(rotated) 1171 self.assertAllEqual(image, rotated.eval()) 1172 1173 def testRot90GroupOrderWithBatch(self): 1174 image = np.arange(48, dtype=np.uint8).reshape([2, 2, 4, 3]) 1175 with self.test_session(use_gpu=True): 1176 rotated = image 1177 for _ in xrange(4): 1178 rotated = image_ops.rot90(rotated) 1179 self.assertAllEqual(image, rotated.eval()) 1180 1181 def testRot90NumpyEquivalence(self): 1182 image = np.arange(24, dtype=np.uint8).reshape([2, 4, 3]) 1183 with self.test_session(use_gpu=True): 1184 k_placeholder = array_ops.placeholder(dtypes.int32, shape=[]) 1185 y_tf = image_ops.rot90(image, k_placeholder) 1186 for k in xrange(4): 1187 y_np = np.rot90(image, k=k) 1188 self.assertAllEqual(y_np, y_tf.eval({k_placeholder: k})) 1189 1190 def testRot90NumpyEquivalenceWithBatch(self): 1191 image = np.arange(48, dtype=np.uint8).reshape([2, 2, 4, 3]) 1192 with self.test_session(use_gpu=True): 1193 k_placeholder = array_ops.placeholder(dtypes.int32, shape=[]) 1194 y_tf = image_ops.rot90(image, k_placeholder) 1195 for k in xrange(4): 1196 y_np = np.rot90(image, k=k, axes=(1, 2)) 1197 self.assertAllEqual(y_np, y_tf.eval({k_placeholder: k})) 1198 1199 class RandomFlipTest(test_util.TensorFlowTestCase): 1200 1201 def testRandomLeftRight(self): 1202 x_np = np.array([0, 1], dtype=np.uint8).reshape([1, 2, 1]) 1203 num_iterations = 500 1204 1205 hist = [0, 0] 1206 with self.test_session(use_gpu=True): 1207 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1208 y = image_ops.random_flip_left_right(x_tf) 1209 for _ in xrange(num_iterations): 1210 y_np = y.eval().flatten()[0] 1211 hist[y_np] += 1 1212 1213 # Ensure that each entry is observed within 4 standard deviations. 1214 four_stddev = 4.0 * np.sqrt(num_iterations / 2.0) 1215 self.assertAllClose(hist, [num_iterations / 2.0] * 2, atol=four_stddev) 1216 1217 def testRandomUpDown(self): 1218 x_np = np.array([0, 1], dtype=np.uint8).reshape([2, 1, 1]) 1219 num_iterations = 500 1220 1221 hist = [0, 0] 1222 with self.test_session(use_gpu=True): 1223 x_tf = constant_op.constant(x_np, shape=x_np.shape) 1224 y = image_ops.random_flip_up_down(x_tf) 1225 for _ in xrange(num_iterations): 1226 y_np = y.eval().flatten()[0] 1227 hist[y_np] += 1 1228 1229 # Ensure that each entry is observed within 4 standard deviations. 1230 four_stddev = 4.0 * np.sqrt(num_iterations / 2.0) 1231 self.assertAllClose(hist, [num_iterations / 2.0] * 2, atol=four_stddev) 1232 1233 1234 class AdjustContrastTest(test_util.TensorFlowTestCase): 1235 1236 def _testContrast(self, x_np, y_np, contrast_factor): 1237 with self.test_session(use_gpu=True): 1238 x = constant_op.constant(x_np, shape=x_np.shape) 1239 y = image_ops.adjust_contrast(x, contrast_factor) 1240 y_tf = y.eval() 1241 self.assertAllClose(y_tf, y_np, 1e-6) 1242 1243 def testDoubleContrastUint8(self): 1244 x_shape = [1, 2, 2, 3] 1245 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 1246 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 1247 1248 y_data = [0, 0, 0, 62, 169, 255, 28, 0, 255, 135, 255, 0] 1249 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 1250 1251 self._testContrast(x_np, y_np, contrast_factor=2.0) 1252 1253 def testDoubleContrastFloat(self): 1254 x_shape = [1, 2, 2, 3] 1255 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 1256 x_np = np.array(x_data, dtype=np.float).reshape(x_shape) / 255. 1257 1258 y_data = [ 1259 -45.25, -90.75, -92.5, 62.75, 169.25, 333.5, 28.75, -84.75, 349.5, 1260 134.75, 409.25, -116.5 1261 ] 1262 y_np = np.array(y_data, dtype=np.float).reshape(x_shape) / 255. 1263 1264 self._testContrast(x_np, y_np, contrast_factor=2.0) 1265 1266 def testHalfContrastUint8(self): 1267 x_shape = [1, 2, 2, 3] 1268 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 1269 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 1270 1271 y_data = [22, 52, 65, 49, 118, 172, 41, 54, 176, 67, 178, 59] 1272 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 1273 1274 self._testContrast(x_np, y_np, contrast_factor=0.5) 1275 1276 def testBatchDoubleContrast(self): 1277 x_shape = [2, 1, 2, 3] 1278 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 1279 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 1280 1281 y_data = [0, 0, 0, 81, 200, 255, 10, 0, 255, 116, 255, 0] 1282 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 1283 1284 self._testContrast(x_np, y_np, contrast_factor=2.0) 1285 1286 def _adjustContrastNp(self, x_np, contrast_factor): 1287 mean = np.mean(x_np, (1, 2), keepdims=True) 1288 y_np = mean + contrast_factor * (x_np - mean) 1289 return y_np 1290 1291 def _adjustContrastTf(self, x_np, contrast_factor): 1292 with self.test_session(use_gpu=True): 1293 x = constant_op.constant(x_np) 1294 y = image_ops.adjust_contrast(x, contrast_factor) 1295 y_tf = y.eval() 1296 return y_tf 1297 1298 def testRandomContrast(self): 1299 x_shapes = [ 1300 [1, 2, 2, 3], 1301 [2, 1, 2, 3], 1302 [1, 2, 2, 3], 1303 [2, 5, 5, 3], 1304 [2, 1, 1, 3], 1305 ] 1306 for x_shape in x_shapes: 1307 x_np = np.random.rand(*x_shape) * 255. 1308 contrast_factor = np.random.rand() * 2.0 + 0.1 1309 y_np = self._adjustContrastNp(x_np, contrast_factor) 1310 y_tf = self._adjustContrastTf(x_np, contrast_factor) 1311 self.assertAllClose(y_tf, y_np, rtol=1e-5, atol=1e-5) 1312 1313 1314 class AdjustBrightnessTest(test_util.TensorFlowTestCase): 1315 1316 def _testBrightness(self, x_np, y_np, delta): 1317 with self.test_session(use_gpu=True): 1318 x = constant_op.constant(x_np, shape=x_np.shape) 1319 y = image_ops.adjust_brightness(x, delta) 1320 y_tf = y.eval() 1321 self.assertAllClose(y_tf, y_np, 1e-6) 1322 1323 def testPositiveDeltaUint8(self): 1324 x_shape = [2, 2, 3] 1325 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 1326 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 1327 1328 y_data = [10, 15, 23, 64, 145, 236, 47, 18, 244, 100, 255, 11] 1329 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 1330 1331 self._testBrightness(x_np, y_np, delta=10. / 255.) 1332 1333 def testPositiveDeltaFloat(self): 1334 x_shape = [2, 2, 3] 1335 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 1336 x_np = np.array(x_data, dtype=np.float32).reshape(x_shape) / 255. 1337 1338 y_data = [10, 15, 23, 64, 145, 236, 47, 18, 244, 100, 265, 11] 1339 y_np = np.array(y_data, dtype=np.float32).reshape(x_shape) / 255. 1340 1341 self._testBrightness(x_np, y_np, delta=10. / 255.) 1342 1343 def testNegativeDelta(self): 1344 x_shape = [2, 2, 3] 1345 x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] 1346 x_np = np.array(x_data, dtype=np.uint8).reshape(x_shape) 1347 1348 y_data = [0, 0, 3, 44, 125, 216, 27, 0, 224, 80, 245, 0] 1349 y_np = np.array(y_data, dtype=np.uint8).reshape(x_shape) 1350 1351 self._testBrightness(x_np, y_np, delta=-10. / 255.) 1352 1353 1354 class PerImageWhiteningTest(test_util.TensorFlowTestCase): 1355 1356 def _NumpyPerImageWhitening(self, x): 1357 num_pixels = np.prod(x.shape) 1358 x2 = np.square(x).astype(np.float32) 1359 mn = np.mean(x) 1360 vr = np.mean(x2) - (mn * mn) 1361 stddev = max(math.sqrt(vr), 1.0 / math.sqrt(num_pixels)) 1362 1363 y = x.astype(np.float32) 1364 y -= mn 1365 y /= stddev 1366 return y 1367 1368 def testBasic(self): 1369 x_shape = [13, 9, 3] 1370 x_np = np.arange(0, np.prod(x_shape), dtype=np.int32).reshape(x_shape) 1371 y_np = self._NumpyPerImageWhitening(x_np) 1372 1373 with self.test_session(use_gpu=True): 1374 x = constant_op.constant(x_np, shape=x_shape) 1375 y = image_ops.per_image_standardization(x) 1376 self.assertTrue(y.op.name.startswith("per_image_standardization")) 1377 y_tf = y.eval() 1378 self.assertAllClose(y_tf, y_np, atol=1e-4) 1379 1380 def testUniformImage(self): 1381 im_np = np.ones([19, 19, 3]).astype(np.float32) * 249 1382 im = constant_op.constant(im_np) 1383 whiten = image_ops.per_image_standardization(im) 1384 with self.test_session(use_gpu=True): 1385 whiten_np = whiten.eval() 1386 self.assertFalse(np.any(np.isnan(whiten_np))) 1387 1388 1389 class CropToBoundingBoxTest(test_util.TensorFlowTestCase): 1390 1391 def _CropToBoundingBox(self, x, offset_height, offset_width, target_height, 1392 target_width, use_tensor_inputs): 1393 if use_tensor_inputs: 1394 offset_height = ops.convert_to_tensor(offset_height) 1395 offset_width = ops.convert_to_tensor(offset_width) 1396 target_height = ops.convert_to_tensor(target_height) 1397 target_width = ops.convert_to_tensor(target_width) 1398 x_tensor = array_ops.placeholder(x.dtype, shape=[None] * x.ndim) 1399 feed_dict = {x_tensor: x} 1400 else: 1401 x_tensor = x 1402 feed_dict = {} 1403 1404 y = image_ops.crop_to_bounding_box(x_tensor, offset_height, offset_width, 1405 target_height, target_width) 1406 if not use_tensor_inputs: 1407 self.assertTrue(y.get_shape().is_fully_defined()) 1408 1409 with self.test_session(use_gpu=True): 1410 return y.eval(feed_dict=feed_dict) 1411 1412 def _assertReturns(self, 1413 x, 1414 x_shape, 1415 offset_height, 1416 offset_width, 1417 y, 1418 y_shape, 1419 use_tensor_inputs_options=None): 1420 use_tensor_inputs_options = use_tensor_inputs_options or [False, True] 1421 target_height, target_width, _ = y_shape 1422 x = np.array(x).reshape(x_shape) 1423 y = np.array(y).reshape(y_shape) 1424 1425 for use_tensor_inputs in use_tensor_inputs_options: 1426 y_tf = self._CropToBoundingBox(x, offset_height, offset_width, 1427 target_height, target_width, 1428 use_tensor_inputs) 1429 self.assertAllClose(y, y_tf) 1430 1431 def _assertRaises(self, 1432 x, 1433 x_shape, 1434 offset_height, 1435 offset_width, 1436 target_height, 1437 target_width, 1438 err_msg, 1439 use_tensor_inputs_options=None): 1440 use_tensor_inputs_options = use_tensor_inputs_options or [False, True] 1441 x = np.array(x).reshape(x_shape) 1442 1443 for use_tensor_inputs in use_tensor_inputs_options: 1444 try: 1445 self._CropToBoundingBox(x, offset_height, offset_width, target_height, 1446 target_width, use_tensor_inputs) 1447 except Exception as e: 1448 if err_msg not in str(e): 1449 raise 1450 else: 1451 raise AssertionError("Exception not raised: %s" % err_msg) 1452 1453 def _assertShapeInference(self, pre_shape, height, width, post_shape): 1454 image = array_ops.placeholder(dtypes.float32, shape=pre_shape) 1455 y = image_ops.crop_to_bounding_box(image, 0, 0, height, width) 1456 self.assertEqual(y.get_shape().as_list(), post_shape) 1457 1458 def testNoOp(self): 1459 x_shape = [10, 10, 10] 1460 x = np.random.uniform(size=x_shape) 1461 self._assertReturns(x, x_shape, 0, 0, x, x_shape) 1462 1463 def testCrop(self): 1464 x = [1, 2, 3, 4, 5, 6, 7, 8, 9] 1465 x_shape = [3, 3, 1] 1466 1467 offset_height, offset_width = [1, 0] 1468 y_shape = [2, 3, 1] 1469 y = [4, 5, 6, 7, 8, 9] 1470 self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) 1471 1472 offset_height, offset_width = [0, 1] 1473 y_shape = [3, 2, 1] 1474 y = [2, 3, 5, 6, 8, 9] 1475 self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) 1476 1477 offset_height, offset_width = [0, 0] 1478 y_shape = [2, 3, 1] 1479 y = [1, 2, 3, 4, 5, 6] 1480 self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) 1481 1482 offset_height, offset_width = [0, 0] 1483 y_shape = [3, 2, 1] 1484 y = [1, 2, 4, 5, 7, 8] 1485 self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) 1486 1487 def testShapeInference(self): 1488 self._assertShapeInference([55, 66, 3], 55, 66, [55, 66, 3]) 1489 self._assertShapeInference([59, 69, 3], 55, 66, [55, 66, 3]) 1490 self._assertShapeInference([None, 66, 3], 55, 66, [55, 66, 3]) 1491 self._assertShapeInference([None, 69, 3], 55, 66, [55, 66, 3]) 1492 self._assertShapeInference([55, None, 3], 55, 66, [55, 66, 3]) 1493 self._assertShapeInference([59, None, 3], 55, 66, [55, 66, 3]) 1494 self._assertShapeInference([None, None, 3], 55, 66, [55, 66, 3]) 1495 self._assertShapeInference([55, 66, None], 55, 66, [55, 66, None]) 1496 self._assertShapeInference([59, 69, None], 55, 66, [55, 66, None]) 1497 self._assertShapeInference([None, None, None], 55, 66, [55, 66, None]) 1498 self._assertShapeInference(None, 55, 66, [55, 66, None]) 1499 1500 def testNon3DInput(self): 1501 # Input image is not 3D 1502 x = [0] * 15 1503 offset_height, offset_width = [0, 0] 1504 target_height, target_width = [2, 2] 1505 1506 for x_shape in ([3, 5], [1, 3, 5, 1, 1]): 1507 self._assertRaises(x, x_shape, offset_height, offset_width, target_height, 1508 target_width, 1509 "'image' must have either 3 or 4 dimensions.") 1510 1511 def testZeroLengthInput(self): 1512 # Input image has 0-length dimension(s). 1513 # Each line is a test configuration: 1514 # x_shape, target_height, target_width 1515 test_config = (([0, 2, 2], 1, 1), ([2, 0, 2], 1, 1), ([2, 2, 0], 1, 1), 1516 ([0, 2, 2], 0, 1), ([2, 0, 2], 1, 0)) 1517 offset_height, offset_width = [0, 0] 1518 x = [] 1519 1520 for x_shape, target_height, target_width in test_config: 1521 self._assertRaises( 1522 x, 1523 x_shape, 1524 offset_height, 1525 offset_width, 1526 target_height, 1527 target_width, 1528 "all dims of 'image.shape' must be > 0", 1529 use_tensor_inputs_options=[False]) 1530 # Multiple assertion could fail, but the evaluation order is arbitrary. 1531 # Match gainst generic pattern. 1532 self._assertRaises( 1533 x, 1534 x_shape, 1535 offset_height, 1536 offset_width, 1537 target_height, 1538 target_width, 1539 "assertion failed:", 1540 use_tensor_inputs_options=[True]) 1541 1542 def testBadParams(self): 1543 x_shape = [4, 4, 1] 1544 x = np.zeros(x_shape) 1545 1546 # Each line is a test configuration: 1547 # (offset_height, offset_width, target_height, target_width), err_msg 1548 test_config = (([-1, 0, 3, 3], "offset_height must be >= 0"), ([ 1549 0, -1, 3, 3 1550 ], "offset_width must be >= 0"), ([0, 0, 0, 3], 1551 "target_height must be > 0"), 1552 ([0, 0, 3, 0], "target_width must be > 0"), 1553 ([2, 0, 3, 3], "height must be >= target + offset"), 1554 ([0, 2, 3, 3], "width must be >= target + offset")) 1555 1556 for params, err_msg in test_config: 1557 self._assertRaises(x, x_shape, *params, err_msg=err_msg) 1558 1559 def testNameScope(self): 1560 image = array_ops.placeholder(dtypes.float32, shape=[55, 66, 3]) 1561 y = image_ops.crop_to_bounding_box(image, 0, 0, 55, 66) 1562 self.assertTrue(y.name.startswith("crop_to_bounding_box")) 1563 1564 1565 class CentralCropTest(test_util.TensorFlowTestCase): 1566 1567 def _assertShapeInference(self, pre_shape, fraction, post_shape): 1568 image = array_ops.placeholder(dtypes.float32, shape=pre_shape) 1569 y = image_ops.central_crop(image, fraction) 1570 if post_shape is None: 1571 self.assertEqual(y.get_shape().dims, None) 1572 else: 1573 self.assertEqual(y.get_shape().as_list(), post_shape) 1574 1575 def testNoOp(self): 1576 x_shape = [13, 9, 3] 1577 x_np = np.ones(x_shape, dtype=np.float32) 1578 with self.test_session(use_gpu=True): 1579 x = constant_op.constant(x_np, shape=x_shape) 1580 y = image_ops.central_crop(x, 1.0) 1581 y_tf = y.eval() 1582 self.assertAllEqual(y_tf, x_np) 1583 self.assertEqual(y.op.name, x.op.name) 1584 1585 def testCropping(self): 1586 x_shape = [4, 8, 1] 1587 x_np = np.array( 1588 [[1, 2, 3, 4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7, 8], 1589 [1, 2, 3, 4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7, 8]], 1590 dtype=np.int32).reshape(x_shape) 1591 y_np = np.array([[3, 4, 5, 6], [3, 4, 5, 6]]).reshape([2, 4, 1]) 1592 with self.test_session(use_gpu=True): 1593 x = constant_op.constant(x_np, shape=x_shape) 1594 y = image_ops.central_crop(x, 0.5) 1595 y_tf = y.eval() 1596 self.assertAllEqual(y_tf, y_np) 1597 self.assertAllEqual(y_tf.shape, y_np.shape) 1598 1599 def testCropping2(self): 1600 # Test case for 10315 1601 x_shape = [240, 320, 3] 1602 x_np = np.zeros(x_shape, dtype=np.int32) 1603 y_np = np.zeros([80, 106, 3], dtype=np.int32) 1604 with self.test_session(use_gpu=True): 1605 x = array_ops.placeholder(shape=x_shape, dtype=dtypes.int32) 1606 y = image_ops.central_crop(x, 0.33) 1607 y_tf = y.eval(feed_dict={x: x_np}) 1608 self.assertAllEqual(y_tf, y_np) 1609 self.assertAllEqual(y_tf.shape, y_np.shape) 1610 1611 def testShapeInference(self): 1612 # Test no-op fraction=1.0 1613 self._assertShapeInference([50, 60, 3], 1.0, [50, 60, 3]) 1614 self._assertShapeInference([None, 60, 3], 1.0, [None, 60, 3]) 1615 self._assertShapeInference([50, None, 3], 1.0, [50, None, 3]) 1616 self._assertShapeInference([None, None, 3], 1.0, [None, None, 3]) 1617 self._assertShapeInference([50, 60, None], 1.0, [50, 60, None]) 1618 self._assertShapeInference([None, None, None], 1.0, [None, None, None]) 1619 self._assertShapeInference(None, 1.0, None) 1620 # TODO(toddw): Currently central_crop() doesn't infer the result shape even 1621 # when it's possible. If we change it to do so, we can test as follows: 1622 # 1623 # self._assertShapeInference([50, 60, 3], 0.5, [25, 30, 3]) 1624 # self._assertShapeInference([None, 60, 3], 0.5, [None, 30, 3]) 1625 # self._assertShapeInference([50, None, 3], 0.5, [25, None, 3]) 1626 # self._assertShapeInference([None, None, 3], 0.5, [None, None, 3]) 1627 # self._assertShapeInference([50, 60, None], 0.5, [25, 30, None]) 1628 # self._assertShapeInference([None, None, None], 0.5, [None, None, None]) 1629 # self._assertShapeInference(None, 0.5, None) 1630 1631 def testError(self): 1632 x_shape = [13, 9, 3] 1633 x_np = np.ones(x_shape, dtype=np.float32) 1634 with self.test_session(use_gpu=True): 1635 x = constant_op.constant(x_np, shape=x_shape) 1636 with self.assertRaises(ValueError): 1637 _ = image_ops.central_crop(x, 0.0) 1638 with self.assertRaises(ValueError): 1639 _ = image_ops.central_crop(x, 1.01) 1640 1641 def testNameScope(self): 1642 x_shape = [13, 9, 3] 1643 x_np = np.ones(x_shape, dtype=np.float32) 1644 with self.test_session(use_gpu=True): 1645 y = image_ops.central_crop(x_np, 1.0) 1646 self.assertTrue(y.op.name.startswith("central_crop")) 1647 1648 1649 class PadToBoundingBoxTest(test_util.TensorFlowTestCase): 1650 1651 def _PadToBoundingBox(self, x, offset_height, offset_width, target_height, 1652 target_width, use_tensor_inputs): 1653 if use_tensor_inputs: 1654 offset_height = ops.convert_to_tensor(offset_height) 1655 offset_width = ops.convert_to_tensor(offset_width) 1656 target_height = ops.convert_to_tensor(target_height) 1657 target_width = ops.convert_to_tensor(target_width) 1658 x_tensor = array_ops.placeholder(x.dtype, shape=[None] * x.ndim) 1659 feed_dict = {x_tensor: x} 1660 else: 1661 x_tensor = x 1662 feed_dict = {} 1663 1664 y = image_ops.pad_to_bounding_box(x_tensor, offset_height, offset_width, 1665 target_height, target_width) 1666 if not use_tensor_inputs: 1667 self.assertTrue(y.get_shape().is_fully_defined()) 1668 1669 with self.test_session(use_gpu=True): 1670 return y.eval(feed_dict=feed_dict) 1671 1672 def _assertReturns(self, 1673 x, 1674 x_shape, 1675 offset_height, 1676 offset_width, 1677 y, 1678 y_shape, 1679 use_tensor_inputs_options=None): 1680 use_tensor_inputs_options = use_tensor_inputs_options or [False, True] 1681 target_height, target_width, _ = y_shape 1682 x = np.array(x).reshape(x_shape) 1683 y = np.array(y).reshape(y_shape) 1684 1685 for use_tensor_inputs in use_tensor_inputs_options: 1686 y_tf = self._PadToBoundingBox(x, offset_height, offset_width, 1687 target_height, target_width, 1688 use_tensor_inputs) 1689 self.assertAllClose(y, y_tf) 1690 1691 def _assertRaises(self, 1692 x, 1693 x_shape, 1694 offset_height, 1695 offset_width, 1696 target_height, 1697 target_width, 1698 err_msg, 1699 use_tensor_inputs_options=None): 1700 use_tensor_inputs_options = use_tensor_inputs_options or [False, True] 1701 x = np.array(x).reshape(x_shape) 1702 1703 for use_tensor_inputs in use_tensor_inputs_options: 1704 try: 1705 self._PadToBoundingBox(x, offset_height, offset_width, target_height, 1706 target_width, use_tensor_inputs) 1707 except Exception as e: 1708 if err_msg not in str(e): 1709 raise 1710 else: 1711 raise AssertionError("Exception not raised: %s" % err_msg) 1712 1713 def _assertShapeInference(self, pre_shape, height, width, post_shape): 1714 image = array_ops.placeholder(dtypes.float32, shape=pre_shape) 1715 y = image_ops.pad_to_bounding_box(image, 0, 0, height, width) 1716 self.assertEqual(y.get_shape().as_list(), post_shape) 1717 1718 def testInt64(self): 1719 x = [1, 2, 3, 4, 5, 6, 7, 8, 9] 1720 x_shape = [3, 3, 1] 1721 1722 y = [0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 1723 y_shape = [4, 3, 1] 1724 x = np.array(x).reshape(x_shape) 1725 y = np.array(y).reshape(y_shape) 1726 1727 i = constant_op.constant([1, 0, 4, 3], dtype=dtypes.int64) 1728 y_tf = image_ops.pad_to_bounding_box(x, i[0], i[1], i[2], i[3]) 1729 with self.test_session(use_gpu=True): 1730 self.assertAllClose(y, y_tf.eval()) 1731 1732 def testNoOp(self): 1733 x_shape = [10, 10, 10] 1734 x = np.random.uniform(size=x_shape) 1735 offset_height, offset_width = [0, 0] 1736 self._assertReturns(x, x_shape, offset_height, offset_width, x, x_shape) 1737 1738 def testPadding(self): 1739 x = [1, 2, 3, 4, 5, 6, 7, 8, 9] 1740 x_shape = [3, 3, 1] 1741 1742 offset_height, offset_width = [1, 0] 1743 y = [0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 1744 y_shape = [4, 3, 1] 1745 self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) 1746 1747 offset_height, offset_width = [0, 1] 1748 y = [0, 1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9] 1749 y_shape = [3, 4, 1] 1750 self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) 1751 1752 offset_height, offset_width = [0, 0] 1753 y = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0] 1754 y_shape = [4, 3, 1] 1755 self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) 1756 1757 offset_height, offset_width = [0, 0] 1758 y = [1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9, 0] 1759 y_shape = [3, 4, 1] 1760 self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) 1761 1762 def testShapeInference(self): 1763 self._assertShapeInference([55, 66, 3], 55, 66, [55, 66, 3]) 1764 self._assertShapeInference([50, 60, 3], 55, 66, [55, 66, 3]) 1765 self._assertShapeInference([None, 66, 3], 55, 66, [55, 66, 3]) 1766 self._assertShapeInference([None, 60, 3], 55, 66, [55, 66, 3]) 1767 self._assertShapeInference([55, None, 3], 55, 66, [55, 66, 3]) 1768 self._assertShapeInference([50, None, 3], 55, 66, [55, 66, 3]) 1769 self._assertShapeInference([None, None, 3], 55, 66, [55, 66, 3]) 1770 self._assertShapeInference([55, 66, None], 55, 66, [55, 66, None]) 1771 self._assertShapeInference([50, 60, None], 55, 66, [55, 66, None]) 1772 self._assertShapeInference([None, None, None], 55, 66, [55, 66, None]) 1773 self._assertShapeInference(None, 55, 66, [55, 66, None]) 1774 1775 def testNon3DInput(self): 1776 # Input image is not 3D 1777 x = [0] * 15 1778 offset_height, offset_width = [0, 0] 1779 target_height, target_width = [2, 2] 1780 1781 for x_shape in ([3, 5], [1, 3, 5, 1, 1]): 1782 self._assertRaises(x, x_shape, offset_height, offset_width, target_height, 1783 target_width, 1784 "'image' must have either 3 or 4 dimensions.") 1785 1786 def testZeroLengthInput(self): 1787 # Input image has 0-length dimension(s). 1788 # Each line is a test configuration: 1789 # x_shape, target_height, target_width 1790 test_config = (([0, 2, 2], 2, 2), ([2, 0, 2], 2, 2), ([2, 2, 0], 2, 2)) 1791 offset_height, offset_width = [0, 0] 1792 x = [] 1793 1794 for x_shape, target_height, target_width in test_config: 1795 self._assertRaises( 1796 x, 1797 x_shape, 1798 offset_height, 1799 offset_width, 1800 target_height, 1801 target_width, 1802 "all dims of 'image.shape' must be > 0", 1803 use_tensor_inputs_options=[False]) 1804 1805 # The orignal error message does not contain back slashes. However, they 1806 # are added by either the assert op or the runtime. If this behavior 1807 # changes in the future, the match string will also needs to be changed. 1808 self._assertRaises( 1809 x, 1810 x_shape, 1811 offset_height, 1812 offset_width, 1813 target_height, 1814 target_width, 1815 "all dims of \\'image.shape\\' must be > 0", 1816 use_tensor_inputs_options=[True]) 1817 1818 def testBadParams(self): 1819 x_shape = [3, 3, 1] 1820 x = np.zeros(x_shape) 1821 1822 # Each line is a test configuration: 1823 # offset_height, offset_width, target_height, target_width, err_msg 1824 test_config = ((-1, 0, 4, 4, "offset_height must be >= 0"), 1825 (0, -1, 4, 4, "offset_width must be >= 0"), 1826 (2, 0, 4, 4, "height must be <= target - offset"), 1827 (0, 2, 4, 4, "width must be <= target - offset")) 1828 1829 for config_item in test_config: 1830 self._assertRaises(x, x_shape, *config_item) 1831 1832 def testNameScope(self): 1833 image = array_ops.placeholder(dtypes.float32, shape=[55, 66, 3]) 1834 y = image_ops.pad_to_bounding_box(image, 0, 0, 55, 66) 1835 self.assertTrue(y.op.name.startswith("pad_to_bounding_box")) 1836 1837 1838 class SelectDistortedCropBoxTest(test_util.TensorFlowTestCase): 1839 1840 def _testSampleDistortedBoundingBox(self, image, bounding_box, 1841 min_object_covered, aspect_ratio_range, 1842 area_range): 1843 original_area = float(np.prod(image.shape)) 1844 bounding_box_area = float((bounding_box[3] - bounding_box[1]) * 1845 (bounding_box[2] - bounding_box[0])) 1846 1847 image_size_np = np.array(image.shape, dtype=np.int32) 1848 bounding_box_np = ( 1849 np.array(bounding_box, dtype=np.float32).reshape([1, 1, 4])) 1850 1851 aspect_ratios = [] 1852 area_ratios = [] 1853 1854 fraction_object_covered = [] 1855 1856 num_iter = 1000 1857 with self.test_session(use_gpu=True): 1858 image_tf = constant_op.constant(image, shape=image.shape) 1859 image_size_tf = constant_op.constant( 1860 image_size_np, shape=image_size_np.shape) 1861 bounding_box_tf = constant_op.constant( 1862 bounding_box_np, dtype=dtypes.float32, shape=bounding_box_np.shape) 1863 1864 begin, size, _ = image_ops.sample_distorted_bounding_box( 1865 image_size=image_size_tf, 1866 bounding_boxes=bounding_box_tf, 1867 min_object_covered=min_object_covered, 1868 aspect_ratio_range=aspect_ratio_range, 1869 area_range=area_range) 1870 y = array_ops.strided_slice(image_tf, begin, begin + size) 1871 1872 for _ in xrange(num_iter): 1873 y_tf = y.eval() 1874 crop_height = y_tf.shape[0] 1875 crop_width = y_tf.shape[1] 1876 aspect_ratio = float(crop_width) / float(crop_height) 1877 area = float(crop_width * crop_height) 1878 1879 aspect_ratios.append(aspect_ratio) 1880 area_ratios.append(area / original_area) 1881 fraction_object_covered.append(float(np.sum(y_tf)) / bounding_box_area) 1882 1883 # min_object_covered as tensor 1884 min_object_covered_placeholder = array_ops.placeholder(dtypes.float32) 1885 begin, size, _ = image_ops.sample_distorted_bounding_box( 1886 image_size=image_size_tf, 1887 bounding_boxes=bounding_box_tf, 1888 min_object_covered=min_object_covered_placeholder, 1889 aspect_ratio_range=aspect_ratio_range, 1890 area_range=area_range) 1891 y = array_ops.strided_slice(image_tf, begin, begin + size) 1892 1893 for _ in xrange(num_iter): 1894 y_tf = y.eval(feed_dict={ 1895 min_object_covered_placeholder: min_object_covered 1896 }) 1897 crop_height = y_tf.shape[0] 1898 crop_width = y_tf.shape[1] 1899 aspect_ratio = float(crop_width) / float(crop_height) 1900 area = float(crop_width * crop_height) 1901 1902 aspect_ratios.append(aspect_ratio) 1903 area_ratios.append(area / original_area) 1904 fraction_object_covered.append(float(np.sum(y_tf)) / bounding_box_area) 1905 1906 # Ensure that each entry is observed within 3 standard deviations. 1907 # num_bins = 10 1908 # aspect_ratio_hist, _ = np.histogram(aspect_ratios, 1909 # bins=num_bins, 1910 # range=aspect_ratio_range) 1911 # mean = np.mean(aspect_ratio_hist) 1912 # stddev = np.sqrt(mean) 1913 # TODO(wicke, shlens, dga): Restore this test so that it is no longer flaky. 1914 # TODO(irving): Since the rejection probability is not independent of the 1915 # aspect ratio, the aspect_ratio random value is not exactly uniformly 1916 # distributed in [min_aspect_ratio, max_aspect_ratio). This test should be 1917 # fixed to reflect the true statistical property, then tightened to enforce 1918 # a stricter bound. Or, ideally, the sample_distorted_bounding_box Op 1919 # be fixed to not use rejection sampling and generate correctly uniform 1920 # aspect ratios. 1921 # self.assertAllClose(aspect_ratio_hist, 1922 # [mean] * num_bins, atol=3.6 * stddev) 1923 1924 # The resulting crop will not be uniformly distributed in area. In practice, 1925 # we find that the area skews towards the small sizes. Instead, we perform 1926 # a weaker test to ensure that the area ratios are merely within the 1927 # specified bounds. 1928 self.assertLessEqual(max(area_ratios), area_range[1]) 1929 self.assertGreaterEqual(min(area_ratios), area_range[0]) 1930 1931 # For reference, here is what the distribution of area ratios look like. 1932 area_ratio_hist, _ = np.histogram(area_ratios, bins=10, range=area_range) 1933 print("area_ratio_hist ", area_ratio_hist) 1934 1935 # Ensure that fraction_object_covered is satisfied. 1936 # TODO(wicke, shlens, dga): Restore this test so that it is no longer flaky. 1937 # self.assertGreaterEqual(min(fraction_object_covered), min_object_covered) 1938 1939 def testWholeImageBoundingBox(self): 1940 height = 40 1941 width = 50 1942 image_size = [height, width, 1] 1943 bounding_box = [0.0, 0.0, 1.0, 1.0] 1944 image = np.arange( 1945 0, np.prod(image_size), dtype=np.int32).reshape(image_size) 1946 self._testSampleDistortedBoundingBox( 1947 image, 1948 bounding_box, 1949 min_object_covered=0.1, 1950 aspect_ratio_range=(0.75, 1.33), 1951 area_range=(0.05, 1.0)) 1952 1953 def testWithBoundingBox(self): 1954 height = 40 1955 width = 50 1956 x_shape = [height, width, 1] 1957 image = np.zeros(x_shape, dtype=np.int32) 1958 1959 # Create an object with 1's in a region with area A and require that 1960 # the total pixel values >= 0.1 * A. 1961 min_object_covered = 0.1 1962 1963 xmin = 2 1964 ymin = 3 1965 xmax = 12 1966 ymax = 13 1967 for x in np.arange(xmin, xmax + 1, 1): 1968 for y in np.arange(ymin, ymax + 1, 1): 1969 image[x, y] = 1 1970 1971 # Bounding box is specified as (ymin, xmin, ymax, xmax) in 1972 # relative coordinates. 1973 bounding_box = (float(ymin) / height, float(xmin) / width, 1974 float(ymax) / height, float(xmax) / width) 1975 1976 self._testSampleDistortedBoundingBox( 1977 image, 1978 bounding_box=bounding_box, 1979 min_object_covered=min_object_covered, 1980 aspect_ratio_range=(0.75, 1.33), 1981 area_range=(0.05, 1.0)) 1982 1983 def testSampleDistortedBoundingBoxShape(self): 1984 with self.test_session(use_gpu=True): 1985 image_size = constant_op.constant( 1986 [40, 50, 1], shape=[3], dtype=dtypes.int32) 1987 bounding_box = constant_op.constant( 1988 [[[0.0, 0.0, 1.0, 1.0]]], 1989 shape=[1, 1, 4], 1990 dtype=dtypes.float32, 1991 ) 1992 begin, end, bbox_for_drawing = image_ops.sample_distorted_bounding_box( 1993 image_size=image_size, 1994 bounding_boxes=bounding_box, 1995 min_object_covered=0.1, 1996 aspect_ratio_range=(0.75, 1.33), 1997 area_range=(0.05, 1.0)) 1998 1999 # Test that the shapes are correct. 2000 self.assertAllEqual([3], begin.get_shape().as_list()) 2001 self.assertAllEqual([3], end.get_shape().as_list()) 2002 self.assertAllEqual([1, 1, 4], bbox_for_drawing.get_shape().as_list()) 2003 # Actual run to make sure shape is correct inside Compute(). 2004 begin = begin.eval() 2005 end = end.eval() 2006 bbox_for_drawing = bbox_for_drawing.eval() 2007 2008 begin, end, bbox_for_drawing = image_ops.sample_distorted_bounding_box( 2009 image_size=image_size, 2010 bounding_boxes=bounding_box, 2011 min_object_covered=array_ops.placeholder(dtypes.float32), 2012 aspect_ratio_range=(0.75, 1.33), 2013 area_range=(0.05, 1.0)) 2014 2015 # Test that the shapes are correct. 2016 self.assertAllEqual([3], begin.get_shape().as_list()) 2017 self.assertAllEqual([3], end.get_shape().as_list()) 2018 self.assertAllEqual([1, 1, 4], bbox_for_drawing.get_shape().as_list()) 2019 2020 def testDefaultMinObjectCovered(self): 2021 # By default min_object_covered=0.1 if not provided 2022 with self.test_session(use_gpu=True): 2023 image_size = constant_op.constant( 2024 [40, 50, 1], shape=[3], dtype=dtypes.int32) 2025 bounding_box = constant_op.constant( 2026 [[[0.0, 0.0, 1.0, 1.0]]], 2027 shape=[1, 1, 4], 2028 dtype=dtypes.float32, 2029 ) 2030 begin, end, bbox_for_drawing = image_ops.sample_distorted_bounding_box( 2031 image_size=image_size, 2032 bounding_boxes=bounding_box, 2033 aspect_ratio_range=(0.75, 1.33), 2034 area_range=(0.05, 1.0)) 2035 2036 self.assertAllEqual([3], begin.get_shape().as_list()) 2037 self.assertAllEqual([3], end.get_shape().as_list()) 2038 self.assertAllEqual([1, 1, 4], bbox_for_drawing.get_shape().as_list()) 2039 # Actual run to make sure shape is correct inside Compute(). 2040 begin = begin.eval() 2041 end = end.eval() 2042 bbox_for_drawing = bbox_for_drawing.eval() 2043 2044 2045 class ResizeImagesTest(test_util.TensorFlowTestCase): 2046 2047 OPTIONS = [ 2048 image_ops.ResizeMethod.BILINEAR, image_ops.ResizeMethod.NEAREST_NEIGHBOR, 2049 image_ops.ResizeMethod.BICUBIC, image_ops.ResizeMethod.AREA 2050 ] 2051 2052 TYPES = [ 2053 np.uint8, np.int8, np.uint16, np.int16, np.int32, np.int64, np.float16, 2054 np.float32, np.float64 2055 ] 2056 2057 def _assertShapeInference(self, pre_shape, size, post_shape): 2058 # Try single image resize 2059 single_image = array_ops.placeholder(dtypes.float32, shape=pre_shape) 2060 y = image_ops.resize_images(single_image, size) 2061 self.assertEqual(y.get_shape().as_list(), post_shape) 2062 # Try batch images resize with known batch size 2063 images = array_ops.placeholder(dtypes.float32, shape=[99] + pre_shape) 2064 y = image_ops.resize_images(images, size) 2065 self.assertEqual(y.get_shape().as_list(), [99] + post_shape) 2066 # Try batch images resize with unknown batch size 2067 images = array_ops.placeholder(dtypes.float32, shape=[None] + pre_shape) 2068 y = image_ops.resize_images(images, size) 2069 self.assertEqual(y.get_shape().as_list(), [None] + post_shape) 2070 2071 def shouldRunOnGPU(self, opt, nptype): 2072 if (opt == image_ops.ResizeMethod.NEAREST_NEIGHBOR and 2073 nptype in [np.float32, np.float64]): 2074 return True 2075 else: 2076 return False 2077 2078 def testNoOp(self): 2079 img_shape = [1, 6, 4, 1] 2080 single_shape = [6, 4, 1] 2081 # This test is also conducted with int8, so 127 is the maximum 2082 # value that can be used. 2083 data = [ 2084 127, 127, 64, 64, 127, 127, 64, 64, 64, 64, 127, 127, 64, 64, 127, 127, 2085 50, 50, 100, 100, 50, 50, 100, 100 2086 ] 2087 target_height = 6 2088 target_width = 4 2089 2090 for nptype in self.TYPES: 2091 img_np = np.array(data, dtype=nptype).reshape(img_shape) 2092 2093 for opt in self.OPTIONS: 2094 with self.test_session(use_gpu=True) as sess: 2095 image = constant_op.constant(img_np, shape=img_shape) 2096 y = image_ops.resize_images(image, [target_height, target_width], opt) 2097 yshape = array_ops.shape(y) 2098 resized, newshape = sess.run([y, yshape]) 2099 self.assertAllEqual(img_shape, newshape) 2100 self.assertAllClose(resized, img_np, atol=1e-5) 2101 2102 # Resizing with a single image must leave the shape unchanged also. 2103 with self.test_session(use_gpu=True): 2104 img_single = img_np.reshape(single_shape) 2105 image = constant_op.constant(img_single, shape=single_shape) 2106 y = image_ops.resize_images(image, [target_height, target_width], 2107 self.OPTIONS[0]) 2108 yshape = array_ops.shape(y) 2109 newshape = yshape.eval() 2110 self.assertAllEqual(single_shape, newshape) 2111 2112 def testTensorArguments(self): 2113 img_shape = [1, 6, 4, 1] 2114 single_shape = [6, 4, 1] 2115 # This test is also conducted with int8, so 127 is the maximum 2116 # value that can be used. 2117 data = [ 2118 127, 127, 64, 64, 127, 127, 64, 64, 64, 64, 127, 127, 64, 64, 127, 127, 2119 50, 50, 100, 100, 50, 50, 100, 100 2120 ] 2121 new_size = array_ops.placeholder(dtypes.int32, shape=(2)) 2122 2123 img_np = np.array(data, dtype=np.uint8).reshape(img_shape) 2124 2125 for opt in self.OPTIONS: 2126 with self.test_session(use_gpu=True) as sess: 2127 image = constant_op.constant(img_np, shape=img_shape) 2128 y = image_ops.resize_images(image, new_size, opt) 2129 yshape = array_ops.shape(y) 2130 resized, newshape = sess.run([y, yshape], {new_size: [6, 4]}) 2131 self.assertAllEqual(img_shape, newshape) 2132 self.assertAllClose(resized, img_np, atol=1e-5) 2133 2134 # Resizing with a single image must leave the shape unchanged also. 2135 with self.test_session(use_gpu=True): 2136 img_single = img_np.reshape(single_shape) 2137 image = constant_op.constant(img_single, shape=single_shape) 2138 y = image_ops.resize_images(image, new_size, self.OPTIONS[0]) 2139 yshape = array_ops.shape(y) 2140 resized, newshape = sess.run([y, yshape], {new_size: [6, 4]}) 2141 self.assertAllEqual(single_shape, newshape) 2142 self.assertAllClose(resized, img_single, atol=1e-5) 2143 2144 # Incorrect shape. 2145 with self.assertRaises(ValueError): 2146 new_size = constant_op.constant(4) 2147 _ = image_ops.resize_images(image, new_size, 2148 image_ops.ResizeMethod.BILINEAR) 2149 with self.assertRaises(ValueError): 2150 new_size = constant_op.constant([4]) 2151 _ = image_ops.resize_images(image, new_size, 2152 image_ops.ResizeMethod.BILINEAR) 2153 with self.assertRaises(ValueError): 2154 new_size = constant_op.constant([1, 2, 3]) 2155 _ = image_ops.resize_images(image, new_size, 2156 image_ops.ResizeMethod.BILINEAR) 2157 2158 # Incorrect dtypes. 2159 with self.assertRaises(ValueError): 2160 new_size = constant_op.constant([6.0, 4]) 2161 _ = image_ops.resize_images(image, new_size, 2162 image_ops.ResizeMethod.BILINEAR) 2163 with self.assertRaises(ValueError): 2164 _ = image_ops.resize_images(image, [6, 4.0], 2165 image_ops.ResizeMethod.BILINEAR) 2166 with self.assertRaises(ValueError): 2167 _ = image_ops.resize_images(image, [None, 4], 2168 image_ops.ResizeMethod.BILINEAR) 2169 with self.assertRaises(ValueError): 2170 _ = image_ops.resize_images(image, [6, None], 2171 image_ops.ResizeMethod.BILINEAR) 2172 2173 def testReturnDtype(self): 2174 target_shapes = [[6, 4], [3, 2], [ 2175 array_ops.placeholder(dtypes.int32), 2176 array_ops.placeholder(dtypes.int32) 2177 ]] 2178 for nptype in self.TYPES: 2179 image = array_ops.placeholder(nptype, shape=[1, 6, 4, 1]) 2180 for opt in self.OPTIONS: 2181 for target_shape in target_shapes: 2182 y = image_ops.resize_images(image, target_shape, opt) 2183 if (opt == image_ops.ResizeMethod.NEAREST_NEIGHBOR or 2184 target_shape == image.shape[1:3]): 2185 expected_dtype = image.dtype 2186 else: 2187 expected_dtype = dtypes.float32 2188 self.assertEqual(y.dtype, expected_dtype) 2189 2190 def testSumTensor(self): 2191 img_shape = [1, 6, 4, 1] 2192 # This test is also conducted with int8, so 127 is the maximum 2193 # value that can be used. 2194 data = [ 2195 127, 127, 64, 64, 127, 127, 64, 64, 64, 64, 127, 127, 64, 64, 127, 127, 2196 50, 50, 100, 100, 50, 50, 100, 100 2197 ] 2198 # Test size where width is specified as a tensor which is a sum 2199 # of two tensors. 2200 width_1 = constant_op.constant(1) 2201 width_2 = constant_op.constant(3) 2202 width = math_ops.add(width_1, width_2) 2203 height = constant_op.constant(6) 2204 2205 img_np = np.array(data, dtype=np.uint8).reshape(img_shape) 2206 2207 for opt in self.OPTIONS: 2208 with self.test_session() as sess: 2209 image = constant_op.constant(img_np, shape=img_shape) 2210 y = image_ops.resize_images(image, [height, width], opt) 2211 yshape = array_ops.shape(y) 2212 resized, newshape = sess.run([y, yshape]) 2213 self.assertAllEqual(img_shape, newshape) 2214 self.assertAllClose(resized, img_np, atol=1e-5) 2215 2216 def testResizeDown(self): 2217 # This test is also conducted with int8, so 127 is the maximum 2218 # value that can be used. 2219 data = [ 2220 127, 127, 64, 64, 127, 127, 64, 64, 64, 64, 127, 127, 64, 64, 127, 127, 2221 50, 50, 100, 100, 50, 50, 100, 100 2222 ] 2223 expected_data = [127, 64, 64, 127, 50, 100] 2224 target_height = 3 2225 target_width = 2 2226 2227 # Test out 3-D and 4-D image shapes. 2228 img_shapes = [[1, 6, 4, 1], [6, 4, 1]] 2229 target_shapes = [[1, target_height, target_width, 1], 2230 [target_height, target_width, 1]] 2231 2232 for target_shape, img_shape in zip(target_shapes, img_shapes): 2233 2234 for nptype in self.TYPES: 2235 img_np = np.array(data, dtype=nptype).reshape(img_shape) 2236 2237 for opt in self.OPTIONS: 2238 if test.is_gpu_available() and self.shouldRunOnGPU(opt, nptype): 2239 with self.test_session(use_gpu=True): 2240 image = constant_op.constant(img_np, shape=img_shape) 2241 y = image_ops.resize_images(image, [target_height, target_width], 2242 opt) 2243 expected = np.array(expected_data).reshape(target_shape) 2244 resized = y.eval() 2245 self.assertAllClose(resized, expected, atol=1e-5) 2246 2247 def testResizeUpAlignCornersFalse(self): 2248 img_shape = [1, 3, 2, 1] 2249 data = [64, 32, 32, 64, 50, 100] 2250 target_height = 6 2251 target_width = 4 2252 expected_data = {} 2253 expected_data[image_ops.ResizeMethod.BILINEAR] = [ 2254 64.0, 48.0, 32.0, 32.0, 48.0, 48.0, 48.0, 48.0, 32.0, 48.0, 64.0, 64.0, 2255 41.0, 61.5, 82.0, 82.0, 50.0, 75.0, 100.0, 100.0, 50.0, 75.0, 100.0, 2256 100.0 2257 ] 2258 expected_data[image_ops.ResizeMethod.NEAREST_NEIGHBOR] = [ 2259 64.0, 64.0, 32.0, 32.0, 64.0, 64.0, 32.0, 32.0, 32.0, 32.0, 64.0, 64.0, 2260 32.0, 32.0, 64.0, 64.0, 50.0, 50.0, 100.0, 100.0, 50.0, 50.0, 100.0, 2261 100.0 2262 ] 2263 expected_data[image_ops.ResizeMethod.AREA] = [ 2264 64.0, 64.0, 32.0, 32.0, 64.0, 64.0, 32.0, 32.0, 32.0, 32.0, 64.0, 64.0, 2265 32.0, 32.0, 64.0, 64.0, 50.0, 50.0, 100.0, 100.0, 50.0, 50.0, 100.0, 2266 100.0 2267 ] 2268 2269 for nptype in self.TYPES: 2270 for opt in [ 2271 image_ops.ResizeMethod.BILINEAR, 2272 image_ops.ResizeMethod.NEAREST_NEIGHBOR, image_ops.ResizeMethod.AREA 2273 ]: 2274 with self.test_session(use_gpu=True): 2275 img_np = np.array(data, dtype=nptype).reshape(img_shape) 2276 image = constant_op.constant(img_np, shape=img_shape) 2277 y = image_ops.resize_images( 2278 image, [target_height, target_width], opt, align_corners=False) 2279 resized = y.eval() 2280 expected = np.array(expected_data[opt]).reshape( 2281 [1, target_height, target_width, 1]) 2282 self.assertAllClose(resized, expected, atol=1e-05) 2283 2284 def testResizeUpAlignCornersTrue(self): 2285 img_shape = [1, 3, 2, 1] 2286 data = [6, 3, 3, 6, 6, 9] 2287 target_height = 5 2288 target_width = 4 2289 expected_data = {} 2290 expected_data[image_ops.ResizeMethod.BILINEAR] = [ 2291 6.0, 5.0, 4.0, 3.0, 4.5, 4.5, 4.5, 4.5, 3.0, 4.0, 5.0, 6.0, 4.5, 5.5, 2292 6.5, 7.5, 6.0, 7.0, 8.0, 9.0 2293 ] 2294 expected_data[image_ops.ResizeMethod.NEAREST_NEIGHBOR] = [ 2295 6.0, 6.0, 3.0, 3.0, 3.0, 3.0, 6.0, 6.0, 3.0, 3.0, 6.0, 6.0, 6.0, 6.0, 2296 9.0, 9.0, 6.0, 6.0, 9.0, 9.0 2297 ] 2298 # TODO(b/37749740): Improve alignment of ResizeMethod.AREA when 2299 # align_corners=True. 2300 expected_data[image_ops.ResizeMethod.AREA] = [ 2301 6.0, 6.0, 6.0, 3.0, 6.0, 6.0, 6.0, 3.0, 3.0, 3.0, 3.0, 6.0, 3.0, 3.0, 2302 3.0, 6.0, 6.0, 6.0, 6.0, 9.0 2303 ] 2304 2305 for nptype in self.TYPES: 2306 for opt in [ 2307 image_ops.ResizeMethod.BILINEAR, 2308 image_ops.ResizeMethod.NEAREST_NEIGHBOR, image_ops.ResizeMethod.AREA 2309 ]: 2310 with self.test_session(use_gpu=True): 2311 img_np = np.array(data, dtype=nptype).reshape(img_shape) 2312 image = constant_op.constant(img_np, shape=img_shape) 2313 y = image_ops.resize_images( 2314 image, [target_height, target_width], opt, align_corners=True) 2315 resized = y.eval() 2316 expected = np.array(expected_data[opt]).reshape( 2317 [1, target_height, target_width, 1]) 2318 self.assertAllClose(resized, expected, atol=1e-05) 2319 2320 def testResizeUpBicubic(self): 2321 img_shape = [1, 6, 6, 1] 2322 data = [ 2323 128, 128, 64, 64, 128, 128, 64, 64, 64, 64, 128, 128, 64, 64, 128, 128, 2324 50, 50, 100, 100, 50, 50, 100, 100, 50, 50, 100, 100, 50, 50, 100, 100, 2325 50, 50, 100, 100 2326 ] 2327 img_np = np.array(data, dtype=np.uint8).reshape(img_shape) 2328 2329 target_height = 8 2330 target_width = 8 2331 expected_data = [ 2332 128, 135, 96, 55, 64, 114, 134, 128, 78, 81, 68, 52, 57, 118, 144, 136, 2333 55, 49, 79, 109, 103, 89, 83, 84, 74, 70, 95, 122, 115, 69, 49, 55, 100, 2334 105, 75, 43, 50, 89, 105, 100, 57, 54, 74, 96, 91, 65, 55, 58, 70, 69, 2335 75, 81, 80, 72, 69, 70, 105, 112, 75, 36, 45, 92, 111, 105 2336 ] 2337 2338 with self.test_session(use_gpu=True): 2339 image = constant_op.constant(img_np, shape=img_shape) 2340 y = image_ops.resize_images(image, [target_height, target_width], 2341 image_ops.ResizeMethod.BICUBIC) 2342 resized = y.eval() 2343 expected = np.array(expected_data).reshape( 2344 [1, target_height, target_width, 1]) 2345 self.assertAllClose(resized, expected, atol=1) 2346 2347 def testResizeDownArea(self): 2348 img_shape = [1, 6, 6, 1] 2349 data = [ 2350 128, 64, 32, 16, 8, 4, 4, 8, 16, 32, 64, 128, 128, 64, 32, 16, 8, 4, 5, 2351 10, 15, 20, 25, 30, 30, 25, 20, 15, 10, 5, 5, 10, 15, 20, 25, 30 2352 ] 2353 img_np = np.array(data, dtype=np.uint8).reshape(img_shape) 2354 2355 target_height = 4 2356 target_width = 4 2357 expected_data = [ 2358 73, 33, 23, 39, 73, 33, 23, 39, 14, 16, 19, 21, 14, 16, 19, 21 2359 ] 2360 2361 with self.test_session(use_gpu=True): 2362 image = constant_op.constant(img_np, shape=img_shape) 2363 y = image_ops.resize_images(image, [target_height, target_width], 2364 image_ops.ResizeMethod.AREA) 2365 expected = np.array(expected_data).reshape( 2366 [1, target_height, target_width, 1]) 2367 resized = y.eval() 2368 self.assertAllClose(resized, expected, atol=1) 2369 2370 def testCompareNearestNeighbor(self): 2371 if test.is_gpu_available(): 2372 input_shape = [1, 5, 6, 3] 2373 target_height = 8 2374 target_width = 12 2375 for nptype in [np.float32, np.float64]: 2376 for align_corners in [True, False]: 2377 img_np = np.arange( 2378 0, np.prod(input_shape), dtype=nptype).reshape(input_shape) 2379 with self.test_session(use_gpu=True): 2380 image = constant_op.constant(img_np, shape=input_shape) 2381 new_size = constant_op.constant([target_height, target_width]) 2382 out_op = image_ops.resize_images( 2383 image, 2384 new_size, 2385 image_ops.ResizeMethod.NEAREST_NEIGHBOR, 2386 align_corners=align_corners) 2387 gpu_val = out_op.eval() 2388 with self.test_session(use_gpu=False): 2389 image = constant_op.constant(img_np, shape=input_shape) 2390 new_size = constant_op.constant([target_height, target_width]) 2391 out_op = image_ops.resize_images( 2392 image, 2393 new_size, 2394 image_ops.ResizeMethod.NEAREST_NEIGHBOR, 2395 align_corners=align_corners) 2396 cpu_val = out_op.eval() 2397 self.assertAllClose(cpu_val, gpu_val, rtol=1e-5, atol=1e-5) 2398 2399 def testCompareBilinear(self): 2400 if test.is_gpu_available(): 2401 input_shape = [1, 5, 6, 3] 2402 target_height = 8 2403 target_width = 12 2404 for nptype in [np.float32, np.float64]: 2405 for align_corners in [True, False]: 2406 img_np = np.arange( 2407 0, np.prod(input_shape), dtype=nptype).reshape(input_shape) 2408 value = {} 2409 for use_gpu in [True, False]: 2410 with self.test_session(use_gpu=use_gpu): 2411 image = constant_op.constant(img_np, shape=input_shape) 2412 new_size = constant_op.constant([target_height, target_width]) 2413 out_op = image_ops.resize_images( 2414 image, 2415 new_size, 2416 image_ops.ResizeMethod.BILINEAR, 2417 align_corners=align_corners) 2418 value[use_gpu] = out_op.eval() 2419 self.assertAllClose(value[True], value[False], rtol=1e-5, atol=1e-5) 2420 2421 def testShapeInference(self): 2422 self._assertShapeInference([50, 60, 3], [55, 66], [55, 66, 3]) 2423 self._assertShapeInference([55, 66, 3], [55, 66], [55, 66, 3]) 2424 self._assertShapeInference([59, 69, 3], [55, 66], [55, 66, 3]) 2425 self._assertShapeInference([50, 69, 3], [55, 66], [55, 66, 3]) 2426 self._assertShapeInference([59, 60, 3], [55, 66], [55, 66, 3]) 2427 self._assertShapeInference([None, 60, 3], [55, 66], [55, 66, 3]) 2428 self._assertShapeInference([None, 66, 3], [55, 66], [55, 66, 3]) 2429 self._assertShapeInference([None, 69, 3], [55, 66], [55, 66, 3]) 2430 self._assertShapeInference([50, None, 3], [55, 66], [55, 66, 3]) 2431 self._assertShapeInference([55, None, 3], [55, 66], [55, 66, 3]) 2432 self._assertShapeInference([59, None, 3], [55, 66], [55, 66, 3]) 2433 self._assertShapeInference([None, None, 3], [55, 66], [55, 66, 3]) 2434 self._assertShapeInference([50, 60, None], [55, 66], [55, 66, None]) 2435 self._assertShapeInference([55, 66, None], [55, 66], [55, 66, None]) 2436 self._assertShapeInference([59, 69, None], [55, 66], [55, 66, None]) 2437 self._assertShapeInference([50, 69, None], [55, 66], [55, 66, None]) 2438 self._assertShapeInference([59, 60, None], [55, 66], [55, 66, None]) 2439 self._assertShapeInference([None, None, None], [55, 66], [55, 66, None]) 2440 2441 def testNameScope(self): 2442 img_shape = [1, 3, 2, 1] 2443 with self.test_session(use_gpu=True): 2444 single_image = array_ops.placeholder(dtypes.float32, shape=[50, 60, 3]) 2445 y = image_ops.resize_images(single_image, [55, 66]) 2446 self.assertTrue(y.op.name.startswith("resize_images")) 2447 2448 2449 class ResizeImageWithCropOrPadTest(test_util.TensorFlowTestCase): 2450 2451 def _ResizeImageWithCropOrPad(self, x, target_height, target_width, 2452 use_tensor_inputs): 2453 if use_tensor_inputs: 2454 target_height = ops.convert_to_tensor(target_height) 2455 target_width = ops.convert_to_tensor(target_width) 2456 x_tensor = array_ops.placeholder(x.dtype, shape=[None] * x.ndim) 2457 feed_dict = {x_tensor: x} 2458 else: 2459 x_tensor = x 2460 feed_dict = {} 2461 2462 y = image_ops.resize_image_with_crop_or_pad(x_tensor, target_height, 2463 target_width) 2464 if not use_tensor_inputs: 2465 self.assertTrue(y.get_shape().is_fully_defined()) 2466 2467 with self.test_session(use_gpu=True): 2468 return y.eval(feed_dict=feed_dict) 2469 2470 def _assertReturns(self, 2471 x, 2472 x_shape, 2473 y, 2474 y_shape, 2475 use_tensor_inputs_options=None): 2476 use_tensor_inputs_options = use_tensor_inputs_options or [False, True] 2477 target_height, target_width, _ = y_shape 2478 x = np.array(x).reshape(x_shape) 2479 y = np.array(y).reshape(y_shape) 2480 2481 for use_tensor_inputs in use_tensor_inputs_options: 2482 y_tf = self._ResizeImageWithCropOrPad(x, target_height, target_width, 2483 use_tensor_inputs) 2484 self.assertAllClose(y, y_tf) 2485 2486 def _assertRaises(self, 2487 x, 2488 x_shape, 2489 target_height, 2490 target_width, 2491 err_msg, 2492 use_tensor_inputs_options=None): 2493 use_tensor_inputs_options = use_tensor_inputs_options or [False, True] 2494 x = np.array(x).reshape(x_shape) 2495 2496 for use_tensor_inputs in use_tensor_inputs_options: 2497 try: 2498 self._ResizeImageWithCropOrPad(x, target_height, target_width, 2499 use_tensor_inputs) 2500 except Exception as e: 2501 if err_msg not in str(e): 2502 raise 2503 else: 2504 raise AssertionError("Exception not raised: %s" % err_msg) 2505 2506 def _assertShapeInference(self, pre_shape, height, width, post_shape): 2507 image = array_ops.placeholder(dtypes.float32, shape=pre_shape) 2508 y = image_ops.resize_image_with_crop_or_pad(image, height, width) 2509 self.assertEqual(y.get_shape().as_list(), post_shape) 2510 2511 def testNoOp(self): 2512 x_shape = [10, 10, 10] 2513 x = np.random.uniform(size=x_shape) 2514 2515 self._assertReturns(x, x_shape, x, x_shape) 2516 2517 def testPad(self): 2518 # Pad even along col. 2519 x = [1, 2, 3, 4, 5, 6, 7, 8] 2520 x_shape = [2, 4, 1] 2521 2522 y = [0, 1, 2, 3, 4, 0, 0, 5, 6, 7, 8, 0] 2523 y_shape = [2, 6, 1] 2524 2525 self._assertReturns(x, x_shape, y, y_shape) 2526 2527 # Pad odd along col. 2528 x = [1, 2, 3, 4, 5, 6, 7, 8] 2529 x_shape = [2, 4, 1] 2530 2531 y = [0, 1, 2, 3, 4, 0, 0, 0, 5, 6, 7, 8, 0, 0] 2532 y_shape = [2, 7, 1] 2533 2534 self._assertReturns(x, x_shape, y, y_shape) 2535 2536 # Pad even along row. 2537 x = [1, 2, 3, 4, 5, 6, 7, 8] 2538 x_shape = [2, 4, 1] 2539 2540 y = [0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0] 2541 y_shape = [4, 4, 1] 2542 2543 self._assertReturns(x, x_shape, y, y_shape) 2544 2545 # Pad odd along row. 2546 x = [1, 2, 3, 4, 5, 6, 7, 8] 2547 x_shape = [2, 4, 1] 2548 2549 y = [0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0] 2550 y_shape = [5, 4, 1] 2551 2552 self._assertReturns(x, x_shape, y, y_shape) 2553 2554 def testCrop(self): 2555 # Crop even along col. 2556 x = [1, 2, 3, 4, 5, 6, 7, 8] 2557 x_shape = [2, 4, 1] 2558 2559 y = [2, 3, 6, 7] 2560 y_shape = [2, 2, 1] 2561 2562 self._assertReturns(x, x_shape, y, y_shape) 2563 2564 # Crop odd along col. 2565 x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 2566 x_shape = [2, 6, 1] 2567 2568 y = [2, 3, 4, 8, 9, 10] 2569 y_shape = [2, 3, 1] 2570 2571 self._assertReturns(x, x_shape, y, y_shape) 2572 2573 # Crop even along row. 2574 x = [1, 2, 3, 4, 5, 6, 7, 8] 2575 x_shape = [4, 2, 1] 2576 2577 y = [3, 4, 5, 6] 2578 y_shape = [2, 2, 1] 2579 2580 self._assertReturns(x, x_shape, y, y_shape) 2581 2582 # Crop odd along row. 2583 x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] 2584 x_shape = [8, 2, 1] 2585 2586 y = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 2587 y_shape = [5, 2, 1] 2588 2589 self._assertReturns(x, x_shape, y, y_shape) 2590 2591 def testCropAndPad(self): 2592 # Pad along row but crop along col. 2593 x = [1, 2, 3, 4, 5, 6, 7, 8] 2594 x_shape = [2, 4, 1] 2595 2596 y = [0, 0, 2, 3, 6, 7, 0, 0] 2597 y_shape = [4, 2, 1] 2598 2599 self._assertReturns(x, x_shape, y, y_shape) 2600 2601 # Crop along row but pad along col. 2602 x = [1, 2, 3, 4, 5, 6, 7, 8] 2603 x_shape = [4, 2, 1] 2604 2605 y = [0, 3, 4, 0, 0, 5, 6, 0] 2606 y_shape = [2, 4, 1] 2607 2608 self._assertReturns(x, x_shape, y, y_shape) 2609 2610 def testShapeInference(self): 2611 self._assertShapeInference([50, 60, 3], 55, 66, [55, 66, 3]) 2612 self._assertShapeInference([55, 66, 3], 55, 66, [55, 66, 3]) 2613 self._assertShapeInference([59, 69, 3], 55, 66, [55, 66, 3]) 2614 self._assertShapeInference([50, 69, 3], 55, 66, [55, 66, 3]) 2615 self._assertShapeInference([59, 60, 3], 55, 66, [55, 66, 3]) 2616 self._assertShapeInference([None, 60, 3], 55, 66, [55, 66, 3]) 2617 self._assertShapeInference([None, 66, 3], 55, 66, [55, 66, 3]) 2618 self._assertShapeInference([None, 69, 3], 55, 66, [55, 66, 3]) 2619 self._assertShapeInference([50, None, 3], 55, 66, [55, 66, 3]) 2620 self._assertShapeInference([55, None, 3], 55, 66, [55, 66, 3]) 2621 self._assertShapeInference([59, None, 3], 55, 66, [55, 66, 3]) 2622 self._assertShapeInference([None, None, 3], 55, 66, [55, 66, 3]) 2623 self._assertShapeInference([50, 60, None], 55, 66, [55, 66, None]) 2624 self._assertShapeInference([55, 66, None], 55, 66, [55, 66, None]) 2625 self._assertShapeInference([59, 69, None], 55, 66, [55, 66, None]) 2626 self._assertShapeInference([50, 69, None], 55, 66, [55, 66, None]) 2627 self._assertShapeInference([59, 60, None], 55, 66, [55, 66, None]) 2628 self._assertShapeInference([None, None, None], 55, 66, [55, 66, None]) 2629 self._assertShapeInference(None, 55, 66, [55, 66, None]) 2630 2631 def testNon3DInput(self): 2632 # Input image is not 3D 2633 x = [0] * 15 2634 target_height, target_width = [4, 4] 2635 2636 for x_shape in ([3, 5],): 2637 self._assertRaises(x, x_shape, target_height, target_width, 2638 "'image' must have either 3 or 4 dimensions.") 2639 2640 for x_shape in ([1, 3, 5, 1, 1],): 2641 self._assertRaises(x, x_shape, target_height, target_width, 2642 "'image' must have either 3 or 4 dimensions.") 2643 2644 def testZeroLengthInput(self): 2645 # Input image has 0-length dimension(s). 2646 target_height, target_width = [1, 1] 2647 x = [] 2648 2649 for x_shape in ([0, 2, 2], [2, 0, 2], [2, 2, 0]): 2650 self._assertRaises( 2651 x, 2652 x_shape, 2653 target_height, 2654 target_width, 2655 "all dims of 'image.shape' must be > 0", 2656 use_tensor_inputs_options=[False]) 2657 2658 # The orignal error message does not contain back slashes. However, they 2659 # are added by either the assert op or the runtime. If this behavior 2660 # changes in the future, the match string will also needs to be changed. 2661 self._assertRaises( 2662 x, 2663 x_shape, 2664 target_height, 2665 target_width, 2666 "all dims of \\'image.shape\\' must be > 0", 2667 use_tensor_inputs_options=[True]) 2668 2669 def testBadParams(self): 2670 x_shape = [4, 4, 1] 2671 x = np.zeros(x_shape) 2672 2673 # target_height <= 0 2674 target_height, target_width = [0, 5] 2675 self._assertRaises(x, x_shape, target_height, target_width, 2676 "target_height must be > 0") 2677 2678 # target_width <= 0 2679 target_height, target_width = [5, 0] 2680 self._assertRaises(x, x_shape, target_height, target_width, 2681 "target_width must be > 0") 2682 2683 def testNameScope(self): 2684 image = array_ops.placeholder(dtypes.float32, shape=[50, 60, 3]) 2685 y = image_ops.resize_image_with_crop_or_pad(image, 55, 66) 2686 self.assertTrue(y.op.name.startswith("resize_image_with_crop_or_pad")) 2687 2688 2689 def _SimpleColorRamp(): 2690 """Build a simple color ramp RGB image.""" 2691 w, h = 256, 200 2692 i = np.arange(h)[:, None] 2693 j = np.arange(w) 2694 image = np.empty((h, w, 3), dtype=np.uint8) 2695 image[:, :, 0] = i 2696 image[:, :, 1] = j 2697 image[:, :, 2] = (i + j) >> 1 2698 return image 2699 2700 2701 class JpegTest(test_util.TensorFlowTestCase): 2702 2703 # TODO(irving): Add self.assertAverageLess or similar to test_util 2704 def averageError(self, image0, image1): 2705 self.assertEqual(image0.shape, image1.shape) 2706 image0 = image0.astype(int) # Avoid overflow 2707 return np.abs(image0 - image1).sum() / np.prod(image0.shape) 2708 2709 def testExisting(self): 2710 # Read a real jpeg and verify shape 2711 path = ("tensorflow/core/lib/jpeg/testdata/" 2712 "jpeg_merge_test1.jpg") 2713 with self.test_session(use_gpu=True) as sess: 2714 jpeg0 = io_ops.read_file(path) 2715 image0 = image_ops.decode_jpeg(jpeg0) 2716 image1 = image_ops.decode_jpeg(image_ops.encode_jpeg(image0)) 2717 jpeg0, image0, image1 = sess.run([jpeg0, image0, image1]) 2718 self.assertEqual(len(jpeg0), 3771) 2719 self.assertEqual(image0.shape, (256, 128, 3)) 2720 self.assertLess(self.averageError(image0, image1), 1.4) 2721 2722 def testCmyk(self): 2723 # Confirm that CMYK reads in as RGB 2724 base = "tensorflow/core/lib/jpeg/testdata" 2725 rgb_path = os.path.join(base, "jpeg_merge_test1.jpg") 2726 cmyk_path = os.path.join(base, "jpeg_merge_test1_cmyk.jpg") 2727 shape = 256, 128, 3 2728 for channels in 3, 0: 2729 with self.test_session(use_gpu=True) as sess: 2730 rgb = image_ops.decode_jpeg( 2731 io_ops.read_file(rgb_path), channels=channels) 2732 cmyk = image_ops.decode_jpeg( 2733 io_ops.read_file(cmyk_path), channels=channels) 2734 rgb, cmyk = sess.run([rgb, cmyk]) 2735 self.assertEqual(rgb.shape, shape) 2736 self.assertEqual(cmyk.shape, shape) 2737 error = self.averageError(rgb, cmyk) 2738 self.assertLess(error, 4) 2739 2740 def testCropAndDecodeJpeg(self): 2741 with self.test_session() as sess: 2742 # Encode it, then decode it, then encode it 2743 base = "tensorflow/core/lib/jpeg/testdata" 2744 jpeg0 = io_ops.read_file(os.path.join(base, "jpeg_merge_test1.jpg")) 2745 2746 h, w, _ = 256, 128, 3 2747 crop_windows = [[0, 0, 5, 5], [0, 0, 5, w], [0, 0, h, 5], 2748 [h - 6, w - 5, 6, 5], [6, 5, 15, 10], [0, 0, h, w]] 2749 for crop_window in crop_windows: 2750 # Explicit two stages: decode + crop. 2751 image1 = image_ops.decode_jpeg(jpeg0) 2752 y, x, h, w = crop_window 2753 image1_crop = image_ops.crop_to_bounding_box(image1, y, x, h, w) 2754 2755 # Combined decode+crop. 2756 image2 = image_ops.decode_and_crop_jpeg(jpeg0, crop_window) 2757 2758 # Combined decode+crop should have the same shape inference 2759 self.assertAllEqual(image1_crop.get_shape().as_list(), 2760 image2.get_shape().as_list()) 2761 2762 # CropAndDecode should be equal to DecodeJpeg+Crop. 2763 image1_crop, image2 = sess.run([image1_crop, image2]) 2764 self.assertAllEqual(image1_crop, image2) 2765 2766 def testCropAndDecodeJpegWithInvalidCropWindow(self): 2767 with self.test_session() as sess: 2768 # Encode it, then decode it, then encode it 2769 base = "tensorflow/core/lib/jpeg/testdata" 2770 jpeg0 = io_ops.read_file(os.path.join(base, "jpeg_merge_test1.jpg")) 2771 2772 h, w, _ = 256, 128, 3 2773 # Invalid crop windows. 2774 crop_windows = [[-1, 11, 11, 11], [11, -1, 11, 11], [11, 11, -1, 11], 2775 [11, 11, 11, -1], [11, 11, 0, 11], [11, 11, 11, 0], 2776 [0, 0, h + 1, w], [0, 0, h, w + 1]] 2777 for crop_window in crop_windows: 2778 result = image_ops.decode_and_crop_jpeg(jpeg0, crop_window) 2779 with self.assertRaisesWithPredicateMatch( 2780 errors.InvalidArgumentError, 2781 lambda e: "Invalid JPEG data or crop window" in str(e)): 2782 sess.run(result) 2783 2784 def testSynthetic(self): 2785 with self.test_session(use_gpu=True) as sess: 2786 # Encode it, then decode it, then encode it 2787 image0 = constant_op.constant(_SimpleColorRamp()) 2788 jpeg0 = image_ops.encode_jpeg(image0) 2789 image1 = image_ops.decode_jpeg(jpeg0, dct_method="INTEGER_ACCURATE") 2790 image2 = image_ops.decode_jpeg( 2791 image_ops.encode_jpeg(image1), dct_method="INTEGER_ACCURATE") 2792 jpeg0, image0, image1, image2 = sess.run([jpeg0, image0, image1, image2]) 2793 2794 # The decoded-encoded image should be similar to the input 2795 self.assertLess(self.averageError(image0, image1), 0.6) 2796 2797 # We should be very close to a fixpoint 2798 self.assertLess(self.averageError(image1, image2), 0.02) 2799 2800 # Smooth ramps compress well (input size is 153600) 2801 self.assertGreaterEqual(len(jpeg0), 5000) 2802 self.assertLessEqual(len(jpeg0), 6000) 2803 2804 def testSyntheticFasterAlgorithm(self): 2805 with self.test_session(use_gpu=True) as sess: 2806 # Encode it, then decode it, then encode it 2807 image0 = constant_op.constant(_SimpleColorRamp()) 2808 jpeg0 = image_ops.encode_jpeg(image0) 2809 image1 = image_ops.decode_jpeg(jpeg0, dct_method="INTEGER_FAST") 2810 image2 = image_ops.decode_jpeg( 2811 image_ops.encode_jpeg(image1), dct_method="INTEGER_FAST") 2812 jpeg0, image0, image1, image2 = sess.run([jpeg0, image0, image1, image2]) 2813 2814 # The decoded-encoded image should be similar to the input, but 2815 # note this is worse than the slower algorithm because it is 2816 # less accurate. 2817 self.assertLess(self.averageError(image0, image1), 0.95) 2818 2819 # Repeated compression / decompression will have a higher error 2820 # with a lossier algorithm. 2821 self.assertLess(self.averageError(image1, image2), 1.05) 2822 2823 # Smooth ramps compress well (input size is 153600) 2824 self.assertGreaterEqual(len(jpeg0), 5000) 2825 self.assertLessEqual(len(jpeg0), 6000) 2826 2827 def testDefaultDCTMethodIsIntegerFast(self): 2828 with self.test_session(use_gpu=True) as sess: 2829 # Compare decoding with both dct_option=INTEGER_FAST and 2830 # default. They should be the same. 2831 image0 = constant_op.constant(_SimpleColorRamp()) 2832 jpeg0 = image_ops.encode_jpeg(image0) 2833 image1 = image_ops.decode_jpeg(jpeg0, dct_method="INTEGER_FAST") 2834 image2 = image_ops.decode_jpeg(jpeg0) 2835 image1, image2 = sess.run([image1, image2]) 2836 2837 # The images should be the same. 2838 self.assertAllClose(image1, image2) 2839 2840 def testShape(self): 2841 with self.test_session(use_gpu=True) as sess: 2842 jpeg = constant_op.constant("nonsense") 2843 for channels in 0, 1, 3: 2844 image = image_ops.decode_jpeg(jpeg, channels=channels) 2845 self.assertEqual(image.get_shape().as_list(), 2846 [None, None, channels or None]) 2847 2848 def testExtractJpegShape(self): 2849 # Read a real jpeg and verify shape. 2850 path = ("tensorflow/core/lib/jpeg/testdata/" 2851 "jpeg_merge_test1.jpg") 2852 with self.test_session(use_gpu=True) as sess: 2853 jpeg = io_ops.read_file(path) 2854 # Extract shape without decoding. 2855 [image_shape] = sess.run([image_ops.extract_jpeg_shape(jpeg)]) 2856 self.assertEqual(image_shape.tolist(), [256, 128, 3]) 2857 2858 def testExtractJpegShapeforCmyk(self): 2859 # Read a cmyk jpeg image, and verify its shape. 2860 path = ("tensorflow/core/lib/jpeg/testdata/" 2861 "jpeg_merge_test1_cmyk.jpg") 2862 with self.test_session(use_gpu=True) as sess: 2863 jpeg = io_ops.read_file(path) 2864 [image_shape] = sess.run([image_ops.extract_jpeg_shape(jpeg)]) 2865 # Cmyk jpeg image has 4 channels. 2866 self.assertEqual(image_shape.tolist(), [256, 128, 4]) 2867 2868 2869 class PngTest(test_util.TensorFlowTestCase): 2870 2871 def testExisting(self): 2872 # Read some real PNGs, converting to different channel numbers 2873 prefix = "tensorflow/core/lib/png/testdata/" 2874 inputs = (1, "lena_gray.png"), (4, "lena_rgba.png") 2875 for channels_in, filename in inputs: 2876 for channels in 0, 1, 3, 4: 2877 with self.test_session(use_gpu=True) as sess: 2878 png0 = io_ops.read_file(prefix + filename) 2879 image0 = image_ops.decode_png(png0, channels=channels) 2880 png0, image0 = sess.run([png0, image0]) 2881 self.assertEqual(image0.shape, (26, 51, channels or channels_in)) 2882 if channels == channels_in: 2883 image1 = image_ops.decode_png(image_ops.encode_png(image0)) 2884 self.assertAllEqual(image0, image1.eval()) 2885 2886 def testSynthetic(self): 2887 with self.test_session(use_gpu=True) as sess: 2888 # Encode it, then decode it 2889 image0 = constant_op.constant(_SimpleColorRamp()) 2890 png0 = image_ops.encode_png(image0, compression=7) 2891 image1 = image_ops.decode_png(png0) 2892 png0, image0, image1 = sess.run([png0, image0, image1]) 2893 2894 # PNG is lossless 2895 self.assertAllEqual(image0, image1) 2896 2897 # Smooth ramps compress well, but not too well 2898 self.assertGreaterEqual(len(png0), 400) 2899 self.assertLessEqual(len(png0), 750) 2900 2901 def testSyntheticUint16(self): 2902 with self.test_session(use_gpu=True) as sess: 2903 # Encode it, then decode it 2904 image0 = constant_op.constant(_SimpleColorRamp(), dtype=dtypes.uint16) 2905 png0 = image_ops.encode_png(image0, compression=7) 2906 image1 = image_ops.decode_png(png0, dtype=dtypes.uint16) 2907 png0, image0, image1 = sess.run([png0, image0, image1]) 2908 2909 # PNG is lossless 2910 self.assertAllEqual(image0, image1) 2911 2912 # Smooth ramps compress well, but not too well 2913 self.assertGreaterEqual(len(png0), 800) 2914 self.assertLessEqual(len(png0), 1500) 2915 2916 def testSyntheticTwoChannel(self): 2917 with self.test_session(use_gpu=True) as sess: 2918 # Strip the b channel from an rgb image to get a two-channel image. 2919 gray_alpha = _SimpleColorRamp()[:, :, 0:2] 2920 image0 = constant_op.constant(gray_alpha) 2921 png0 = image_ops.encode_png(image0, compression=7) 2922 image1 = image_ops.decode_png(png0) 2923 png0, image0, image1 = sess.run([png0, image0, image1]) 2924 self.assertEqual(2, image0.shape[-1]) 2925 self.assertAllEqual(image0, image1) 2926 2927 def testSyntheticTwoChannelUint16(self): 2928 with self.test_session(use_gpu=True) as sess: 2929 # Strip the b channel from an rgb image to get a two-channel image. 2930 gray_alpha = _SimpleColorRamp()[:, :, 0:2] 2931 image0 = constant_op.constant(gray_alpha, dtype=dtypes.uint16) 2932 png0 = image_ops.encode_png(image0, compression=7) 2933 image1 = image_ops.decode_png(png0, dtype=dtypes.uint16) 2934 png0, image0, image1 = sess.run([png0, image0, image1]) 2935 self.assertEqual(2, image0.shape[-1]) 2936 self.assertAllEqual(image0, image1) 2937 2938 def testShape(self): 2939 with self.test_session(use_gpu=True): 2940 png = constant_op.constant("nonsense") 2941 for channels in 0, 1, 3: 2942 image = image_ops.decode_png(png, channels=channels) 2943 self.assertEqual(image.get_shape().as_list(), 2944 [None, None, channels or None]) 2945 2946 2947 class GifTest(test_util.TensorFlowTestCase): 2948 2949 def _testValid(self, filename): 2950 # Read some real GIFs 2951 prefix = "tensorflow/core/lib/gif/testdata/" 2952 WIDTH = 20 2953 HEIGHT = 40 2954 STRIDE = 5 2955 shape = (12, HEIGHT, WIDTH, 3) 2956 2957 with self.test_session(use_gpu=True) as sess: 2958 gif0 = io_ops.read_file(prefix + filename) 2959 image0 = image_ops.decode_gif(gif0) 2960 gif0, image0 = sess.run([gif0, image0]) 2961 2962 self.assertEqual(image0.shape, shape) 2963 2964 for frame_idx, frame in enumerate(image0): 2965 gt = np.zeros(shape[1:], dtype=np.uint8) 2966 start = frame_idx * STRIDE 2967 end = (frame_idx + 1) * STRIDE 2968 print(frame_idx) 2969 if end <= WIDTH: 2970 gt[:, start:end, :] = 255 2971 else: 2972 start -= WIDTH 2973 end -= WIDTH 2974 gt[start:end, :, :] = 255 2975 2976 self.assertAllClose(frame, gt) 2977 2978 def testValid(self): 2979 self._testValid("scan.gif") 2980 self._testValid("optimized.gif") 2981 2982 def testShape(self): 2983 with self.test_session(use_gpu=True) as sess: 2984 gif = constant_op.constant("nonsense") 2985 image = image_ops.decode_gif(gif) 2986 self.assertEqual(image.get_shape().as_list(), [None, None, None, 3]) 2987 2988 2989 class ConvertImageTest(test_util.TensorFlowTestCase): 2990 2991 def _convert(self, original, original_dtype, output_dtype, expected): 2992 x_np = np.array(original, dtype=original_dtype.as_numpy_dtype()) 2993 y_np = np.array(expected, dtype=output_dtype.as_numpy_dtype()) 2994 2995 with self.test_session(use_gpu=True): 2996 image = constant_op.constant(x_np) 2997 y = image_ops.convert_image_dtype(image, output_dtype) 2998 self.assertTrue(y.dtype == output_dtype) 2999 self.assertAllClose(y.eval(), y_np, atol=1e-5) 3000 if output_dtype in [ 3001 dtypes.float32, dtypes.float64, dtypes.int32, dtypes.int64 3002 ]: 3003 y_saturate = image_ops.convert_image_dtype( 3004 image, output_dtype, saturate=True) 3005 self.assertTrue(y_saturate.dtype == output_dtype) 3006 self.assertAllClose(y_saturate.eval(), y_np, atol=1e-5) 3007 3008 def testNoConvert(self): 3009 # Make sure converting to the same data type creates only an identity op 3010 with self.test_session(use_gpu=True): 3011 image = constant_op.constant([1], dtype=dtypes.uint8) 3012 image_ops.convert_image_dtype(image, dtypes.uint8) 3013 y = image_ops.convert_image_dtype(image, dtypes.uint8) 3014 self.assertEquals(y.op.type, "Identity") 3015 self.assertEquals(y.op.inputs[0], image) 3016 3017 def testConvertBetweenInteger(self): 3018 # Make sure converting to between integer types scales appropriately 3019 with self.test_session(use_gpu=True): 3020 self._convert([0, 255], dtypes.uint8, dtypes.int16, [0, 255 * 128]) 3021 self._convert([0, 32767], dtypes.int16, dtypes.uint8, [0, 255]) 3022 self._convert([0, 2**32], dtypes.int64, dtypes.int32, [0, 1]) 3023 self._convert([0, 1], dtypes.int32, dtypes.int64, [0, 2**32]) 3024 3025 def testConvertBetweenFloat(self): 3026 # Make sure converting to between float types does nothing interesting 3027 with self.test_session(use_gpu=True): 3028 self._convert([-1.0, 0, 1.0, 200000], dtypes.float32, dtypes.float64, 3029 [-1.0, 0, 1.0, 200000]) 3030 self._convert([-1.0, 0, 1.0, 200000], dtypes.float64, dtypes.float32, 3031 [-1.0, 0, 1.0, 200000]) 3032 3033 def testConvertBetweenIntegerAndFloat(self): 3034 # Make sure converting from and to a float type scales appropriately 3035 with self.test_session(use_gpu=True): 3036 self._convert([0, 1, 255], dtypes.uint8, dtypes.float32, 3037 [0, 1.0 / 255.0, 1]) 3038 self._convert([0, 1.1 / 255.0, 1], dtypes.float32, dtypes.uint8, 3039 [0, 1, 255]) 3040 3041 def testConvertBetweenInt16AndInt8(self): 3042 with self.test_session(use_gpu=True): 3043 # uint8, uint16 3044 self._convert([0, 255 * 256], dtypes.uint16, dtypes.uint8, [0, 255]) 3045 self._convert([0, 255], dtypes.uint8, dtypes.uint16, [0, 255 * 256]) 3046 # int8, uint16 3047 self._convert([0, 127 * 2 * 256], dtypes.uint16, dtypes.int8, [0, 127]) 3048 self._convert([0, 127], dtypes.int8, dtypes.uint16, [0, 127 * 2 * 256]) 3049 # int16, uint16 3050 self._convert([0, 255 * 256], dtypes.uint16, dtypes.int16, [0, 255 * 128]) 3051 self._convert([0, 255 * 128], dtypes.int16, dtypes.uint16, [0, 255 * 256]) 3052 3053 3054 class TotalVariationTest(test_util.TensorFlowTestCase): 3055 """Tests the function total_variation() in image_ops. 3056 3057 We test a few small handmade examples, as well as 3058 some larger examples using an equivalent numpy 3059 implementation of the total_variation() function. 3060 3061 We do NOT test for overflows and invalid / edge-case arguments. 3062 """ 3063 3064 def _test(self, x_np, y_np): 3065 """Test that the TensorFlow implementation of 3066 total_variation(x_np) calculates the values in y_np. 3067 3068 Note that these may be float-numbers so we only test 3069 for approximate equality within some narrow error-bound. 3070 """ 3071 3072 # Create a TensorFlow session. 3073 with self.test_session(use_gpu=True): 3074 # Add a constant to the TensorFlow graph that holds the input. 3075 x_tf = constant_op.constant(x_np, shape=x_np.shape) 3076 3077 # Add ops for calculating the total variation using TensorFlow. 3078 y = image_ops.total_variation(images=x_tf) 3079 3080 # Run the TensorFlow session to calculate the result. 3081 y_tf = y.eval() 3082 3083 # Assert that the results are as expected within 3084 # some small error-bound in case they are float-values. 3085 self.assertAllClose(y_tf, y_np) 3086 3087 def _total_variation_np(self, x_np): 3088 """Calculate the total variation of x_np using numpy. 3089 This implements the same function as TensorFlow but 3090 using numpy instead. 3091 3092 Args: 3093 x_np: Numpy array with 3 or 4 dimensions. 3094 """ 3095 3096 dim = len(x_np.shape) 3097 3098 if dim == 3: 3099 # Calculate differences for neighboring pixel-values using slices. 3100 dif1 = x_np[1:, :, :] - x_np[:-1, :, :] 3101 dif2 = x_np[:, 1:, :] - x_np[:, :-1, :] 3102 3103 # Sum for all axis. 3104 sum_axis = None 3105 elif dim == 4: 3106 # Calculate differences for neighboring pixel-values using slices. 3107 dif1 = x_np[:, 1:, :, :] - x_np[:, :-1, :, :] 3108 dif2 = x_np[:, :, 1:, :] - x_np[:, :, :-1, :] 3109 3110 # Only sum for the last 3 axis. 3111 sum_axis = (1, 2, 3) 3112 else: 3113 # This should not occur in this test-code. 3114 pass 3115 3116 tot_var = np.sum(np.abs(dif1), axis=sum_axis) + \ 3117 np.sum(np.abs(dif2), axis=sum_axis) 3118 3119 return tot_var 3120 3121 def _test_tensorflow_vs_numpy(self, x_np): 3122 """Test the TensorFlow implementation against a numpy implementation. 3123 3124 Args: 3125 x_np: Numpy array with 3 or 4 dimensions. 3126 """ 3127 3128 # Calculate the y-values using the numpy implementation. 3129 y_np = self._total_variation_np(x_np) 3130 3131 self._test(x_np, y_np) 3132 3133 def _generateArray(self, shape): 3134 """Generate an array of the given shape for use in testing. 3135 The numbers are calculated as the cumulative sum, which 3136 causes the difference between neighboring numbers to vary.""" 3137 3138 # Flattened length of the array. 3139 flat_len = np.prod(shape) 3140 3141 a = np.array(range(flat_len), dtype=int) 3142 a = np.cumsum(a) 3143 a = a.reshape(shape) 3144 3145 return a 3146 3147 def testTotalVariationNumpy(self): 3148 """Test the TensorFlow implementation against a numpy implementation. 3149 The two implementations are very similar so it is possible that both 3150 have the same bug, which would not be detected by this test. It is 3151 therefore necessary to test with manually crafted data as well.""" 3152 3153 # Generate a test-array. 3154 # This is an 'image' with 100x80 pixels and 3 color channels. 3155 a = self._generateArray(shape=(100, 80, 3)) 3156 3157 # Test the TensorFlow implementation vs. numpy implementation. 3158 # We use a numpy implementation to check the results that are 3159 # calculated using TensorFlow are correct. 3160 self._test_tensorflow_vs_numpy(a) 3161 self._test_tensorflow_vs_numpy(a + 1) 3162 self._test_tensorflow_vs_numpy(-a) 3163 self._test_tensorflow_vs_numpy(1.1 * a) 3164 3165 # Expand to a 4-dim array. 3166 b = a[np.newaxis, :] 3167 3168 # Combine several variations of the image into a single 4-dim array. 3169 multi = np.vstack((b, b + 1, -b, 1.1 * b)) 3170 3171 # Test that the TensorFlow function can also handle 4-dim arrays. 3172 self._test_tensorflow_vs_numpy(multi) 3173 3174 def testTotalVariationHandmade(self): 3175 """Test the total variation for a few handmade examples.""" 3176 3177 # We create an image that is 2x2 pixels with 3 color channels. 3178 # The image is very small so we can check the result by hand. 3179 3180 # Red color channel. 3181 # The following are the sum of absolute differences between the pixels. 3182 # sum row dif = (4-1) + (7-2) = 3 + 5 = 8 3183 # sum col dif = (2-1) + (7-4) = 1 + 3 = 4 3184 r = [[1, 2], [4, 7]] 3185 3186 # Blue color channel. 3187 # sum row dif = 18 + 29 = 47 3188 # sum col dif = 7 + 18 = 25 3189 g = [[11, 18], [29, 47]] 3190 3191 # Green color channel. 3192 # sum row dif = 120 + 193 = 313 3193 # sum col dif = 47 + 120 = 167 3194 b = [[73, 120], [193, 313]] 3195 3196 # Combine the 3 color channels into a single 3-dim array. 3197 # The shape is (2, 2, 3) corresponding to (height, width and color). 3198 a = np.dstack((r, g, b)) 3199 3200 # Total variation for this image. 3201 # Sum of all pixel differences = 8 + 4 + 47 + 25 + 313 + 167 = 564 3202 tot_var = 564 3203 3204 # Calculate the total variation using TensorFlow and assert it is correct. 3205 self._test(a, tot_var) 3206 3207 # If we add 1 to all pixel-values then the total variation is unchanged. 3208 self._test(a + 1, tot_var) 3209 3210 # If we negate all pixel-values then the total variation is unchanged. 3211 self._test(-a, tot_var) 3212 3213 # Scale the pixel-values by a float. This scales the total variation as well. 3214 b = 1.1 * a 3215 self._test(b, 1.1 * tot_var) 3216 3217 # Scale by another float. 3218 c = 1.2 * a 3219 self._test(c, 1.2 * tot_var) 3220 3221 # Combine these 3 images into a single array of shape (3, 2, 2, 3) 3222 # where the first dimension is for the image-number. 3223 multi = np.vstack((a[np.newaxis, :], b[np.newaxis, :], c[np.newaxis, :])) 3224 3225 # Check that TensorFlow correctly calculates the total variation 3226 # for each image individually and returns the correct array. 3227 self._test(multi, tot_var * np.array([1.0, 1.1, 1.2])) 3228 3229 3230 class FormatTest(test_util.TensorFlowTestCase): 3231 3232 def testFormats(self): 3233 prefix = "tensorflow/core/lib" 3234 paths = ("png/testdata/lena_gray.png", "jpeg/testdata/jpeg_merge_test1.jpg", 3235 "gif/testdata/lena.gif") 3236 decoders = { 3237 "jpeg": functools.partial(image_ops.decode_jpeg, channels=3), 3238 "png": functools.partial(image_ops.decode_png, channels=3), 3239 "gif": lambda s: array_ops.squeeze(image_ops.decode_gif(s), axis=0), 3240 } 3241 with self.test_session(): 3242 for path in paths: 3243 contents = io_ops.read_file(os.path.join(prefix, path)).eval() 3244 images = {} 3245 for name, decode in decoders.items(): 3246 image = decode(contents).eval() 3247 self.assertEqual(image.ndim, 3) 3248 for prev_name, prev in images.items(): 3249 print("path %s, names %s %s, shapes %s %s" % 3250 (path, name, prev_name, image.shape, prev.shape)) 3251 self.assertAllEqual(image, prev) 3252 images[name] = image 3253 3254 def testError(self): 3255 path = "tensorflow/core/lib/gif/testdata/scan.gif" 3256 with self.test_session(): 3257 for decode in image_ops.decode_jpeg, image_ops.decode_png: 3258 with self.assertRaisesOpError(r"Got 12 frames"): 3259 decode(io_ops.read_file(path)).eval() 3260 3261 3262 class NonMaxSuppressionTest(test_util.TensorFlowTestCase): 3263 3264 def testSelectFromThreeClusters(self): 3265 boxes_np = [[0, 0, 1, 1], [0, 0.1, 1, 1.1], [0, -0.1, 1, 0.9], 3266 [0, 10, 1, 11], [0, 10.1, 1, 11.1], [0, 100, 1, 101]] 3267 scores_np = [0.9, 0.75, 0.6, 0.95, 0.5, 0.3] 3268 max_output_size_np = 3 3269 iou_threshold_np = 0.5 3270 with self.test_session(): 3271 boxes = constant_op.constant(boxes_np) 3272 scores = constant_op.constant(scores_np) 3273 max_output_size = constant_op.constant(max_output_size_np) 3274 iou_threshold = constant_op.constant(iou_threshold_np) 3275 selected_indices = image_ops.non_max_suppression( 3276 boxes, scores, max_output_size, iou_threshold).eval() 3277 self.assertAllClose(selected_indices, [3, 0, 5]) 3278 3279 def testInvalidShape(self): 3280 # The boxes should be 2D of shape [num_boxes, 4]. 3281 with self.assertRaisesRegexp(ValueError, 3282 "Shape must be rank 2 but is rank 1"): 3283 boxes = constant_op.constant([0.0, 0.0, 1.0, 1.0]) 3284 scores = constant_op.constant([0.9]) 3285 image_ops.non_max_suppression(boxes, scores, 3, 0.5) 3286 3287 with self.assertRaisesRegexp(ValueError, "Dimension must be 4 but is 3"): 3288 boxes = constant_op.constant([[0.0, 0.0, 1.0]]) 3289 scores = constant_op.constant([0.9]) 3290 image_ops.non_max_suppression(boxes, scores, 3, 0.5) 3291 3292 # The boxes is of shape [num_boxes, 4], and the scores is 3293 # of shape [num_boxes]. So an error will thrown. 3294 with self.assertRaisesRegexp( 3295 ValueError, 'Dimensions must be equal, but are 1 and 2'): 3296 boxes = constant_op.constant([[0.0, 0.0, 1.0, 1.0]]) 3297 scores = constant_op.constant([0.9, 0.75]) 3298 selected_indices = image_ops.non_max_suppression( 3299 boxes, scores, 3, 0.5) 3300 3301 # The scores should be 1D of shape [num_boxes]. 3302 with self.assertRaisesRegexp(ValueError, 3303 "Shape must be rank 1 but is rank 2"): 3304 boxes = constant_op.constant([[0.0, 0.0, 1.0, 1.0]]) 3305 scores = constant_op.constant([[0.9]]) 3306 image_ops.non_max_suppression(boxes, scores, 3, 0.5) 3307 3308 # The max_output_size should be a scaler (0-D). 3309 with self.assertRaisesRegexp(ValueError, 3310 "Shape must be rank 0 but is rank 1"): 3311 boxes = constant_op.constant([[0.0, 0.0, 1.0, 1.0]]) 3312 scores = constant_op.constant([0.9]) 3313 image_ops.non_max_suppression(boxes, scores, [3], 0.5) 3314 3315 # The iou_threshold should be a scaler (0-D). 3316 with self.assertRaisesRegexp(ValueError, 3317 "Shape must be rank 0 but is rank 2"): 3318 boxes = constant_op.constant([[0.0, 0.0, 1.0, 1.0]]) 3319 scores = constant_op.constant([0.9]) 3320 image_ops.non_max_suppression(boxes, scores, 3, [[0.5]]) 3321 3322 3323 if __name__ == "__main__": 3324 googletest.main() 3325