def test_bilinear(self): image = tf.constant( # yapf: disable [[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], # yapf: enable tf.float32) # The following result matches: # >>> scipy.ndimage.rotate(image, 45, order=1, reshape=False) # which uses spline interpolation of order 1, equivalent to bilinear # interpolation. self.assertAllClose( transform_ops.rotate(image, np.pi / 4.0, interpolation="BILINEAR"), # yapf: disable [[0.000, 0.000, 0.343, 0.000, 0.000], [0.000, 0.586, 0.914, 0.586, 0.000], [0.343, 0.914, 0.000, 0.914, 0.343], [0.000, 0.586, 0.914, 0.586, 0.000], [0.000, 0.000, 0.343, 0.000, 0.000]], # yapf: enable atol=0.001) # yapf: disable self.assertAllClose( transform_ops.rotate( image, np.pi / 4.0, interpolation="NEAREST"), [[0, 0, 1, 0, 0], [0, 1, 1, 1, 0], [1, 1, 0, 1, 1], [0, 1, 1, 1, 0], [0, 0, 1, 0, 0]])
def test_bilinear_uint8(): image = tf.constant( np.asarray( [ [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 255, 255, 255, 0.0], [0.0, 255, 0.0, 255, 0.0], [0.0, 255, 255, 255, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ], np.uint8, ), tf.uint8, ) # == np.rint((expected image above) * 255) transformed = transform_ops.rotate(image, np.pi / 4.0, interpolation="BILINEAR") np.testing.assert_equal( transformed.numpy(), [ [0.0, 0.0, 87.0, 0.0, 0.0], [0.0, 149, 233, 149, 0.0], [87.0, 233, 0.0, 233, 87.0], [0.0, 149, 233, 149, 0.0], [0.0, 0.0, 87.0, 0.0, 0.0], ], )
def test_rotate_odd(dtype): image = tf.reshape(tf.cast(tf.range(25), dtype), (5, 5)) image_rep = tf.tile(image[None, :, :, None], [3, 1, 1, 1]) angles = tf.constant([np.pi / 4.0, 1.0, -np.pi / 2.0], tf.float32) image_rotated = transform_ops.rotate(image_rep, angles) np.testing.assert_equal( image_rotated.numpy()[:, :, :, 0], [ [ [0, 3, 8, 9, 0], [1, 7, 8, 13, 19], [6, 6, 12, 18, 18], [5, 11, 16, 17, 23], [0, 15, 16, 21, 0], ], [ [0, 3, 9, 14, 0], [2, 7, 8, 13, 19], [1, 6, 12, 18, 23], [5, 11, 16, 17, 22], [0, 10, 15, 21, 0], ], [ [20, 15, 10, 5, 0], [21, 16, 11, 6, 1], [22, 17, 12, 7, 2], [23, 18, 13, 8, 3], [24, 19, 14, 9, 4], ], ], )
def test_rotate_even(dtype): image = tf.reshape(tf.cast(tf.range(36), dtype), (6, 6)) image_rep = tf.tile(image[None, :, :, None], [3, 1, 1, 1]) angles = tf.constant([0.0, np.pi / 4.0, np.pi / 2.0], tf.float32) image_rotated = transform_ops.rotate(image_rep, angles) np.testing.assert_equal( image_rotated.numpy()[:, :, :, 0], [ [ [0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23], [24, 25, 26, 27, 28, 29], [30, 31, 32, 33, 34, 35], ], [ [0, 3, 4, 11, 17, 0], [2, 3, 9, 16, 23, 23], [1, 8, 15, 21, 22, 29], [6, 13, 20, 21, 27, 34], [12, 18, 19, 26, 33, 33], [0, 18, 24, 31, 32, 0], ], [ [5, 11, 17, 23, 29, 35], [4, 10, 16, 22, 28, 34], [3, 9, 15, 21, 27, 33], [2, 8, 14, 20, 26, 32], [1, 7, 13, 19, 25, 31], [0, 6, 12, 18, 24, 30], ], ], )
def test_rotate_even(self): for dtype in _DTYPES: image = tf.reshape(tf.cast(tf.range(36), dtype), (6, 6)) image_rep = tf.tile(image[None, :, :, None], [3, 1, 1, 1]) angles = tf.constant([0.0, np.pi / 4.0, np.pi / 2.0], tf.float32) image_rotated = transform_ops.rotate(image_rep, angles) # yapf: disable self.assertAllEqual( image_rotated[:, :, :, 0], [[[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23], [24, 25, 26, 27, 28, 29], [30, 31, 32, 33, 34, 35]], [[0, 3, 4, 11, 17, 0], [2, 3, 9, 16, 23, 23], [1, 8, 15, 21, 22, 29], [6, 13, 20, 21, 27, 34], [12, 18, 19, 26, 33, 33], [0, 18, 24, 31, 32, 0]], [[5, 11, 17, 23, 29, 35], [4, 10, 16, 22, 28, 34], [3, 9, 15, 21, 27, 33], [2, 8, 14, 20, 26, 32], [1, 7, 13, 19, 25, 31], [0, 6, 12, 18, 24, 30]]])
def test_zeros(self): for dtype in _DTYPES: for shape in [(5, 5), (24, 24), (2, 24, 24, 3)]: for angle in [0, 1, np.pi / 2.0]: image = tf.zeros(shape, dtype) self.assertAllEqual(transform_ops.rotate(image, angle), np.zeros(shape, dtype.as_numpy_dtype))
def random_rotation( img: tf.Tensor, max_rotation: float = 0.1, crop: bool = True, minimum_width: int = 0) -> tf.Tensor: # adapted from SeguinBe """ Rotates an image with a random angle. See https://stackoverflow.com/questions/16702966/rotate-image-and-crop-out-black-borders for formulae :param img: Tensor :param max_rotation: maximum angle to rotate (radians) :param crop: boolean to crop or not the image after rotation :param minimum_width: minimum width of image after data augmentation :return: """ with tf.name_scope('RandomRotation'): rotation = tf.random.uniform([], -max_rotation, max_rotation, name='pick_random_angle') # rotated_image = tf.contrib.image.rotate(img, rotation, interpolation='BILINEAR') rotated_image = rotate(tf.expand_dims(img, axis=0), rotation, interpolation='BILINEAR') rotated_image = tf.squeeze(rotated_image, axis=0) if crop: rotation = tf.abs(rotation) original_shape = tf.shape(rotated_image)[:2] h, w = original_shape[0], original_shape[1] old_l, old_s = tf.cond(h > w, lambda: [h, w], lambda: [w, h]) old_l, old_s = tf.cast(old_l, tf.float32), tf.cast(old_s, tf.float32) new_l = (old_l * tf.cos(rotation) - old_s * tf.sin(rotation)) / tf.cos(2 * rotation) new_s = (old_s - tf.sin(rotation) * new_l) / tf.cos(rotation) new_h, new_w = tf.cond(h > w, lambda: [new_l, new_s], lambda: [new_s, new_l]) new_h, new_w = tf.cast(new_h, tf.int32), tf.cast(new_w, tf.int32) bb_begin = tf.cast(tf.math.ceil((h - new_h) / 2), tf.int32), tf.cast( tf.math.ceil((w - new_w) / 2), tf.int32) # Test sliced rotated_image_crop = tf.cond( tf.logical_and(bb_begin[0] < h - bb_begin[0], bb_begin[1] < w - bb_begin[1]), true_fn=lambda: rotated_image[bb_begin[0]:h - bb_begin[0], bb_begin[1]:w - bb_begin[1], :], false_fn=lambda: img, name='check_slices_indices') # rotated_image_crop = rotated_image[bb_begin[0]:h - bb_begin[0], bb_begin[1]:w - bb_begin[1], :] # If crop removes the entire image, keep the original image rotated_image = tf.cond(tf.less_equal( tf.shape(rotated_image_crop)[1], minimum_width), true_fn=lambda: img, false_fn=lambda: rotated_image_crop, name='check_size_crop') return rotated_image
def test_zeros(dtype): for shape in [(5, 5), (24, 24), (2, 24, 24, 3)]: for angle in [0, 1, np.pi / 2.0]: image = tf.zeros(shape, dtype) np.testing.assert_equal( transform_ops.rotate(image, angle), np.zeros(shape, dtype.as_numpy_dtype), )
def test_bilinear(): image = tf.constant( [ [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0], ], tf.float32, ) # The following result matches: # >>> scipy.ndimage.rotate(image, 45, order=1, reshape=False) # which uses spline interpolation of order 1, equivalent to bilinear # interpolation. transformed = transform_ops.rotate(image, np.pi / 4.0, interpolation="BILINEAR") np.testing.assert_allclose( transformed.numpy(), [ [0.000, 0.000, 0.343, 0.000, 0.000], [0.000, 0.586, 0.914, 0.586, 0.000], [0.343, 0.914, 0.000, 0.914, 0.343], [0.000, 0.586, 0.914, 0.586, 0.000], [0.000, 0.000, 0.343, 0.000, 0.000], ], atol=0.001, ) transformed = transform_ops.rotate(image, np.pi / 4.0, interpolation="NEAREST") np.testing.assert_allclose( transformed.numpy(), [ [0, 0, 1, 0, 0], [0, 1, 1, 1, 0], [1, 1, 0, 1, 1], [0, 1, 1, 1, 0], [0, 0, 1, 0, 0], ], )
def test_bilinear_uint8(self): # yapf: disable image = tf.constant( np.asarray( [[0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 255, 255, 255, 0.0], [0.0, 255, 0.0, 255, 0.0], [0.0, 255, 255, 255, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0]], np.uint8), tf.uint8) # yapf: enable # == np.rint((expected image above) * 255) # yapf: disable self.assertAllEqual( transform_ops.rotate(image, np.pi / 4.0, interpolation="BILINEAR"), [[0.0, 0.0, 87., 0.0, 0.0], [0.0, 149, 233, 149, 0.0], [87., 233, 0.0, 233, 87.], [0.0, 149, 233, 149, 0.0], [0.0, 0.0, 87., 0.0, 0.0]])
def test_rotate_odd(self): for dtype in _DTYPES: image = tf.reshape(tf.cast(tf.range(25), dtype), (5, 5)) image_rep = tf.tile(image[None, :, :, None], [3, 1, 1, 1]) angles = tf.constant([np.pi / 4.0, 1.0, -np.pi / 2.0], tf.float32) image_rotated = transform_ops.rotate(image_rep, angles) # yapf: disable self.assertAllEqual( image_rotated[:, :, :, 0], [[[0, 3, 8, 9, 0], [1, 7, 8, 13, 19], [6, 6, 12, 18, 18], [5, 11, 16, 17, 23], [0, 15, 16, 21, 0]], [[0, 3, 9, 14, 0], [2, 7, 8, 13, 19], [1, 6, 12, 18, 23], [5, 11, 16, 17, 22], [0, 10, 15, 21, 0]], [[20, 15, 10, 5, 0], [21, 16, 11, 6, 1], [22, 17, 12, 7, 2], [23, 18, 13, 8, 3], [24, 19, 14, 9, 4]]])
def test_rotate_static_shape(): image = tf.linalg.diag([1.0, 2.0, 3.0]) result = transform_ops.rotate( image, tf.random.uniform((), -1, 1), interpolation="BILINEAR" ) np.testing.assert_equal(image.get_shape(), result.get_shape())
def test_rotate_static_shape(self): image = tf.linalg.diag([1., 2., 3.]) result = transform_ops.rotate(image, tf.random.uniform((), -1, 1), interpolation="BILINEAR") self.assertEqual(image.get_shape(), result.get_shape())