from __future__ import print_function, division, absolute_import import sys # unittest only added in 3.4 self.subTest() if sys.version_info[0] < 3 or sys.version_info[1] < 4: import unittest2 as unittest else: import unittest # unittest.mock is not available in 2.7 (though unittest2 might contain it?) try: import unittest.mock as mock except ImportError: import mock import numpy as np import six.moves as sm from imgaug import augmenters as iaa from imgaug import parameters as iap from imgaug import dtypes as iadt from imgaug import random as iarandom from imgaug.testutils import reseed, runtest_pickleable_uint8_img # TODO add tests for EdgeDetect # TODO add tests for DirectedEdgeDetect class Test_convolve(unittest.TestCase): def test_1x1_identity_matrix_2d_image(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) matrix = np.float32([ [1.0] ]) image_aug = iaa.convolve(image, matrix) assert image_aug is not image assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3) assert np.array_equal(image_aug, image) class Test_convolve_(unittest.TestCase): def test_1x1_identity_matrix_2d_image_small_image_sizes(self): for height in np.arange(16): for width in np.arange(16): shapes = [ (height, width), (height, width, 1), (height, width, 3) ] for shape in shapes: with self.subTest(shape=shape): image = np.mod( np.arange(int(np.prod(shape))).reshape(shape), 255 ).astype(np.uint8) matrix = np.float32([ [1.0] ]) image_aug = iaa.convolve_(np.copy(image), matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape assert np.array_equal(image_aug, image) def test_1x1_identity_matrix_2d_image(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) matrix = np.float32([ [1.0] ]) image_aug = iaa.convolve_(np.copy(image), matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3) assert np.array_equal(image_aug, image) def test_2x2_identity_matrix_2d_image(self): image = np.array([ [0, 10, 20, 30], [40, 50, 60, 70] ], dtype=np.uint8) matrix = np.float32([ [0.0, 0.0], [0.0, 1.0] ]) image_aug = iaa.convolve_(np.copy(image), matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 4) assert np.array_equal(image_aug, image) def test_3x3_identity_matrix_2d_image(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) matrix = np.float32([ [0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0] ]) image_aug = iaa.convolve_(np.copy(image), matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3) assert np.array_equal(image_aug, image) def test_single_matrix_2d_image(self): image = np.array([ [0, 10, 20], [30, 40, 50], [60, 70, 80] ], dtype=np.uint8) matrix = np.float32([ [0.0, 1.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0] ]) expected = np.array([ [0+30, 10+40, 20+50], [30+0, 40+10, 50+20], [60+30, 70+40, 80+50] ], dtype=np.float32) image_aug = iaa.convolve_(np.copy(image), matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (3, 3) assert np.array_equal(image_aug, expected) def test_single_matrix_3d_image(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) image = np.tile(image[:, :, np.newaxis], (1, 1, 2)) matrix = np.float32([ [0.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 0.0] ]) image_aug = iaa.convolve_(np.copy(image), matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3, 2) assert np.array_equal(image_aug, 2*image) def test_matrix_is_list_of_arrays(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) image = np.tile(image[:, :, np.newaxis], (1, 1, 2)) matrices = [ np.float32([ [0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0] ]), np.float32([ [0.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 0.0] ]) ] image_aug = iaa.convolve_(np.copy(image), matrices) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3, 2) assert np.array_equal(image_aug[:, :, 0], image[:, :, 0]) assert np.array_equal(image_aug[:, :, 1], 2*image[:, :, 1]) def test_matrix_is_list_containing_none(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) image = np.tile(image[:, :, np.newaxis], (1, 1, 2)) matrices = [ None, np.float32([ [0.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 0.0] ]) ] image_aug = iaa.convolve_(np.copy(image), matrices) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3, 2) assert np.array_equal(image_aug[:, :, 0], image[:, :, 0]) assert np.array_equal(image_aug[:, :, 1], 2*image[:, :, 1]) def test_matrix_is_list_containing_only_none(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) image = np.tile(image[:, :, np.newaxis], (1, 1, 2)) matrices = [ None, None ] image_aug = iaa.convolve_(np.copy(image), matrices) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3, 2) assert np.array_equal(image_aug[:, :, 0], image[:, :, 0]) assert np.array_equal(image_aug[:, :, 1], image[:, :, 1]) def test_unusual_channel_numbers(self): for nb_channels in [1, 2, 3, 4, 5, 10, 512, 513]: with self.subTest(nb_channels=nb_channels): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) image = image[:, :, np.newaxis] image = np.tile(image, (1, 1, nb_channels)) matrix = np.float32([ [2.0] ]) image_aug = iaa.convolve_(np.copy(image), matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3, nb_channels) assert np.array_equal(image_aug, 2*image) def test_zero_sized_axes(self): shapes = [ (0, 0), (0, 1), (1, 0), (0, 1, 0), (1, 0, 0), (0, 1, 1), (1, 0, 1) ] for shape in shapes: with self.subTest(shape=shape): image = np.zeros(shape, dtype=np.uint8) matrix = np.float32([ [2.0] ]) image_aug = iaa.convolve_(np.copy(image), matrix) assert image_aug.shape == image.shape def test_view_heightwise(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) image_view = np.copy(image)[:2, :] assert image_view.flags["OWNDATA"] is False matrix = np.float32([ [2.0] ]) image_aug = iaa.convolve_(image_view, matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3) assert np.array_equal(image_aug, 2*image) def test_view_channelwise_1_channel(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) image = np.tile(image[:, :, np.newaxis], (1, 1, 3)) image[:, :, 0] += 0 image[:, :, 1] += 1 image[:, :, 2] += 2 image_view = np.copy(image)[:, :, [False, True, False]] assert image_view.flags["OWNDATA"] is False assert image_view.base.shape == (1, 2, 3) matrix = np.float32([ [2.0] ]) image_aug = iaa.convolve_(image_view, matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3, 1) assert np.array_equal(image_aug, 2*image[:, :, 1:2]) def test_view_channelwise_4_channels(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) image = np.tile(image[:, :, np.newaxis], (1, 1, 6)) image[:, :, 0] += 0 image[:, :, 1] += 1 image[:, :, 2] += 2 mask = [False, True, True, True, True, False] image_view = np.copy(image)[:, :, mask] assert image_view.flags["OWNDATA"] is False assert image_view.base.shape == (4, 2, 3) matrix = np.float32([ [2.0] ]) image_aug = iaa.convolve_(image_view, matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3, 4) assert np.array_equal(image_aug, 2*image[:, :, mask]) def test_noncontiguous(self): image = np.array([ [0, 10, 20], [30, 40, 50] ], dtype=np.uint8) image_nonc = np.array(image, dtype=np.uint8, order="F") assert image_nonc.flags["C_CONTIGUOUS"] is False matrix = np.float32([ [2.0] ]) image_aug = iaa.convolve_(image_nonc, matrix) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (2, 3) assert np.array_equal(image_aug, 2*image) # TODO add test for keypoints once their handling was improved in Convolve class TestConvolve(unittest.TestCase): def setUp(self): reseed() @property def img(self): return np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9] ], dtype=np.uint8) def test_matrix_is_none(self): aug = iaa.Convolve(matrix=None) observed = aug.augment_image(self.img) assert np.array_equal(observed, self.img) def test_matrix_is_lambda_none(self): def _matrix_generator(_img, _nb_channels, _random_state): return [None] aug = iaa.Convolve(matrix=_matrix_generator) observed = aug.augment_image(self.img) assert np.array_equal(observed, self.img) def test_matrix_is_1x1_identity(self): # matrix is [[1]] aug = iaa.Convolve(matrix=np.float32([[1]])) observed = aug.augment_image(self.img) assert np.array_equal(observed, self.img) def test_matrix_is_lambda_1x1_identity(self): def _matrix_generator(_img, _nb_channels, _random_state): return np.float32([[1]]) aug = iaa.Convolve(matrix=_matrix_generator) observed = aug.augment_image(self.img) assert np.array_equal(observed, self.img) def test_matrix_is_3x3_identity(self): m = np.float32([ [0, 0, 0], [0, 1, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=m) observed = aug.augment_image(self.img) assert np.array_equal(observed, self.img) def test_matrix_is_lambda_3x3_identity(self): def _matrix_generator(_img, _nb_channels, _random_state): return np.float32([ [0, 0, 0], [0, 1, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=_matrix_generator) observed = aug.augment_image(self.img) assert np.array_equal(observed, self.img) def test_matrix_is_3x3_two_in_center(self): m = np.float32([ [0, 0, 0], [0, 2, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=m) observed = aug.augment_image(self.img) assert np.array_equal(observed, 2*self.img) def test_matrix_is_lambda_3x3_two_in_center(self): def _matrix_generator(_img, _nb_channels, _random_state): return np.float32([ [0, 0, 0], [0, 2, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=_matrix_generator) observed = aug.augment_image(self.img) assert np.array_equal(observed, 2*self.img) def test_matrix_is_3x3_two_in_center_3_channels(self): m = np.float32([ [0, 0, 0], [0, 2, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=m) img3 = np.tile(self.img[..., np.newaxis], (1, 1, 3)) # 3 channels observed = aug.augment_image(img3) assert np.array_equal(observed, 2*img3) def test_matrix_is_lambda_3x3_two_in_center_3_channels(self): def _matrix_generator(_img, _nb_channels, _random_state): return np.float32([ [0, 0, 0], [0, 2, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=_matrix_generator) img3 = np.tile(self.img[..., np.newaxis], (1, 1, 3)) # 3 channels observed = aug.augment_image(img3) assert np.array_equal(observed, 2*img3) def test_matrix_is_3x3_with_multiple_nonzero_values(self): m = np.float32([ [0, -1, 0], [0, 10, 0], [0, 0, 0] ]) expected = np.uint8([ [10*1+(-1)*4, 10*2+(-1)*5, 10*3+(-1)*6], [10*4+(-1)*1, 10*5+(-1)*2, 10*6+(-1)*3], [10*7+(-1)*4, 10*8+(-1)*5, 10*9+(-1)*6] ]) aug = iaa.Convolve(matrix=m) observed = aug.augment_image(self.img) assert np.array_equal(observed, expected) def test_matrix_is_lambda_3x3_with_multiple_nonzero_values(self): def _matrix_generator(_img, _nb_channels, _random_state): return np.float32([ [0, -1, 0], [0, 10, 0], [0, 0, 0] ]) expected = np.uint8([ [10*1+(-1)*4, 10*2+(-1)*5, 10*3+(-1)*6], [10*4+(-1)*1, 10*5+(-1)*2, 10*6+(-1)*3], [10*7+(-1)*4, 10*8+(-1)*5, 10*9+(-1)*6] ]) aug = iaa.Convolve(matrix=_matrix_generator) observed = aug.augment_image(self.img) assert np.array_equal(observed, expected) def test_lambda_with_changing_matrices(self): # changing matrices when using callable def _matrix_generator(_img, _nb_channels, random_state): return np.float32([[ iarandom.polyfill_integers(random_state, 0, 5) ]]) expected = [] for i in sm.xrange(5): expected.append(self.img * i) aug = iaa.Convolve(matrix=_matrix_generator) seen = [False] * 5 for _ in sm.xrange(200): observed = aug.augment_image(self.img) found = False for i, expected_i in enumerate(expected): if np.array_equal(observed, expected_i): seen[i] = True found = True break assert found if all(seen): break assert np.all(seen) def test_matrix_has_bad_datatype(self): # don't use assertRaisesRegex, because it doesnt exist in 2.7 got_exception = False try: _aug = iaa.Convolve(matrix=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test_zero_sized_axes(self): shapes = [ (0, 0), (0, 1), (1, 0), (0, 1, 0), (1, 0, 0), (0, 1, 1), (1, 0, 1) ] for shape in shapes: with self.subTest(shape=shape): image = np.zeros(shape, dtype=np.uint8) aug = iaa.Convolve(matrix=np.float32([[1]])) image_aug = aug(image=image) assert image_aug.shape == image.shape def test_get_parameters(self): matrix = np.int32([[1]]) aug = iaa.Convolve(matrix=matrix) params = aug.get_parameters() assert np.array_equal(params[0], matrix) assert params[1] == "constant" def test_other_dtypes_bool_identity_matrix(self): identity_matrix = np.int64([[1]]) aug = iaa.Convolve(matrix=identity_matrix) image = np.zeros((3, 3), dtype=bool) image[1, 1] = True image_aug = aug.augment_image(image) assert image.dtype.type == np.bool_ assert np.all(image_aug == image) def test_other_dtypes_uint_int_identity_matrix(self): identity_matrix = np.int64([[1]]) aug = iaa.Convolve(matrix=identity_matrix) for dtype in [np.uint8, np.uint16, np.int8, np.int16]: image = np.zeros((3, 3), dtype=dtype) image[1, 1] = 100 image_aug = aug.augment_image(image) assert image.dtype.type == dtype assert np.all(image_aug == image) def test_other_dtypes_float_identity_matrix(self): identity_matrix = np.int64([[1]]) aug = iaa.Convolve(matrix=identity_matrix) for dtype in [np.float16, np.float32, np.float64]: image = np.zeros((3, 3), dtype=dtype) image[1, 1] = 100.0 image_aug = aug.augment_image(image) assert image.dtype.type == dtype assert np.allclose(image_aug, image) def test_other_dtypes_bool_non_identity_matrix_with_small_values(self): matrix = np.float64([ [0, 0.6, 0], [0, 0.4, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=matrix) image = np.zeros((3, 3), dtype=bool) image[1, 1] = True image[2, 1] = True expected = np.zeros((3, 3), dtype=bool) expected[0, 1] = True expected[2, 1] = True image_aug = aug.augment_image(image) assert image.dtype.type == np.bool_ assert np.all(image_aug == expected) def test_other_dtypes_uint_int_non_identity_matrix_with_small_values(self): matrix = np.float64([ [0, 0.5, 0], [0, 0.5, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=matrix) for dtype in [np.uint8, np.uint16, np.int8, np.int16]: image = np.zeros((3, 3), dtype=dtype) image[1, 1] = 100 image[2, 1] = 100 image_aug = aug.augment_image(image) expected = np.zeros((3, 3), dtype=dtype) expected[0, 1] = int(np.round(100 * 0.5)) expected[1, 1] = int(np.round(100 * 0.5)) expected[2, 1] = int(np.round(100 * 0.5 + 100 * 0.5)) diff = np.abs( image_aug.astype(np.int64) - expected.astype(np.int64)) assert image_aug.dtype.type == dtype assert np.max(diff) <= 2 def test_other_dtypes_float_non_identity_matrix_with_small_values(self): matrix = np.float64([ [0, 0.5, 0], [0, 0.5, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=matrix) for dtype in [np.float16, np.float32, np.float64]: image = np.zeros((3, 3), dtype=dtype) image[1, 1] = 100.0 image[2, 1] = 100.0 image_aug = aug.augment_image(image) expected = np.zeros((3, 3), dtype=dtype) expected[0, 1] = 100 * 0.5 expected[1, 1] = 100 * 0.5 expected[2, 1] = 100 * 0.5 + 100 * 0.5 diff = np.abs( image_aug.astype(np.float64) - expected.astype(np.float64) ) assert image_aug.dtype.type == dtype assert np.max(diff) < 1.0 def test_other_dtypes_uint_int_non_identity_matrix_with_large_values(self): matrix = np.float64([ [0, 0.5, 0], [0, 0.5, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=matrix) for dtype in [np.uint8, np.uint16, np.int8, np.int16]: _min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) value = int(center_value + 0.4 * max_value) image = np.zeros((3, 3), dtype=dtype) image[1, 1] = value image[2, 1] = value image_aug = aug.augment_image(image) expected = np.zeros((3, 3), dtype=dtype) expected[0, 1] = int(np.round(value * 0.5)) expected[1, 1] = int(np.round(value * 0.5)) expected[2, 1] = int(np.round(value * 0.5 + value * 0.5)) diff = np.abs( image_aug.astype(np.int64) - expected.astype(np.int64)) assert image_aug.dtype.type == dtype assert np.max(diff) <= 2 def test_other_dtypes_float_non_identity_matrix_with_large_values(self): matrix = np.float64([ [0, 0.5, 0], [0, 0.5, 0], [0, 0, 0] ]) aug = iaa.Convolve(matrix=matrix) for dtype, value in zip([np.float16, np.float32, np.float64], [5000, 1000*1000, 1000*1000*1000]): image = np.zeros((3, 3), dtype=dtype) image[1, 1] = value image[2, 1] = value image_aug = aug.augment_image(image) expected = np.zeros((3, 3), dtype=dtype) expected[0, 1] = value * 0.5 expected[1, 1] = value * 0.5 expected[2, 1] = value * 0.5 + value * 0.5 diff = np.abs( image_aug.astype(np.float64) - expected.astype(np.float64)) assert image_aug.dtype.type == dtype assert np.max(diff) < 1.0 def test_failure_on_invalid_dtypes(self): # don't use assertRaisesRegex, because it doesnt exist in 2.7 identity_matrix = np.int64([[1]]) aug = iaa.Convolve(matrix=identity_matrix) for dt in [np.uint32, np.uint64, np.int32, np.int64]: got_exception = False try: _ = aug.augment_image(np.zeros((1, 1), dtype=dt)) except Exception as exc: assert "forbidden dtype" in str(exc) got_exception = True assert got_exception def test_pickleable__identity_matrix(self): identity_matrix = np.int64([[1]]) aug = iaa.Convolve(identity_matrix, seed=1) runtest_pickleable_uint8_img(aug, iterations=20) def test_pickleable__callback_function(self): aug = iaa.Convolve(_convolve_pickleable_matrix_generator, seed=1) runtest_pickleable_uint8_img(aug, iterations=20) def _convolve_pickleable_matrix_generator(_img, _nb_channels, random_state): return np.float32([[random_state.integers(0, 5)]]) class TestSharpen(unittest.TestCase): def setUp(self): reseed() @classmethod def _compute_sharpened_base_img(cls, lightness, m): img = np.zeros((3, 3), dtype=np.float32) k = 1 # note that cv2 uses reflection padding by default img[0, 0] = ( (m[1, 1] + lightness)/k * 10 + 4 * (m[0, 0]/k) * 10 + 4 * (m[2, 2]/k) * 20 ) img[0, 2] = img[0, 0] img[2, 0] = img[0, 0] img[2, 2] = img[0, 0] img[0, 1] = ( (m[1, 1] + lightness)/k * 10 + 6 * (m[0, 1]/k) * 10 + 2 * (m[2, 2]/k) * 20 ) img[1, 0] = img[0, 1] img[1, 2] = img[0, 1] img[2, 1] = img[0, 1] img[1, 1] = ( (m[1, 1] + lightness)/k * 20 + 8 * (m[0, 1]/k) * 10 ) img = np.clip(img, 0, 255).astype(np.uint8) return img @property def base_img(self): base_img = [[10, 10, 10], [10, 20, 10], [10, 10, 10]] base_img = np.uint8(base_img) return base_img @property def base_img_sharpened(self): return self._compute_sharpened_base_img(1, self.m) @property def m(self): return np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], dtype=np.float32) @property def m_noop(self): return np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]], dtype=np.float32) def test_alpha_zero(self): aug = iaa.Sharpen(alpha=0, lightness=1) observed = aug.augment_image(self.base_img) expected = self.base_img assert np.allclose(observed, expected) def test_alpha_one(self): aug = iaa.Sharpen(alpha=1.0, lightness=1) observed = aug.augment_image(self.base_img) expected = self.base_img_sharpened assert np.allclose(observed, expected) def test_alpha_050(self): aug = iaa.Sharpen(alpha=0.5, lightness=1) observed = aug.augment_image(self.base_img) expected = self._compute_sharpened_base_img( 0.5*1, 0.5 * self.m_noop + 0.5 * self.m) assert np.allclose(observed, expected.astype(np.uint8)) def test_alpha_075(self): aug = iaa.Sharpen(alpha=0.75, lightness=1) observed = aug.augment_image(self.base_img) expected = self._compute_sharpened_base_img( 0.75*1, 0.25 * self.m_noop + 0.75 * self.m) assert np.allclose(observed, expected) def test_alpha_is_stochastic_parameter(self): aug = iaa.Sharpen(alpha=iap.Choice([0.5, 1.0]), lightness=1) observed = aug.augment_image(self.base_img) expected1 = self._compute_sharpened_base_img( 0.5*1, 0.5 * self.m_noop + 0.5 * self.m) expected2 = self._compute_sharpened_base_img( 1.0*1, 0.0 * self.m_noop + 1.0 * self.m) assert ( np.allclose(observed, expected1) or np.allclose(observed, expected2) ) def test_failure_if_alpha_has_bad_datatype(self): # don't use assertRaisesRegex, because it doesnt exist in 2.7 got_exception = False try: _ = iaa.Sharpen(alpha="test", lightness=1) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test_alpha_1_lightness_2(self): aug = iaa.Sharpen(alpha=1.0, lightness=2) observed = aug.augment_image(self.base_img) expected = self._compute_sharpened_base_img(1.0*2, self.m) assert np.allclose(observed, expected) def test_alpha_1_lightness_3(self): aug = iaa.Sharpen(alpha=1.0, lightness=3) observed = aug.augment_image(self.base_img) expected = self._compute_sharpened_base_img(1.0*3, self.m) assert np.allclose(observed, expected) def test_alpha_1_lightness_is_stochastic_parameter(self): aug = iaa.Sharpen(alpha=1.0, lightness=iap.Choice([1.0, 1.5])) observed = aug.augment_image(self.base_img) expected1 = self._compute_sharpened_base_img(1.0*1.0, self.m) expected2 = self._compute_sharpened_base_img(1.0*1.5, self.m) assert ( np.allclose(observed, expected1) or np.allclose(observed, expected2) ) def test_failure_if_lightness_has_bad_datatype(self): # don't use assertRaisesRegex, because it doesnt exist in 2.7 got_exception = False try: _ = iaa.Sharpen(alpha=1.0, lightness="test") except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception # this part doesnt really work so far due to nonlinearities resulting # from clipping to uint8 """ # alpha range aug = iaa.Sharpen(alpha=(0.0, 1.0), lightness=1) base_img = np.copy(base_img) base_img_sharpened_min = _compute_sharpened_base_img( 0.0*1, 1.0 * m_noop + 0.0 * m) base_img_sharpened_max = _compute_sharpened_base_img( 1.0*1, 0.0 * m_noop + 1.0 * m) #distance_max = np.average( np.abs( base_img_sharpened.astype(np.float32) - base_img.astype(np.float32) ) ) distance_max = np.average( np.abs( base_img_sharpened_max - base_img_sharpened_min ) ) nb_iterations = 250 distances = [] for _ in sm.xrange(nb_iterations): observed = aug.augment_image(base_img) distance = np.average( np.abs( observed.astype(np.float32) - base_img_sharpened_max.astype(np.float32) ) ) / distance_max distances.append(distance) print(distances) print(min(distances), np.average(distances), max(distances)) assert 0 - 1e-4 < min(distances) < 0.1 assert 0.4 < np.average(distances) < 0.6 assert 0.9 < max(distances) < 1.0 + 1e-4 nb_bins = 5 hist, _ = np.histogram(distances, bins=nb_bins, range=(0.0, 1.0), density=False) density_expected = 1.0/nb_bins density_tolerance = 0.05 for nb_samples in hist: density = nb_samples / nb_iterations assert ( density_expected - density_tolerance < density < density_expected + density_tolerance) # lightness range aug = iaa.Sharpen(alpha=1.0, lightness=(0.5, 2.0)) base_img = np.copy(base_img) base_img_sharpened = _compute_sharpened_base_img(1.0*2.0, m) distance_max = np.average( np.abs( base_img_sharpened.astype(np.int32) - base_img.astype(np.int32) ) ) nb_iterations = 250 distances = [] for _ in sm.xrange(nb_iterations): observed = aug.augment_image(base_img) distance = np.average( np.abs( observed.astype(np.int32) - base_img.astype(np.int32) ) ) / distance_max distances.append(distance) assert 0 - 1e-4 < min(distances) < 0.1 assert 0.4 < np.average(distances) < 0.6 assert 0.9 < max(distances) < 1.0 + 1e-4 nb_bins = 5 hist, _ = np.histogram(distances, bins=nb_bins, range=(0.0, 1.0), density=False) density_expected = 1.0/nb_bins density_tolerance = 0.05 for nb_samples in hist: density = nb_samples / nb_iterations assert ( density_expected - density_tolerance < density < density_expected + density_tolerance) """ def test_pickleable(self): aug = iaa.Sharpen(alpha=(0.0, 1.0), lightness=(1, 3), seed=1) runtest_pickleable_uint8_img(aug, iterations=20) class TestEmboss(unittest.TestCase): def setUp(self): reseed() @classmethod def _compute_embossed_base_img(cls, img, alpha, strength): img = np.copy(img) base_img_embossed = np.zeros((3, 3), dtype=np.float32) m = np.float32([[-1, 0, 0], [0, 1, 0], [0, 0, 1]]) strength_matrix = strength * np.float32([ [-1, -1, 0], [-1, 0, 1], [0, 1, 1] ]) ms = m + strength_matrix for i in range(base_img_embossed.shape[0]): for j in range(base_img_embossed.shape[1]): for u in range(ms.shape[0]): for v in range(ms.shape[1]): weight = ms[u, v] inputs_i = abs(i + (u - (ms.shape[0]-1)//2)) inputs_j = abs(j + (v - (ms.shape[1]-1)//2)) if inputs_i >= img.shape[0]: diff = inputs_i - (img.shape[0]-1) inputs_i = img.shape[0] - 1 - diff if inputs_j >= img.shape[1]: diff = inputs_j - (img.shape[1]-1) inputs_j = img.shape[1] - 1 - diff inputs = img[inputs_i, inputs_j] base_img_embossed[i, j] += inputs * weight return np.clip( (1-alpha) * img + alpha * base_img_embossed, 0, 255 ).astype(np.uint8) @classmethod def _allclose(cls, a, b): return np.max( a.astype(np.float32) - b.astype(np.float32) ) <= 2.1 @property def base_img(self): return np.array([[10, 10, 10], [10, 20, 10], [10, 10, 15]], dtype=np.uint8) def test_alpha_0_strength_1(self): aug = iaa.Emboss(alpha=0, strength=1) observed = aug.augment_image(self.base_img) expected = self.base_img assert self._allclose(observed, expected) def test_alpha_1_strength_1(self): aug = iaa.Emboss(alpha=1.0, strength=1) observed = aug.augment_image(self.base_img) expected = self._compute_embossed_base_img( self.base_img, alpha=1.0, strength=1) assert self._allclose(observed, expected) def test_alpha_050_strength_1(self): aug = iaa.Emboss(alpha=0.5, strength=1) observed = aug.augment_image(self.base_img) expected = self._compute_embossed_base_img( self.base_img, alpha=0.5, strength=1) assert self._allclose(observed, expected.astype(np.uint8)) def test_alpha_075_strength_1(self): aug = iaa.Emboss(alpha=0.75, strength=1) observed = aug.augment_image(self.base_img) expected = self._compute_embossed_base_img( self.base_img, alpha=0.75, strength=1) assert self._allclose(observed, expected) def test_alpha_stochastic_parameter_strength_1(self): aug = iaa.Emboss(alpha=iap.Choice([0.5, 1.0]), strength=1) observed = aug.augment_image(self.base_img) expected1 = self._compute_embossed_base_img( self.base_img, alpha=0.5, strength=1) expected2 = self._compute_embossed_base_img( self.base_img, alpha=1.0, strength=1) assert ( self._allclose(observed, expected1) or self._allclose(observed, expected2) ) def test_failure_on_invalid_datatype_for_alpha(self): # don't use assertRaisesRegex, because it doesnt exist in 2.7 got_exception = False try: _ = iaa.Emboss(alpha="test", strength=1) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test_alpha_1_strength_2(self): aug = iaa.Emboss(alpha=1.0, strength=2) observed = aug.augment_image(self.base_img) expected = self._compute_embossed_base_img( self.base_img, alpha=1.0, strength=2) assert self._allclose(observed, expected) def test_alpha_1_strength_3(self): aug = iaa.Emboss(alpha=1.0, strength=3) observed = aug.augment_image(self.base_img) expected = self._compute_embossed_base_img( self.base_img, alpha=1.0, strength=3) assert self._allclose(observed, expected) def test_alpha_1_strength_6(self): aug = iaa.Emboss(alpha=1.0, strength=6) observed = aug.augment_image(self.base_img) expected = self._compute_embossed_base_img( self.base_img, alpha=1.0, strength=6) assert self._allclose(observed, expected) def test_alpha_1_strength_stochastic_parameter(self): aug = iaa.Emboss(alpha=1.0, strength=iap.Choice([1.0, 2.5])) observed = aug.augment_image(self.base_img) expected1 = self._compute_embossed_base_img( self.base_img, alpha=1.0, strength=1.0) expected2 = self._compute_embossed_base_img( self.base_img, alpha=1.0, strength=2.5) assert ( self._allclose(observed, expected1) or self._allclose(observed, expected2) ) def test_failure_on_invalid_datatype_for_strength(self): # don't use assertRaisesRegex, because it doesnt exist in 2.7 got_exception = False try: _ = iaa.Emboss(alpha=1.0, strength="test") except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test_pickleable(self): aug = iaa.Emboss(alpha=(0.0, 1.0), strength=(1, 3), seed=1) runtest_pickleable_uint8_img(aug, iterations=20)