from __future__ import print_function, division, absolute_import import itertools import warnings 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 import skimage.morphology import cv2 import imgaug as ia from imgaug import random as iarandom from imgaug import augmenters as iaa from imgaug import parameters as iap from imgaug import dtypes as iadt from imgaug.testutils import ( array_equal_lists, keypoints_equal, reseed, assert_cbaois_equal, runtest_pickleable_uint8_img, assertWarns, is_parameter_instance) from imgaug.augmentables.heatmaps import HeatmapsOnImage from imgaug.augmentables.segmaps import SegmentationMapsOnImage import imgaug.augmenters.geometric as geometriclib def _assert_same_min_max(observed, actual): assert np.isclose(observed.min_value, actual.min_value, rtol=0, atol=1e-6) assert np.isclose(observed.max_value, actual.max_value, rtol=0, atol=1e-6) def _assert_same_shape(observed, actual): assert observed.shape == actual.shape # TODO add more tests for Affine .mode # TODO add more tests for Affine shear class TestAffine(unittest.TestCase): def test_get_parameters(self): aug = iaa.Affine(scale=1, translate_px=2, rotate=3, shear=4, order=1, cval=0, mode="constant", backend="cv2", fit_output=True) params = aug.get_parameters() assert is_parameter_instance(params[0], iap.Deterministic) # scale assert isinstance(params[1], tuple) # translate assert is_parameter_instance(params[2], iap.Deterministic) # rotate assert is_parameter_instance(params[3], iap.Deterministic) # shear assert params[0].value == 1 # scale assert params[1][0].value == 2 # translate assert params[2].value == 3 # rotate assert params[3].value == 4 # shear assert params[4].value == 1 # order assert params[5].value == 0 # cval assert params[6].value == "constant" # mode assert params[7] == "cv2" # backend assert params[8] is True # fit_output class TestAffine___init__(unittest.TestCase): def test___init___scale_is_stochastic_parameter(self): aug = iaa.Affine(scale=iap.Uniform(0.7, 0.9)) assert is_parameter_instance(aug.scale, iap.Uniform) assert is_parameter_instance(aug.scale.a, iap.Deterministic) assert is_parameter_instance(aug.scale.b, iap.Deterministic) assert 0.7 - 1e-8 < aug.scale.a.value < 0.7 + 1e-8 assert 0.9 - 1e-8 < aug.scale.b.value < 0.9 + 1e-8 def test___init___translate_percent_is_stochastic_parameter(self): aug = iaa.Affine(translate_percent=iap.Uniform(0.7, 0.9)) assert isinstance(aug.translate, tuple) assert is_parameter_instance(aug.translate[0], iap.Uniform) assert is_parameter_instance(aug.translate[0].a, iap.Deterministic) assert is_parameter_instance(aug.translate[0].b, iap.Deterministic) assert 0.7 - 1e-8 < aug.translate[0].a.value < 0.7 + 1e-8 assert 0.9 - 1e-8 < aug.translate[0].b.value < 0.9 + 1e-8 assert aug.translate[1] is None assert aug.translate[2] == "percent" def test___init___translate_px_is_stochastic_parameter(self): aug = iaa.Affine(translate_px=iap.DiscreteUniform(1, 10)) assert isinstance(aug.translate, tuple) assert is_parameter_instance(aug.translate[0], iap.DiscreteUniform) assert is_parameter_instance(aug.translate[0].a, iap.Deterministic) assert is_parameter_instance(aug.translate[0].b, iap.Deterministic) assert aug.translate[0].a.value == 1 assert aug.translate[0].b.value == 10 assert aug.translate[1] is None assert aug.translate[2] == "px" def test___init___rotate_is_stochastic_parameter(self): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=iap.Uniform(10, 20), shear=0) assert is_parameter_instance(aug.rotate, iap.Uniform) assert is_parameter_instance(aug.rotate.a, iap.Deterministic) assert aug.rotate.a.value == 10 assert is_parameter_instance(aug.rotate.b, iap.Deterministic) assert aug.rotate.b.value == 20 def test___init___shear_is_stochastic_parameter(self): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=0, shear=iap.Uniform(10, 20)) assert is_parameter_instance(aug.shear, iap.Uniform) assert is_parameter_instance(aug.shear.a, iap.Deterministic) assert aug.shear.a.value == 10 assert is_parameter_instance(aug.shear.b, iap.Deterministic) assert aug.shear.b.value == 20 def test___init___cval_is_all(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=ia.ALL) assert is_parameter_instance(aug.cval, iap.Uniform) assert is_parameter_instance(aug.cval.a, iap.Deterministic) assert is_parameter_instance(aug.cval.b, iap.Deterministic) assert aug.cval.a.value == 0 assert aug.cval.b.value == 255 def test___init___cval_is_stochastic_parameter(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=iap.DiscreteUniform(1, 5)) assert is_parameter_instance(aug.cval, iap.DiscreteUniform) assert is_parameter_instance(aug.cval.a, iap.Deterministic) assert is_parameter_instance(aug.cval.b, iap.Deterministic) assert aug.cval.a.value == 1 assert aug.cval.b.value == 5 def test___init___mode_is_all(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode=ia.ALL) assert is_parameter_instance(aug.mode, iap.Choice) def test___init___mode_is_string(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode="edge") assert is_parameter_instance(aug.mode, iap.Deterministic) assert aug.mode.value == "edge" def test___init___mode_is_list(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode=["constant", "edge"]) assert is_parameter_instance(aug.mode, iap.Choice) assert ( len(aug.mode.a) == 2 and "constant" in aug.mode.a and "edge" in aug.mode.a) def test___init___mode_is_stochastic_parameter(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode=iap.Choice(["constant", "edge"])) assert is_parameter_instance(aug.mode, iap.Choice) assert ( len(aug.mode.a) == 2 and "constant" in aug.mode.a and "edge" in aug.mode.a) def test___init___fit_output_is_true(self): aug = iaa.Affine(fit_output=True) assert aug.fit_output is True # ------------ # exceptions for bad inputs # ------------ def test___init___bad_datatype_for_scale_fails(self): with self.assertRaises(Exception): _ = iaa.Affine(scale=False) def test___init___bad_datatype_for_translate_px_fails(self): with self.assertRaises(Exception): _ = iaa.Affine(translate_px=False) def test___init___bad_datatype_for_translate_percent_fails(self): with self.assertRaises(Exception): _ = iaa.Affine(translate_percent=False) def test___init___bad_datatype_for_rotate_fails(self): with self.assertRaises(Exception): _ = iaa.Affine(scale=1.0, translate_px=0, rotate=False, shear=0, cval=0) def test___init___bad_datatype_for_shear_fails(self): with self.assertRaises(Exception): _ = iaa.Affine(scale=1.0, translate_px=0, rotate=0, shear=False, cval=0) def test___init___bad_datatype_for_cval_fails(self): with self.assertRaises(Exception): _ = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=None) def test___init___bad_datatype_for_mode_fails(self): with self.assertRaises(Exception): _ = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode=False) def test___init___bad_datatype_for_order_fails(self): # bad order datatype in case of backend=cv2 with self.assertRaises(Exception): _ = iaa.Affine(backend="cv2", order="test") def test___init___nonexistent_order_for_cv2_fails(self): # non-existent order in case of backend=cv2 with self.assertRaises(AssertionError): _ = iaa.Affine(backend="cv2", order=-1) # TODO add test with multiple images class TestAffine_noop(unittest.TestCase): def setUp(self): reseed() @property def base_img(self): base_img = np.array([[0, 0, 0], [0, 255, 0], [0, 0, 0]], dtype=np.uint8) return base_img[:, :, np.newaxis] @property def images(self): return np.array([self.base_img]) @property def kpsoi(self): kps = [ia.Keypoint(x=0, y=0), ia.Keypoint(x=1, y=1), ia.Keypoint(x=2, y=2)] return [ia.KeypointsOnImage(kps, shape=self.base_img.shape)] @property def psoi(self): polygons = [ia.Polygon([(0, 0), (2, 0), (2, 2)])] return [ia.PolygonsOnImage(polygons, shape=self.base_img.shape)] @property def lsoi(self): ls = [ia.LineString([(0, 0), (2, 0), (2, 2)])] return [ia.LineStringsOnImage(ls, shape=self.base_img.shape)] @property def bbsoi(self): bbs = [ia.BoundingBox(x1=0, y1=1, x2=2, y2=3)] return [ia.BoundingBoxesOnImage(bbs, shape=self.base_img.shape)] def test_image_noop(self): # no translation/scale/rotate/shear, shouldnt change nothing aug = iaa.Affine(scale=1.0, translate_px=0, rotate=0, shear=0) observed = aug.augment_images(self.images) expected = self.images assert np.array_equal(observed, expected) def test_image_noop__deterministic(self): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) expected = self.images assert np.array_equal(observed, expected) def test_image_noop__list(self): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=0, shear=0) observed = aug.augment_images([self.base_img]) expected = [self.base_img] assert array_equal_lists(observed, expected) def test_image_noop__list_and_deterministic(self): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.base_img]) expected = [self.base_img] assert array_equal_lists(observed, expected) def test_keypoints_noop(self): self._test_cba_noop("augment_keypoints", self.kpsoi, False) def test_keypoints_noop__deterministic(self): self._test_cba_noop("augment_keypoints", self.kpsoi, True) def test_polygons_noop(self): self._test_cba_noop("augment_polygons", self.psoi, False) def test_polygons_noop__deterministic(self): self._test_cba_noop("augment_polygons", self.psoi, True) def test_line_strings_noop(self): self._test_cba_noop("augment_line_strings", self.lsoi, False) def test_line_strings_noop__deterministic(self): self._test_cba_noop("augment_line_strings", self.lsoi, True) def test_bounding_boxes_noop(self): self._test_cba_noop("augment_bounding_boxes", self.bbsoi, False) def test_bounding_boxes_noop__deterministic(self): self._test_cba_noop("augment_bounding_boxes", self.bbsoi, True) @classmethod def _test_cba_noop(cls, augf_name, cbaoi, deterministic): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=0, shear=0) if deterministic: aug = aug.to_deterministic() observed = getattr(aug, augf_name)(cbaoi) expected = cbaoi assert_cbaois_equal(observed, expected) # TODO add test with multiple images class TestAffine_scale(unittest.TestCase): def setUp(self): reseed() # --------------------- # scale: zoom in # --------------------- @property def base_img(self): base_img = np.array([[0, 0, 0], [0, 255, 0], [0, 0, 0]], dtype=np.uint8) return base_img[:, :, np.newaxis] @property def images(self): return np.array([self.base_img]) @property def kpsoi(self): kps = [ia.Keypoint(x=0, y=0), ia.Keypoint(x=1, y=1), ia.Keypoint(x=2, y=2)] return [ia.KeypointsOnImage(kps, shape=self.base_img.shape)] def kpsoi_scaled(self, scale_y, scale_x): coords = np.array([ [0, 0], [1, 1], [2, 2] ], dtype=np.float32) coords_scaled = self._scale_coordinates(coords, scale_y, scale_x) return [ia.KeypointsOnImage.from_xy_array( coords_scaled, shape=self.base_img.shape)] @property def psoi(self): polys = [ia.Polygon([(0, 0), (0, 2), (2, 2)])] return [ia.PolygonsOnImage(polys, shape=self.base_img.shape)] def psoi_scaled(self, scale_y, scale_x): coords = np.array([ [0, 0], [0, 2], [2, 2] ], dtype=np.float32) coords_scaled = self._scale_coordinates(coords, scale_y, scale_x) return [ia.PolygonsOnImage( [ia.Polygon(coords_scaled)], shape=self.base_img.shape)] @property def lsoi(self): ls = [ia.LineString([(0, 0), (0, 2), (2, 2)])] return [ia.LineStringsOnImage(ls, shape=self.base_img.shape)] def lsoi_scaled(self, scale_y, scale_x): coords = np.array([ [0, 0], [0, 2], [2, 2] ], dtype=np.float32) coords_scaled = self._scale_coordinates(coords, scale_y, scale_x) return [ia.LineStringsOnImage( [ia.LineString(coords_scaled)], shape=self.base_img.shape)] @property def bbsoi(self): bbs = [ia.BoundingBox(x1=0, y1=1, x2=2, y2=3)] return [ia.BoundingBoxesOnImage(bbs, shape=self.base_img.shape)] def bbsoi_scaled(self, scale_y, scale_x): coords = np.array([ [0, 1], [2, 3] ], dtype=np.float32) coords_scaled = self._scale_coordinates(coords, scale_y, scale_x) return [ia.BoundingBoxesOnImage.from_xyxy_array( coords_scaled.reshape((1, 4)), shape=self.base_img.shape)] def _scale_coordinates(self, coords, scale_y, scale_x): height, width = self.base_img.shape[0:2] coords_scaled = [] for x, y in coords: # the additional +0.5 and -0.5 here makes up for the shift factor # used in the affine matrix generation offset = 0.0 x_centered = x - width/2 + offset y_centered = y - height/2 + offset x_new = x_centered * scale_x + width/2 - offset y_new = y_centered * scale_y + height/2 - offset coords_scaled.append((x_new, y_new)) return np.float32(coords_scaled) @property def scale_zoom_in_outer_pixels(self): base_img = self.base_img outer_pixels = ([], []) for i in sm.xrange(base_img.shape[0]): for j in sm.xrange(base_img.shape[1]): if i != j: outer_pixels[0].append(i) outer_pixels[1].append(j) return outer_pixels def test_image_scale_zoom_in(self): aug = iaa.Affine(scale=1.75, translate_px=0, rotate=0, shear=0) observed = aug.augment_images(self.images) outer_pixels = self.scale_zoom_in_outer_pixels assert observed[0][1, 1] > 250 assert (observed[0][outer_pixels[0], outer_pixels[1]] > 20).all() assert (observed[0][outer_pixels[0], outer_pixels[1]] < 150).all() def test_image_scale_zoom_in__deterministic(self): aug = iaa.Affine(scale=1.75, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) outer_pixels = self.scale_zoom_in_outer_pixels assert observed[0][1, 1] > 250 assert (observed[0][outer_pixels[0], outer_pixels[1]] > 20).all() assert (observed[0][outer_pixels[0], outer_pixels[1]] < 150).all() def test_image_scale_zoom_in__list(self): aug = iaa.Affine(scale=1.75, translate_px=0, rotate=0, shear=0) observed = aug.augment_images([self.base_img]) outer_pixels = self.scale_zoom_in_outer_pixels assert observed[0][1, 1] > 250 assert (observed[0][outer_pixels[0], outer_pixels[1]] > 20).all() assert (observed[0][outer_pixels[0], outer_pixels[1]] < 150).all() def test_image_scale_zoom_in__list_and_deterministic(self): aug = iaa.Affine(scale=1.75, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.base_img]) outer_pixels = self.scale_zoom_in_outer_pixels assert observed[0][1, 1] > 250 assert (observed[0][outer_pixels[0], outer_pixels[1]] > 20).all() assert (observed[0][outer_pixels[0], outer_pixels[1]] < 150).all() def test_keypoints_scale_zoom_in(self): self._test_cba_scale( "augment_keypoints", 1.75, self.kpsoi, self.kpsoi_scaled(1.75, 1.75), False) def test_keypoints_scale_zoom_in__deterministic(self): self._test_cba_scale( "augment_keypoints", 1.75, self.kpsoi, self.kpsoi_scaled(1.75, 1.75), True) def test_polygons_scale_zoom_in(self): self._test_cba_scale( "augment_polygons", 1.75, self.psoi, self.psoi_scaled(1.75, 1.75), False) def test_polygons_scale_zoom_in__deterministic(self): self._test_cba_scale( "augment_polygons", 1.75, self.psoi, self.psoi_scaled(1.75, 1.75), True) def test_line_strings_scale_zoom_in(self): self._test_cba_scale( "augment_line_strings", 1.75, self.lsoi, self.lsoi_scaled(1.75, 1.75), False) def test_line_strings_scale_zoom_in__deterministic(self): self._test_cba_scale( "augment_line_strings", 1.75, self.lsoi, self.lsoi_scaled(1.75, 1.75), True) def test_bounding_boxes_scale_zoom_in(self): self._test_cba_scale( "augment_bounding_boxes", 1.75, self.bbsoi, self.bbsoi_scaled(1.75, 1.75), False) def test_bounding_boxes_scale_zoom_in__deterministic(self): self._test_cba_scale( "augment_bounding_boxes", 1.75, self.bbsoi, self.bbsoi_scaled(1.75, 1.75), True) @classmethod def _test_cba_scale(cls, augf_name, scale, cbaoi, cbaoi_scaled, deterministic): aug = iaa.Affine(scale=scale, translate_px=0, rotate=0, shear=0) if deterministic: aug = aug.to_deterministic() observed = getattr(aug, augf_name)(cbaoi) assert_cbaois_equal(observed, cbaoi_scaled) # --------------------- # scale: zoom in only on x axis # --------------------- def test_image_scale_zoom_in_only_x_axis(self): aug = iaa.Affine(scale={"x": 1.75, "y": 1.0}, translate_px=0, rotate=0, shear=0) observed = aug.augment_images(self.images) assert observed[0][1, 1] > 250 assert (observed[0][[1, 1], [0, 2]] > 20).all() assert (observed[0][[1, 1], [0, 2]] < 150).all() assert (observed[0][0, :] < 5).all() assert (observed[0][2, :] < 5).all() def test_image_scale_zoom_in_only_x_axis__deterministic(self): aug = iaa.Affine(scale={"x": 1.75, "y": 1.0}, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) assert observed[0][1, 1] > 250 assert (observed[0][[1, 1], [0, 2]] > 20).all() assert (observed[0][[1, 1], [0, 2]] < 150).all() assert (observed[0][0, :] < 5).all() assert (observed[0][2, :] < 5).all() def test_image_scale_zoom_in_only_x_axis__list(self): aug = iaa.Affine(scale={"x": 1.75, "y": 1.0}, translate_px=0, rotate=0, shear=0) observed = aug.augment_images([self.base_img]) assert observed[0][1, 1] > 250 assert (observed[0][[1, 1], [0, 2]] > 20).all() assert (observed[0][[1, 1], [0, 2]] < 150).all() assert (observed[0][0, :] < 5).all() assert (observed[0][2, :] < 5).all() def test_image_scale_zoom_in_only_x_axis__deterministic_and_list(self): aug = iaa.Affine(scale={"x": 1.75, "y": 1.0}, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.base_img]) assert observed[0][1, 1] > 250 assert (observed[0][[1, 1], [0, 2]] > 20).all() assert (observed[0][[1, 1], [0, 2]] < 150).all() assert (observed[0][0, :] < 5).all() assert (observed[0][2, :] < 5).all() def test_keypoints_scale_zoom_in_only_x_axis(self): self._test_cba_scale( "augment_keypoints", {"y": 1.0, "x": 1.75}, self.kpsoi, self.kpsoi_scaled(1.0, 1.75), False) def test_keypoints_scale_zoom_in_only_x_axis__deterministic(self): self._test_cba_scale( "augment_keypoints", {"y": 1.0, "x": 1.75}, self.kpsoi, self.kpsoi_scaled(1.0, 1.75), True) def test_polygons_scale_zoom_in_only_x_axis(self): self._test_cba_scale( "augment_polygons", {"y": 1.0, "x": 1.75}, self.psoi, self.psoi_scaled(1.0, 1.75), False) def test_polygons_scale_zoom_in_only_x_axis__deterministic(self): self._test_cba_scale( "augment_polygons", {"y": 1.0, "x": 1.75}, self.psoi, self.psoi_scaled(1.0, 1.75), True) def test_line_strings_scale_zoom_in_only_x_axis(self): self._test_cba_scale( "augment_line_strings", {"y": 1.0, "x": 1.75}, self.lsoi, self.lsoi_scaled(1.0, 1.75), False) def test_line_strings_scale_zoom_in_only_x_axis__deterministic(self): self._test_cba_scale( "augment_line_strings", {"y": 1.0, "x": 1.75}, self.lsoi, self.lsoi_scaled(1.0, 1.75), True) def test_bounding_boxes_scale_zoom_in_only_x_axis(self): self._test_cba_scale( "augment_bounding_boxes", {"y": 1.0, "x": 1.75}, self.bbsoi, self.bbsoi_scaled(1.0, 1.75), False) def test_bounding_boxes_scale_zoom_in_only_x_axis__deterministic(self): self._test_cba_scale( "augment_bounding_boxes", {"y": 1.0, "x": 1.75}, self.bbsoi, self.bbsoi_scaled(1.0, 1.75), True) # --------------------- # scale: zoom in only on y axis # --------------------- def test_image_scale_zoom_in_only_y_axis(self): aug = iaa.Affine(scale={"x": 1.0, "y": 1.75}, translate_px=0, rotate=0, shear=0) observed = aug.augment_images(self.images) assert observed[0][1, 1] > 250 assert (observed[0][[0, 2], [1, 1]] > 20).all() assert (observed[0][[0, 2], [1, 1]] < 150).all() assert (observed[0][:, 0] < 5).all() assert (observed[0][:, 2] < 5).all() def test_image_scale_zoom_in_only_y_axis__deterministic(self): aug = iaa.Affine(scale={"x": 1.0, "y": 1.75}, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) assert observed[0][1, 1] > 250 assert (observed[0][[0, 2], [1, 1]] > 20).all() assert (observed[0][[0, 2], [1, 1]] < 150).all() assert (observed[0][:, 0] < 5).all() assert (observed[0][:, 2] < 5).all() def test_image_scale_zoom_in_only_y_axis__list(self): aug = iaa.Affine(scale={"x": 1.0, "y": 1.75}, translate_px=0, rotate=0, shear=0) observed = aug.augment_images([self.base_img]) assert observed[0][1, 1] > 250 assert (observed[0][[0, 2], [1, 1]] > 20).all() assert (observed[0][[0, 2], [1, 1]] < 150).all() assert (observed[0][:, 0] < 5).all() assert (observed[0][:, 2] < 5).all() def test_image_scale_zoom_in_only_y_axis__deterministic_and_list(self): aug = iaa.Affine(scale={"x": 1.0, "y": 1.75}, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.base_img]) assert observed[0][1, 1] > 250 assert (observed[0][[0, 2], [1, 1]] > 20).all() assert (observed[0][[0, 2], [1, 1]] < 150).all() assert (observed[0][:, 0] < 5).all() assert (observed[0][:, 2] < 5).all() def test_keypoints_scale_zoom_in_only_y_axis(self): self._test_cba_scale( "augment_keypoints", {"y": 1.75, "x": 1.0}, self.kpsoi, self.kpsoi_scaled(1.75, 1.0), False) def test_keypoints_scale_zoom_in_only_y_axis__deterministic(self): self._test_cba_scale( "augment_keypoints", {"y": 1.75, "x": 1.0}, self.kpsoi, self.kpsoi_scaled(1.75, 1.0), True) def test_polygons_scale_zoom_in_only_y_axis(self): self._test_cba_scale( "augment_polygons", {"y": 1.75, "x": 1.0}, self.psoi, self.psoi_scaled(1.75, 1.0), False) def test_polygons_scale_zoom_in_only_y_axis__deterministic(self): self._test_cba_scale( "augment_polygons", {"y": 1.75, "x": 1.0}, self.psoi, self.psoi_scaled(1.75, 1.0), True) def test_line_strings_scale_zoom_in_only_y_axis(self): self._test_cba_scale( "augment_polygons", {"y": 1.75, "x": 1.0}, self.psoi, self.psoi_scaled(1.75, 1.0), False) def test_line_strings_scale_zoom_in_only_y_axis__deterministic(self): self._test_cba_scale( "augment_line_strings", {"y": 1.75, "x": 1.0}, self.lsoi, self.lsoi_scaled(1.75, 1.0), True) def test_bounding_boxes_scale_zoom_in_only_y_axis(self): self._test_cba_scale( "augment_bounding_boxes", {"y": 1.75, "x": 1.0}, self.bbsoi, self.bbsoi_scaled(1.75, 1.0), False) def test_bounding_boxes_scale_zoom_in_only_y_axis__deterministic(self): self._test_cba_scale( "augment_bounding_boxes", {"y": 1.75, "x": 1.0}, self.bbsoi, self.bbsoi_scaled(1.75, 1.0), True) # --------------------- # scale: zoom out # --------------------- # these tests use a 4x4 area of all 255, which is zoomed out to a 4x4 area # in which the center 2x2 area is 255 # zoom in should probably be adapted to this style # no separate tests here for x/y axis, should work fine if zoom in works # with that @property def scale_zoom_out_base_img(self): return np.ones((4, 4, 1), dtype=np.uint8) * 255 @property def scale_zoom_out_images(self): return np.array([self.scale_zoom_out_base_img]) @property def scale_zoom_out_outer_pixels(self): outer_pixels = ([], []) for y in sm.xrange(4): xs = sm.xrange(4) if y in [0, 3] else [0, 3] for x in xs: outer_pixels[0].append(y) outer_pixels[1].append(x) return outer_pixels @property def scale_zoom_out_inner_pixels(self): return [1, 1, 2, 2], [1, 2, 1, 2] @property def scale_zoom_out_kpsoi(self): kps = [ia.Keypoint(x=0, y=0), ia.Keypoint(x=3, y=0), ia.Keypoint(x=0, y=3), ia.Keypoint(x=3, y=3)] return [ia.KeypointsOnImage(kps, shape=self.scale_zoom_out_base_img.shape)] @property def scale_zoom_out_kpsoi_aug(self): kps_aug = [ia.Keypoint(x=0.765, y=0.765), ia.Keypoint(x=2.235, y=0.765), ia.Keypoint(x=0.765, y=2.235), ia.Keypoint(x=2.235, y=2.235)] return [ia.KeypointsOnImage(kps_aug, shape=self.scale_zoom_out_base_img.shape)] def test_image_scale_zoom_out(self): aug = iaa.Affine(scale=0.49, translate_px=0, rotate=0, shear=0) observed = aug.augment_images(self.scale_zoom_out_images) outer_pixels = self.scale_zoom_out_outer_pixels inner_pixels = self.scale_zoom_out_inner_pixels assert (observed[0][outer_pixels] < 25).all() assert (observed[0][inner_pixels] > 200).all() def test_image_scale_zoom_out__deterministic(self): aug = iaa.Affine(scale=0.49, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.scale_zoom_out_images) outer_pixels = self.scale_zoom_out_outer_pixels inner_pixels = self.scale_zoom_out_inner_pixels assert (observed[0][outer_pixels] < 25).all() assert (observed[0][inner_pixels] > 200).all() def test_image_scale_zoom_out__list(self): aug = iaa.Affine(scale=0.49, translate_px=0, rotate=0, shear=0) observed = aug.augment_images([self.scale_zoom_out_base_img]) outer_pixels = self.scale_zoom_out_outer_pixels inner_pixels = self.scale_zoom_out_inner_pixels assert (observed[0][outer_pixels] < 25).all() assert (observed[0][inner_pixels] > 200).all() def test_image_scale_zoom_out__list_and_deterministic(self): aug = iaa.Affine(scale=0.49, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.scale_zoom_out_base_img]) outer_pixels = self.scale_zoom_out_outer_pixels inner_pixels = self.scale_zoom_out_inner_pixels assert (observed[0][outer_pixels] < 25).all() assert (observed[0][inner_pixels] > 200).all() def test_keypoints_scale_zoom_out(self): self._test_cba_scale( "augment_keypoints", 0.49, self.kpsoi, self.kpsoi_scaled(0.49, 0.49), False) def test_keypoints_scale_zoom_out__deterministic(self): self._test_cba_scale( "augment_keypoints", 0.49, self.kpsoi, self.kpsoi_scaled(0.49, 0.49), True) def test_polygons_scale_zoom_out(self): self._test_cba_scale( "augment_polygons", 0.49, self.psoi, self.psoi_scaled(0.49, 0.49), False) def test_polygons_scale_zoom_out__deterministic(self): self._test_cba_scale( "augment_polygons", 0.49, self.psoi, self.psoi_scaled(0.49, 0.49), True) def test_line_strings_scale_zoom_out(self): self._test_cba_scale( "augment_line_strings", 0.49, self.lsoi, self.lsoi_scaled(0.49, 0.49), False) def test_line_strings_scale_zoom_out__deterministic(self): self._test_cba_scale( "augment_line_strings", 0.49, self.lsoi, self.lsoi_scaled(0.49, 0.49), True) def test_bounding_boxes_scale_zoom_out(self): self._test_cba_scale( "augment_bounding_boxes", 0.49, self.bbsoi, self.bbsoi_scaled(0.49, 0.49), False) def test_bounding_boxes_scale_zoom_out__deterministic(self): self._test_cba_scale( "augment_bounding_boxes", 0.49, self.bbsoi, self.bbsoi_scaled(0.49, 0.49), True) # --------------------- # scale: x and y axis are both tuples # --------------------- def test_image_x_and_y_axis_are_tuples(self): aug = iaa.Affine(scale={"x": (0.5, 1.5), "y": (0.5, 1.5)}, translate_px=0, rotate=0, shear=0) image = np.array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 2, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], dtype=np.uint8) * 100 image = image[:, :, np.newaxis] images = np.array([image]) last_aug = None nb_changed_aug = 0 nb_iterations = 1000 for i in sm.xrange(nb_iterations): observed_aug = aug.augment_images(images) if i == 0: last_aug = observed_aug else: if not np.array_equal(observed_aug, last_aug): nb_changed_aug += 1 last_aug = observed_aug assert nb_changed_aug >= int(nb_iterations * 0.8) def test_image_x_and_y_axis_are_tuples__deterministic(self): aug = iaa.Affine(scale={"x": (0.5, 1.5), "y": (0.5, 1.5)}, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() image = np.array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 2, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], dtype=np.uint8) * 100 image = image[:, :, np.newaxis] images = np.array([image]) last_aug_det = None nb_changed_aug_det = 0 nb_iterations = 10 for i in sm.xrange(nb_iterations): observed_aug_det = aug_det.augment_images(images) if i == 0: last_aug_det = observed_aug_det else: if not np.array_equal(observed_aug_det, last_aug_det): nb_changed_aug_det += 1 last_aug_det = observed_aug_det assert nb_changed_aug_det == 0 # ------------ # alignment # TODO add alignment tests for: BBs, Polys, LS # ------------ def test_keypoint_alignment(self): image = np.zeros((100, 100), dtype=np.uint8) image[40-1:40+2, 40-1:40+2] = 255 image[40-1:40+2, 60-1:60+2] = 255 kps = [ia.Keypoint(x=40, y=40), ia.Keypoint(x=60, y=40)] kpsoi = ia.KeypointsOnImage(kps, shape=image.shape) images = [image, image, image] kpsois = [kpsoi.deepcopy(), ia.KeypointsOnImage([], shape=image.shape), kpsoi.deepcopy()] aug = iaa.Affine(scale=[0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7], order=0) for iter in sm.xrange(40): images_aug, kpsois_aug = aug(images=images, keypoints=kpsois) assert kpsois_aug[1].empty for i in [0, 2]: image_aug = images_aug[i] kpsoi_aug = kpsois_aug[i] for kp in kpsoi_aug.keypoints: value = image_aug[int(kp.y), int(kp.x)] assert value > 200 # ------------ # make sure that polygons stay valid upon extreme scaling # ------------ def test_polygons_stay_valid_when_using_extreme_scalings(self): scales = [1e-4, 1e-2, 1e2, 1e4] backends = ["auto", "cv2", "skimage"] orders = [0, 1, 3] gen = itertools.product(scales, backends, orders) for scale, backend, order in gen: with self.subTest(scale=scale, backend=backend, order=order): aug = iaa.Affine(scale=scale, order=order) psoi = ia.PolygonsOnImage([ ia.Polygon([(0, 0), (10, 0), (5, 5)])], shape=(10, 10)) psoi_aug = aug.augment_polygons(psoi) poly = psoi_aug.polygons[0] ext = poly.exterior assert poly.is_valid assert ext[0][0] < ext[2][0] < ext[1][0] assert ext[0][1] < ext[2][1] assert np.allclose(ext[0][1], ext[1][1]) class TestAffine_translate(unittest.TestCase): def setUp(self): reseed() @property def image(self): return np.uint8([ [0, 0, 0], [0, 1, 0], [0, 0, 0] ])[:, :, np.newaxis] @property def image_1px_right(self): return np.uint8([ [0, 0, 0], [0, 0, 1], [0, 0, 0] ])[:, :, np.newaxis] @property def image_1px_bottom(self): return np.uint8([ [0, 0, 0], [0, 0, 0], [0, 1, 0] ])[:, :, np.newaxis] @property def images(self): return np.array([self.image]) @property def images_1px_right(self): return np.array([self.image_1px_right]) @property def images_1px_bottom(self): return np.array([self.image_1px_bottom]) @property def kpsoi(self): kps = [ia.Keypoint(x=1, y=1)] return [ia.KeypointsOnImage(kps, shape=self.image.shape)] @property def kpsoi_1px_right(self): kps = [ia.Keypoint(x=2, y=1)] return [ia.KeypointsOnImage(kps, shape=self.image.shape)] @property def kpsoi_1px_bottom(self): kps = [ia.Keypoint(x=1, y=2)] return [ia.KeypointsOnImage(kps, shape=self.image.shape)] @property def psoi(self): polys = [ia.Polygon([(0, 0), (2, 0), (2, 2)])] return [ia.PolygonsOnImage(polys, shape=self.image.shape)] @property def psoi_1px_right(self): polys = [ia.Polygon([(0+1, 0), (2+1, 0), (2+1, 2)])] return [ia.PolygonsOnImage(polys, shape=self.image.shape)] @property def psoi_1px_bottom(self): polys = [ia.Polygon([(0, 0+1), (2, 0+1), (2, 2+1)])] return [ia.PolygonsOnImage(polys, shape=self.image.shape)] @property def lsoi(self): ls = [ia.LineString([(0, 0), (2, 0), (2, 2)])] return [ia.LineStringsOnImage(ls, shape=self.image.shape)] @property def lsoi_1px_right(self): ls = [ia.LineString([(0+1, 0), (2+1, 0), (2+1, 2)])] return [ia.LineStringsOnImage(ls, shape=self.image.shape)] @property def lsoi_1px_bottom(self): ls = [ia.LineString([(0, 0+1), (2, 0+1), (2, 2+1)])] return [ia.LineStringsOnImage(ls, shape=self.image.shape)] @property def bbsoi(self): bbs = [ia.BoundingBox(x1=0, y1=1, x2=2, y2=3)] return [ia.BoundingBoxesOnImage(bbs, shape=self.image.shape)] @property def bbsoi_1px_right(self): bbs = [ia.BoundingBox(x1=0+1, y1=1, x2=2+1, y2=3)] return [ia.BoundingBoxesOnImage(bbs, shape=self.image.shape)] @property def bbsoi_1px_bottom(self): bbs = [ia.BoundingBox(x1=0, y1=1+1, x2=2, y2=3+1)] return [ia.BoundingBoxesOnImage(bbs, shape=self.image.shape)] # --------------------- # translate: move one pixel to the right # --------------------- def test_image_translate_1px_right(self): # move one pixel to the right aug = iaa.Affine(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0) observed = aug.augment_images(self.images) assert np.array_equal(observed, self.images_1px_right) def test_image_translate_1px_right__deterministic(self): aug = iaa.Affine(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) assert np.array_equal(observed, self.images_1px_right) def test_image_translate_1px_right__list(self): aug = iaa.Affine(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0) observed = aug.augment_images([self.image]) assert array_equal_lists(observed, [self.image_1px_right]) def test_image_translate_1px_right__list_and_deterministic(self): aug = iaa.Affine(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.image]) assert array_equal_lists(observed, [self.image_1px_right]) def test_keypoints_translate_1px_right(self): self._test_cba_translate_px( "augment_keypoints", {"x": 1, "y": 0}, self.kpsoi, self.kpsoi_1px_right, False) def test_keypoints_translate_1px_right__deterministic(self): self._test_cba_translate_px( "augment_keypoints", {"x": 1, "y": 0}, self.kpsoi, self.kpsoi_1px_right, True) def test_polygons_translate_1px_right(self): self._test_cba_translate_px( "augment_polygons", {"x": 1, "y": 0}, self.psoi, self.psoi_1px_right, False) def test_polygons_translate_1px_right__deterministic(self): self._test_cba_translate_px( "augment_polygons", {"x": 1, "y": 0}, self.psoi, self.psoi_1px_right, True) def test_line_strings_translate_1px_right(self): self._test_cba_translate_px( "augment_line_strings", {"x": 1, "y": 0}, self.lsoi, self.lsoi_1px_right, False) def test_line_strings_translate_1px_right__deterministic(self): self._test_cba_translate_px( "augment_line_strings", {"x": 1, "y": 0}, self.lsoi, self.lsoi_1px_right, True) def test_bounding_boxes_translate_1px_right(self): self._test_cba_translate_px( "augment_bounding_boxes", {"x": 1, "y": 0}, self.bbsoi, self.bbsoi_1px_right, False) def test_bounding_boxes_translate_1px_right__deterministic(self): self._test_cba_translate_px( "augment_bounding_boxes", {"x": 1, "y": 0}, self.bbsoi, self.bbsoi_1px_right, True) @classmethod def _test_cba_translate_px(cls, augf_name, px, cbaoi, cbaoi_translated, deterministic): aug = iaa.Affine(scale=1.0, translate_px=px, rotate=0, shear=0) if deterministic: aug = aug.to_deterministic() observed = getattr(aug, augf_name)(cbaoi) assert_cbaois_equal(observed, cbaoi_translated) def test_image_translate_1px_right_skimage(self): # move one pixel to the right # with backend = skimage aug = iaa.Affine(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0, backend="skimage") observed = aug.augment_images(self.images) assert np.array_equal(observed, self.images_1px_right) def test_image_translate_1px_right_skimage_order_all(self): # move one pixel to the right # with backend = skimage, order=ALL aug = iaa.Affine(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0, backend="skimage", order=ia.ALL) observed = aug.augment_images(self.images) assert np.array_equal(observed, self.images_1px_right) def test_image_translate_1px_right_skimage_order_is_list(self): # move one pixel to the right # with backend = skimage, order=list aug = iaa.Affine(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0, backend="skimage", order=[0, 1, 3]) observed = aug.augment_images(self.images) assert np.array_equal(observed, self.images_1px_right) def test_image_translate_1px_right_cv2_order_is_list(self): # move one pixel to the right # with backend = cv2, order=list aug = iaa.Affine(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0, backend="cv2", order=[0, 1, 3]) observed = aug.augment_images(self.images) assert np.array_equal(observed, self.images_1px_right) def test_image_translate_1px_right_cv2_order_is_stoch_param(self): # move one pixel to the right # with backend = cv2, order=StochasticParameter aug = iaa.Affine(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0, backend="cv2", order=iap.Choice([0, 1, 3])) observed = aug.augment_images(self.images) assert np.array_equal(observed, self.images_1px_right) # --------------------- # translate: move one pixel to the bottom # --------------------- def test_image_translate_1px_bottom(self): aug = iaa.Affine(scale=1.0, translate_px={"x": 0, "y": 1}, rotate=0, shear=0) observed = aug.augment_images(self.images) assert np.array_equal(observed, self.images_1px_bottom) def test_image_translate_1px_bottom__deterministic(self): aug = iaa.Affine(scale=1.0, translate_px={"x": 0, "y": 1}, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) assert np.array_equal(observed, self.images_1px_bottom) def test_image_translate_1px_bottom__list(self): aug = iaa.Affine(scale=1.0, translate_px={"x": 0, "y": 1}, rotate=0, shear=0) observed = aug.augment_images([self.image]) assert array_equal_lists(observed, [self.image_1px_bottom]) def test_image_translate_1px_bottom__list_and_deterministic(self): aug = iaa.Affine(scale=1.0, translate_px={"x": 0, "y": 1}, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.image]) assert array_equal_lists(observed, [self.image_1px_bottom]) def test_keypoints_translate_1px_bottom(self): self._test_cba_translate_px( "augment_keypoints", {"x": 0, "y": 1}, self.kpsoi, self.kpsoi_1px_bottom, False) def test_keypoints_translate_1px_bottom__deterministic(self): self._test_cba_translate_px( "augment_keypoints", {"x": 0, "y": 1}, self.kpsoi, self.kpsoi_1px_bottom, True) def test_polygons_translate_1px_bottom(self): self._test_cba_translate_px( "augment_polygons", {"x": 0, "y": 1}, self.psoi, self.psoi_1px_bottom, False) def test_polygons_translate_1px_bottom__deterministic(self): self._test_cba_translate_px( "augment_polygons", {"x": 0, "y": 1}, self.psoi, self.psoi_1px_bottom, True) def test_line_strings_translate_1px_bottom(self): self._test_cba_translate_px( "augment_line_strings", {"x": 0, "y": 1}, self.lsoi, self.lsoi_1px_bottom, False) def test_line_strings_translate_1px_bottom__deterministic(self): self._test_cba_translate_px( "augment_line_strings", {"x": 0, "y": 1}, self.lsoi, self.lsoi_1px_bottom, True) def test_bounding_boxes_translate_1px_bottom(self): self._test_cba_translate_px( "augment_bounding_boxes", {"x": 0, "y": 1}, self.bbsoi, self.bbsoi_1px_bottom, False) def test_bounding_boxes_translate_1px_bottom__deterministic(self): self._test_cba_translate_px( "augment_bounding_boxes", {"x": 0, "y": 1}, self.bbsoi, self.bbsoi_1px_bottom, True) # --------------------- # translate: fraction of the image size (towards the right) # --------------------- def test_image_translate_33percent_right(self): aug = iaa.Affine(scale=1.0, translate_percent={"x": 0.3333, "y": 0}, rotate=0, shear=0) observed = aug.augment_images(self.images) assert np.array_equal(observed, self.images_1px_right) def test_image_translate_33percent_right__deterministic(self): aug = iaa.Affine(scale=1.0, translate_percent={"x": 0.3333, "y": 0}, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) assert np.array_equal(observed, self.images_1px_right) def test_image_translate_33percent_right__list(self): aug = iaa.Affine(scale=1.0, translate_percent={"x": 0.3333, "y": 0}, rotate=0, shear=0) observed = aug.augment_images([self.image]) assert array_equal_lists(observed, [self.image_1px_right]) def test_image_translate_33percent_right__list_and_deterministic(self): aug = iaa.Affine(scale=1.0, translate_percent={"x": 0.3333, "y": 0}, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.image]) assert array_equal_lists(observed, [self.image_1px_right]) def test_keypoints_translate_33percent_right(self): self._test_cba_translate_percent( "augment_keypoints", {"x": 0.3333, "y": 0}, self.kpsoi, self.kpsoi_1px_right, False) def test_keypoints_translate_33percent_right__deterministic(self): self._test_cba_translate_percent( "augment_keypoints", {"x": 0.3333, "y": 0}, self.kpsoi, self.kpsoi_1px_right, True) def test_polygons_translate_33percent_right(self): self._test_cba_translate_percent( "augment_polygons", {"x": 0.3333, "y": 0}, self.psoi, self.psoi_1px_right, False) def test_polygons_translate_33percent_right__deterministic(self): self._test_cba_translate_percent( "augment_polygons", {"x": 0.3333, "y": 0}, self.psoi, self.psoi_1px_right, True) def test_line_strings_translate_33percent_right(self): self._test_cba_translate_percent( "augment_line_strings", {"x": 0.3333, "y": 0}, self.lsoi, self.lsoi_1px_right, False) def test_line_strings_translate_33percent_right__deterministic(self): self._test_cba_translate_percent( "augment_line_strings", {"x": 0.3333, "y": 0}, self.lsoi, self.lsoi_1px_right, True) def test_bounding_boxes_translate_33percent_right(self): self._test_cba_translate_percent( "augment_bounding_boxes", {"x": 0.3333, "y": 0}, self.bbsoi, self.bbsoi_1px_right, False) def test_bounding_boxes_translate_33percent_right__deterministic(self): self._test_cba_translate_percent( "augment_bounding_boxes", {"x": 0.3333, "y": 0}, self.bbsoi, self.bbsoi_1px_right, True) def test_keypoints_with_continuous_param_results_in_absolute_shift(self): # This test ensures that t ~ uniform(a, b) results in a translation # by t pixels and not t% # see issue #505 # use iap.Uniform() here to ensure that is really a float value that # is sampled and not accidentally DisceteUniform aug = iaa.Affine(translate_px=iap.Uniform(10, 20)) kps = [ia.Keypoint(x=10, y=10)] kpsoi = ia.KeypointsOnImage(kps, shape=(1000, 1000)) for _ in np.arange(5): kpsoi_aug = aug.augment_keypoints(kpsoi) kp_aug = kpsoi_aug.keypoints[0] assert 10+10 <= kp_aug.x <= 10+20 assert 10+10 <= kp_aug.y <= 10+20 @classmethod def _test_cba_translate_percent(cls, augf_name, percent, cbaoi, cbaoi_translated, deterministic): aug = iaa.Affine(scale=1.0, translate_percent=percent, rotate=0, shear=0) if deterministic: aug = aug.to_deterministic() observed = getattr(aug, augf_name)(cbaoi) assert_cbaois_equal(observed, cbaoi_translated, max_distance=1e-3) # --------------------- # translate: fraction of the image size (towards the bottom) # --------------------- def test_image_translate_33percent_bottom(self): # move 33% (one pixel) to the bottom aug = iaa.Affine(scale=1.0, translate_percent={"x": 0, "y": 0.3333}, rotate=0, shear=0) observed = aug.augment_images(self.images) assert np.array_equal(observed, self.images_1px_bottom) def test_image_translate_33percent_bottom__deterministic(self): aug = iaa.Affine(scale=1.0, translate_percent={"x": 0, "y": 0.3333}, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) assert np.array_equal(observed, self.images_1px_bottom) def test_image_translate_33percent_bottom__list(self): aug = iaa.Affine(scale=1.0, translate_percent={"x": 0, "y": 0.3333}, rotate=0, shear=0) observed = aug.augment_images([self.image]) assert array_equal_lists(observed, [self.image_1px_bottom]) def test_image_translate_33percent_bottom__list_and_deterministic(self): aug = iaa.Affine(scale=1.0, translate_percent={"x": 0, "y": 0.3333}, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.image]) assert array_equal_lists(observed, [self.image_1px_bottom]) def test_keypoints_translate_33percent_bottom(self): self._test_cba_translate_percent( "augment_keypoints", {"x": 0, "y": 0.3333}, self.kpsoi, self.kpsoi_1px_bottom, False) def test_keypoints_translate_33percent_bottom__deterministic(self): self._test_cba_translate_percent( "augment_keypoints", {"x": 0, "y": 0.3333}, self.kpsoi, self.kpsoi_1px_bottom, True) def test_polygons_translate_33percent_bottom(self): self._test_cba_translate_percent( "augment_polygons", {"x": 0, "y": 0.3333}, self.psoi, self.psoi_1px_bottom, False) def test_polygons_translate_33percent_bottom__deterministic(self): self._test_cba_translate_percent( "augment_polygons", {"x": 0, "y": 0.3333}, self.psoi, self.psoi_1px_bottom, True) def test_line_strings_translate_33percent_bottom(self): self._test_cba_translate_percent( "augment_line_strings", {"x": 0, "y": 0.3333}, self.lsoi, self.lsoi_1px_bottom, False) def test_line_strings_translate_33percent_bottom__deterministic(self): self._test_cba_translate_percent( "augment_line_strings", {"x": 0, "y": 0.3333}, self.lsoi, self.lsoi_1px_bottom, True) def test_bounding_boxes_translate_33percent_bottom(self): self._test_cba_translate_percent( "augment_bounding_boxes", {"x": 0, "y": 0.3333}, self.bbsoi, self.bbsoi_1px_bottom, False) def test_bounding_boxes_translate_33percent_bottom__deterministic(self): self._test_cba_translate_percent( "augment_bounding_boxes", {"x": 0, "y": 0.3333}, self.bbsoi, self.bbsoi_1px_bottom, True) # --------------------- # translate: axiswise uniform distributions # --------------------- def test_image_translate_by_axiswise_uniform_distributions(self): # 0-1px to left/right and 0-1px to top/bottom aug = iaa.Affine(scale=1.0, translate_px={"x": (-1, 1), "y": (-1, 1)}, rotate=0, shear=0) last_aug = None nb_changed_aug = 0 nb_iterations = 1000 centers_aug = self.image.astype(np.int32) * 0 for i in sm.xrange(nb_iterations): observed_aug = aug.augment_images(self.images) if i == 0: last_aug = observed_aug else: if not np.array_equal(observed_aug, last_aug): nb_changed_aug += 1 last_aug = observed_aug assert len(observed_aug[0].nonzero()[0]) == 1 centers_aug += (observed_aug[0] > 0) assert nb_changed_aug >= int(nb_iterations * 0.7) assert (centers_aug > int(nb_iterations * (1/9 * 0.6))).all() assert (centers_aug < int(nb_iterations * (1/9 * 1.4))).all() def test_image_translate_by_axiswise_uniform_distributions__det(self): # 0-1px to left/right and 0-1px to top/bottom aug = iaa.Affine(scale=1.0, translate_px={"x": (-1, 1), "y": (-1, 1)}, rotate=0, shear=0) aug_det = aug.to_deterministic() last_aug_det = None nb_changed_aug_det = 0 nb_iterations = 10 centers_aug_det = self.image.astype(np.int32) * 0 for i in sm.xrange(nb_iterations): observed_aug_det = aug_det.augment_images(self.images) if i == 0: last_aug_det = observed_aug_det else: if not np.array_equal(observed_aug_det, last_aug_det): nb_changed_aug_det += 1 last_aug_det = observed_aug_det assert len(observed_aug_det[0].nonzero()[0]) == 1 centers_aug_det += (observed_aug_det[0] > 0) assert nb_changed_aug_det == 0 # --------------------- # translate heatmaps # --------------------- @property def heatmaps(self): return ia.HeatmapsOnImage( np.float32([ [0.0, 0.5, 0.75], [0.0, 0.5, 0.75], [0.75, 0.75, 0.75], ]), shape=(3, 3, 3) ) @property def heatmaps_1px_right(self): return ia.HeatmapsOnImage( np.float32([ [0.0, 0.0, 0.5], [0.0, 0.0, 0.5], [0.0, 0.75, 0.75], ]), shape=(3, 3, 3) ) def test_heatmaps_translate_1px_right(self): aug = iaa.Affine(translate_px={"x": 1}) observed = aug.augment_heatmaps([self.heatmaps])[0] _assert_same_shape(observed, self.heatmaps) _assert_same_min_max(observed, self.heatmaps) assert np.array_equal(observed.get_arr(), self.heatmaps_1px_right.get_arr()) def test_heatmaps_translate_1px_right_should_ignore_cval(self): # should still use mode=constant cval=0 even when other settings chosen aug = iaa.Affine(translate_px={"x": 1}, cval=255) observed = aug.augment_heatmaps([self.heatmaps])[0] _assert_same_shape(observed, self.heatmaps) _assert_same_min_max(observed, self.heatmaps) assert np.array_equal(observed.get_arr(), self.heatmaps_1px_right.get_arr()) def test_heatmaps_translate_1px_right_should_ignore_mode(self): aug = iaa.Affine(translate_px={"x": 1}, mode="edge", cval=255) observed = aug.augment_heatmaps([self.heatmaps])[0] _assert_same_shape(observed, self.heatmaps) _assert_same_min_max(observed, self.heatmaps) assert np.array_equal(observed.get_arr(), self.heatmaps_1px_right.get_arr()) # --------------------- # translate segmaps # --------------------- @property def segmaps(self): return SegmentationMapsOnImage( np.int32([ [0, 1, 2], [0, 1, 2], [2, 2, 2], ]), shape=(3, 3, 3) ) @property def segmaps_1px_right(self): return SegmentationMapsOnImage( np.int32([ [0, 0, 1], [0, 0, 1], [0, 2, 2], ]), shape=(3, 3, 3) ) def test_segmaps_translate_1px_right(self): aug = iaa.Affine(translate_px={"x": 1}) observed = aug.augment_segmentation_maps([self.segmaps])[0] _assert_same_shape(observed, self.segmaps) assert np.array_equal(observed.get_arr(), self.segmaps_1px_right.get_arr()) def test_segmaps_translate_1px_right_should_ignore_cval(self): # should still use mode=constant cval=0 even when other settings chosen aug = iaa.Affine(translate_px={"x": 1}, cval=255) observed = aug.augment_segmentation_maps([self.segmaps])[0] _assert_same_shape(observed, self.segmaps) assert np.array_equal(observed.get_arr(), self.segmaps_1px_right.get_arr()) def test_segmaps_translate_1px_right_should_ignore_mode(self): aug = iaa.Affine(translate_px={"x": 1}, mode="edge", cval=255) observed = aug.augment_segmentation_maps([self.segmaps])[0] _assert_same_shape(observed, self.segmaps) assert np.array_equal(observed.get_arr(), self.segmaps_1px_right.get_arr()) class TestAffine_rotate(unittest.TestCase): def setUp(self): reseed() @property def image(self): return np.uint8([ [0, 0, 0], [255, 255, 255], [0, 0, 0] ])[:, :, np.newaxis] @property def image_rot90(self): return np.uint8([ [0, 255, 0], [0, 255, 0], [0, 255, 0] ])[:, :, np.newaxis] @property def images(self): return np.array([self.image]) @property def images_rot90(self): return np.array([self.image_rot90]) @property def kpsoi(self): kps = [ia.Keypoint(x=0, y=1), ia.Keypoint(x=1, y=1), ia.Keypoint(x=2, y=1)] return [ia.KeypointsOnImage(kps, shape=self.image.shape)] @property def kpsoi_rot90(self): kps = [ia.Keypoint(x=3-1, y=0), ia.Keypoint(x=3-1, y=1), ia.Keypoint(x=3-1, y=2)] return [ia.KeypointsOnImage(kps, shape=self.image_rot90.shape)] @property def psoi(self): polys = [ia.Polygon([(0, 0), (3, 0), (3, 3)])] return [ia.PolygonsOnImage(polys, shape=self.image.shape)] @property def psoi_rot90(self): polys = [ia.Polygon([(3-0, 0), (3-0, 3), (3-3, 3)])] return [ia.PolygonsOnImage(polys, shape=self.image_rot90.shape)] @property def lsoi(self): ls = [ia.LineString([(0, 0), (3, 0), (3, 3)])] return [ia.LineStringsOnImage(ls, shape=self.image.shape)] @property def lsoi_rot90(self): ls = [ia.LineString([(3-0, 0), (3-0, 3), (3-3, 3)])] return [ia.LineStringsOnImage(ls, shape=self.image_rot90.shape)] @property def bbsoi(self): bbs = [ia.BoundingBox(x1=0, y1=1, x2=2, y2=3)] return [ia.BoundingBoxesOnImage(bbs, shape=self.image.shape)] @property def bbsoi_rot90(self): bbs = [ia.BoundingBox(x1=0, y1=0, x2=2, y2=2)] return [ia.BoundingBoxesOnImage(bbs, shape=self.image_rot90.shape)] def test_image_rot90(self): # rotate by 90 degrees aug = iaa.Affine(scale=1.0, translate_px=0, rotate=90, shear=0) observed = aug.augment_images(self.images) observed[observed >= 100] = 255 observed[observed < 100] = 0 assert np.array_equal(observed, self.images_rot90) def test_image_rot90__deterministic(self): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=90, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) observed[observed >= 100] = 255 observed[observed < 100] = 0 assert np.array_equal(observed, self.images_rot90) def test_image_rot90__list(self): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=90, shear=0) observed = aug.augment_images([self.image]) observed[0][observed[0] >= 100] = 255 observed[0][observed[0] < 100] = 0 assert array_equal_lists(observed, [self.image_rot90]) def test_image_rot90__list_and_deterministic(self): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=90, shear=0) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.image]) observed[0][observed[0] >= 100] = 255 observed[0][observed[0] < 100] = 0 assert array_equal_lists(observed, [self.image_rot90]) def test_keypoints_rot90(self): self._test_cba_rotate( "augment_keypoints", 90, self.kpsoi, self.kpsoi_rot90, False) def test_keypoints_rot90__deterministic(self): self._test_cba_rotate( "augment_keypoints", 90, self.kpsoi, self.kpsoi_rot90, True) def test_polygons_rot90(self): self._test_cba_rotate( "augment_polygons", 90, self.psoi, self.psoi_rot90, False) def test_polygons_rot90__deterministic(self): self._test_cba_rotate( "augment_polygons", 90, self.psoi, self.psoi_rot90, True) def test_line_strings_rot90(self): self._test_cba_rotate( "augment_line_strings", 90, self.lsoi, self.lsoi_rot90, False) def test_line_strings_rot90__deterministic(self): self._test_cba_rotate( "augment_line_strings", 90, self.lsoi, self.lsoi_rot90, True) def test_bounding_boxes_rot90(self): self._test_cba_rotate( "augment_bounding_boxes", 90, self.bbsoi, self.bbsoi_rot90, False) def test_bounding_boxes_rot90__deterministic(self): self._test_cba_rotate( "augment_bounding_boxes", 90, self.bbsoi, self.bbsoi_rot90, True) @classmethod def _test_cba_rotate(cls, augf_name, rotate, cbaoi, cbaoi_rotated, deterministic): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=rotate, shear=0) if deterministic: aug = aug.to_deterministic() observed = getattr(aug, augf_name)(cbaoi) assert_cbaois_equal(observed, cbaoi_rotated) def test_image_rotate_is_tuple_0_to_364_deg(self): # random rotation 0-364 degrees aug = iaa.Affine(scale=1.0, translate_px=0, rotate=(0, 364), shear=0) last_aug = None nb_changed_aug = 0 nb_iterations = 1000 pixels_sums_aug = self.image.astype(np.int32) * 0 for i in sm.xrange(nb_iterations): observed_aug = aug.augment_images(self.images) if i == 0: last_aug = observed_aug else: if not np.array_equal(observed_aug, last_aug): nb_changed_aug += 1 last_aug = observed_aug pixels_sums_aug += (observed_aug[0] > 100) assert nb_changed_aug >= int(nb_iterations * 0.9) # center pixel, should always be white when rotating line around center assert pixels_sums_aug[1, 1] > (nb_iterations * 0.98) assert pixels_sums_aug[1, 1] < (nb_iterations * 1.02) # outer pixels, should sometimes be white # the values here had to be set quite tolerant, the middle pixels at # top/left/bottom/right get more activation than expected outer_pixels = ([0, 0, 0, 1, 1, 2, 2, 2], [0, 1, 2, 0, 2, 0, 1, 2]) assert ( pixels_sums_aug[outer_pixels] > int(nb_iterations * (2/8 * 0.4)) ).all() assert ( pixels_sums_aug[outer_pixels] < int(nb_iterations * (2/8 * 2.0)) ).all() def test_image_rotate_is_tuple_0_to_364_deg__deterministic(self): aug = iaa.Affine(scale=1.0, translate_px=0, rotate=(0, 364), shear=0) aug_det = aug.to_deterministic() last_aug_det = None nb_changed_aug_det = 0 nb_iterations = 10 pixels_sums_aug_det = self.image.astype(np.int32) * 0 for i in sm.xrange(nb_iterations): observed_aug_det = aug_det.augment_images(self.images) if i == 0: last_aug_det = observed_aug_det else: if not np.array_equal(observed_aug_det, last_aug_det): nb_changed_aug_det += 1 last_aug_det = observed_aug_det pixels_sums_aug_det += (observed_aug_det[0] > 100) assert nb_changed_aug_det == 0 # center pixel, should always be white when rotating line around center assert pixels_sums_aug_det[1, 1] > (nb_iterations * 0.98) assert pixels_sums_aug_det[1, 1] < (nb_iterations * 1.02) def test_alignment_between_images_and_heatmaps_for_fixed_rot(self): # measure alignment between images and heatmaps when rotating for backend in ["auto", "cv2", "skimage"]: aug = iaa.Affine(rotate=45, backend=backend) image = np.zeros((7, 6), dtype=np.uint8) image[:, 2:3+1] = 255 hm = ia.HeatmapsOnImage(image.astype(np.float32)/255, shape=(7, 6)) img_aug = aug.augment_image(image) hm_aug = aug.augment_heatmaps([hm])[0] img_aug_mask = img_aug > 255*0.1 hm_aug_mask = hm_aug.arr_0to1 > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert hm_aug.shape == (7, 6) assert hm_aug.arr_0to1.shape == (7, 6, 1) assert (same / img_aug_mask.size) >= 0.95 def test_alignment_between_images_and_smaller_heatmaps_for_fixed_rot(self): # measure alignment between images and heatmaps when rotating # here with smaller heatmaps for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=45, backend=backend) image = np.zeros((56, 48), dtype=np.uint8) image[:, 16:24+1] = 255 hm = ia.HeatmapsOnImage( ia.imresize_single_image( image, (28, 24), interpolation="cubic" ).astype(np.float32)/255, shape=(56, 48) ) img_aug = aug.augment_image(image) hm_aug = aug.augment_heatmaps([hm])[0] img_aug_mask = img_aug > 255*0.1 hm_aug_mask = ia.imresize_single_image( hm_aug.arr_0to1, img_aug.shape[0:2], interpolation="cubic" ) > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert hm_aug.shape == (56, 48) assert hm_aug.arr_0to1.shape == (28, 24, 1) assert (same / img_aug_mask.size) >= 0.9 def test_bounding_boxes_have_expected_shape_after_augmentation(self): image = np.zeros((100, 100), dtype=np.uint8) image[20:80, 20:80] = 255 bb = ia.BoundingBox(x1=20, y1=20, x2=80, y2=80) bbsoi = ia.BoundingBoxesOnImage([bb], shape=image.shape) for rotate in [10, 20, 40, 80, 120]: with self.subTest(rotate=rotate): aug = iaa.Affine(rotate=rotate, order=0) image_aug, bbsoi_aug = aug(image=image, bounding_boxes=bbsoi) xx = np.nonzero(np.max(image_aug > 100, axis=0))[0] yy = np.nonzero(np.max(image_aug > 100, axis=1))[0] bb_exp_x1 = xx[0] bb_exp_x2 = xx[-1] bb_exp_y1 = yy[0] bb_exp_y2 = yy[-1] bb_expected = ia.BoundingBox(x1=bb_exp_x1, y1=bb_exp_y1, x2=bb_exp_x2, y2=bb_exp_y2) assert bbsoi_aug.bounding_boxes[0].iou(bb_expected) > 0.95 class TestAffine_cval(unittest.TestCase): @property def image(self): return np.ones((3, 3, 1), dtype=np.uint8) * 255 @property def images(self): return np.array([self.image]) def test_image_fixed_cval(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=128) observed = aug.augment_images(self.images) assert (observed[0] > 128 - 30).all() assert (observed[0] < 128 + 30).all() def test_image_fixed_cval__deterministic(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=128) aug_det = aug.to_deterministic() observed = aug_det.augment_images(self.images) assert (observed[0] > 128 - 30).all() assert (observed[0] < 128 + 30).all() def test_image_fixed_cval__list(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=128) observed = aug.augment_images([self.image]) assert (observed[0] > 128 - 30).all() assert (observed[0] < 128 + 30).all() def test_image_fixed_cval__list_and_deterministic(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=128) aug_det = aug.to_deterministic() observed = aug_det.augment_images([self.image]) assert (observed[0] > 128 - 30).all() assert (observed[0] < 128 + 30).all() def test_image_cval_is_tuple(self): # random cvals aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=(0, 255)) last_aug = None nb_changed_aug = 0 nb_iterations = 1000 for i in sm.xrange(nb_iterations): observed_aug = aug.augment_images(self.images) if i == 0: last_aug = observed_aug else: if not np.array_equal(observed_aug, last_aug): nb_changed_aug += 1 last_aug = observed_aug assert nb_changed_aug >= int(nb_iterations * 0.9) def test_image_cval_is_tuple__deterministic(self): # random cvals aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=(0, 255)) aug_det = aug.to_deterministic() last_aug_det = None nb_changed_aug_det = 0 nb_iterations = 10 for i in sm.xrange(nb_iterations): observed_aug_det = aug_det.augment_images(self.images) if i == 0: last_aug_det = observed_aug_det else: if not np.array_equal(observed_aug_det, last_aug_det): nb_changed_aug_det += 1 last_aug_det = observed_aug_det assert nb_changed_aug_det == 0 def test_float_cval_on_float_image(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0.25) image = np.full((10, 10, 3), 0.75, dtype=np.float32) image_aug = aug(image=image) assert np.allclose(image_aug, 0.25) def test_float_cval_on_int_image(self): aug = iaa.Affine(scale=1.0, translate_px=100, rotate=0, shear=0, cval=2.75) image = np.full((10, 10, 3), 10, dtype=np.uint8) image_aug = aug(image=image) assert np.allclose(image_aug, 2) # cval is casted to int, no rounding class TestAffine_fit_output(unittest.TestCase): @property def image(self): return np.ones((3, 3, 1), dtype=np.uint8) * 255 @property def images(self): return np.array([self.image]) @property def heatmaps(self): return ia.HeatmapsOnImage( np.float32([ [0.0, 0.5, 0.75], [0.0, 0.5, 0.75], [0.75, 0.75, 0.75], ]), shape=(3, 3, 3) ) @property def kpsoi(self): kps = [ia.Keypoint(x=0, y=1), ia.Keypoint(x=1, y=1), ia.Keypoint(x=2, y=1)] return [ia.KeypointsOnImage(kps, shape=self.image.shape)] def test_image_translate(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(translate_px=100, fit_output=True, backend=backend) observed = aug.augment_images(self.images) expected = self.images assert np.array_equal(observed, expected) def test_keypoints_translate(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(translate_px=100, fit_output=True, backend=backend) observed = aug.augment_keypoints(self.kpsoi) expected = self.kpsoi assert keypoints_equal(observed, expected) def test_heatmaps_translate(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(translate_px=100, fit_output=True, backend=backend) observed = aug.augment_heatmaps([self.heatmaps])[0] expected = self.heatmaps assert np.allclose(observed.arr_0to1, expected.arr_0to1) def test_image_rot45(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=45, fit_output=True, backend=backend) img = np.zeros((10, 10), dtype=np.uint8) img[0:2, 0:2] = 255 img[-2:, 0:2] = 255 img[0:2, -2:] = 255 img[-2:, -2:] = 255 img_aug = aug.augment_image(img) _labels, nb_labels = skimage.morphology.label( img_aug > 240, return_num=True, connectivity=2) assert nb_labels == 4 def test_heatmaps_rot45(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=45, fit_output=True, backend=backend) img = np.zeros((10, 10), dtype=np.uint8) img[0:2, 0:2] = 255 img[-2:, 0:2] = 255 img[0:2, -2:] = 255 img[-2:, -2:] = 255 hm = ia.HeatmapsOnImage(img.astype(np.float32)/255, shape=(10, 10)) hm_aug = aug.augment_heatmaps([hm])[0] _labels, nb_labels = skimage.morphology.label( hm_aug.arr_0to1 > 240/255, return_num=True, connectivity=2) assert nb_labels == 4 def test_heatmaps_rot45__heatmaps_smaller_than_image(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=45, fit_output=True, backend=backend) img = np.zeros((80, 80), dtype=np.uint8) img[0:5, 0:5] = 255 img[-5:, 0:5] = 255 img[0:5, -5:] = 255 img[-5:, -5:] = 255 hm = HeatmapsOnImage( ia.imresize_single_image( img, (40, 40), interpolation="cubic" ).astype(np.float32)/255, shape=(80, 80) ) hm_aug = aug.augment_heatmaps([hm])[0] # these asserts are deactivated because the image size can # change under fit_output=True # assert hm_aug.shape == (80, 80) # assert hm_aug.arr_0to1.shape == (40, 40, 1) _labels, nb_labels = skimage.morphology.label( hm_aug.arr_0to1 > 200/255, return_num=True, connectivity=2) assert nb_labels == 4 def test_image_heatmap_alignment_random_rots(self): nb_iterations = 50 for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): for _ in sm.xrange(nb_iterations): aug = iaa.Affine(rotate=(0, 364), fit_output=True, backend=backend) img = np.zeros((80, 80), dtype=np.uint8) img[0:5, 0:5] = 255 img[-5:, 0:5] = 255 img[0:5, -5:] = 255 img[-5:, -5:] = 255 hm = HeatmapsOnImage( img.astype(np.float32)/255, shape=(80, 80) ) img_aug = aug.augment_image(img) hm_aug = aug.augment_heatmaps([hm])[0] img_aug_mask = img_aug > 255*0.1 hm_aug_mask = ia.imresize_single_image( hm_aug.arr_0to1, img_aug.shape[0:2], interpolation="cubic" ) > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert (same / img_aug_mask.size) >= 0.95 def test_image_heatmap_alignment_random_rots__hms_smaller_than_img(self): nb_iterations = 50 for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): for _ in sm.xrange(nb_iterations): aug = iaa.Affine(rotate=(0, 364), fit_output=True, backend=backend) img = np.zeros((80, 80), dtype=np.uint8) img[0:5, 0:5] = 255 img[-5:, 0:5] = 255 img[0:5, -5:] = 255 img[-5:, -5:] = 255 hm = HeatmapsOnImage( ia.imresize_single_image( img, (40, 40), interpolation="cubic" ).astype(np.float32)/255, shape=(80, 80) ) img_aug = aug.augment_image(img) hm_aug = aug.augment_heatmaps([hm])[0] img_aug_mask = img_aug > 255*0.1 hm_aug_mask = ia.imresize_single_image( hm_aug.arr_0to1, img_aug.shape[0:2], interpolation="cubic" ) > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert (same / img_aug_mask.size) >= 0.95 def test_segmaps_rot45(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=45, fit_output=True, backend=backend) img = np.zeros((80, 80), dtype=np.uint8) img[0:5, 0:5] = 255 img[-5:, 0:5] = 255 img[0:5, -5:] = 255 img[-5:, -5:] = 255 segmap = SegmentationMapsOnImage( (img > 100).astype(np.int32), shape=(80, 80) ) segmap_aug = aug.augment_segmentation_maps([segmap])[0] # these asserts are deactivated because the image size can # change under fit_output=True # assert segmap_aug.shape == (80, 80) # assert segmap_aug.arr_0to1.shape == (40, 40, 1) _labels, nb_labels = skimage.morphology.label( segmap_aug.arr > 0, return_num=True, connectivity=2) assert nb_labels == 4 def test_segmaps_rot45__segmaps_smaller_than_img(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=45, fit_output=True, backend=backend) img = np.zeros((80, 80), dtype=np.uint8) img[0:5, 0:5] = 255 img[-5:, 0:5] = 255 img[0:5, -5:] = 255 img[-5:, -5:] = 255 segmap = SegmentationMapsOnImage( ( ia.imresize_single_image( img, (40, 40), interpolation="cubic" ) > 100 ).astype(np.int32), shape=(80, 80) ) segmap_aug = aug.augment_segmentation_maps([segmap])[0] # these asserts are deactivated because the image size can # change under fit_output=True # assert segmap_aug.shape == (80, 80) # assert segmap_aug.arr_0to1.shape == (40, 40, 1) _labels, nb_labels = skimage.morphology.label( segmap_aug.arr > 0, return_num=True, connectivity=2) assert nb_labels == 4 def test_image_segmap_alignment_random_rots(self): nb_iterations = 50 for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): for _ in sm.xrange(nb_iterations): aug = iaa.Affine(rotate=(0, 364), fit_output=True, backend=backend) img = np.zeros((80, 80), dtype=np.uint8) img[0:5, 0:5] = 255 img[-5:, 0:5] = 255 img[0:5, -5:] = 255 img[-5:, -5:] = 255 segmap = SegmentationMapsOnImage( (img > 100).astype(np.int32), shape=(80, 80) ) img_aug = aug.augment_image(img) segmap_aug = aug.augment_segmentation_maps([segmap])[0] img_aug_mask = img_aug > 100 segmap_aug_mask = ia.imresize_single_image( segmap_aug.arr, img_aug.shape[0:2], interpolation="nearest" ) > 0 same = np.sum(img_aug_mask == segmap_aug_mask[:, :, 0]) assert (same / img_aug_mask.size) >= 0.95 def test_image_segmap_alignment_random_rots__sms_smaller_than_img(self): nb_iterations = 50 for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): for _ in sm.xrange(nb_iterations): aug = iaa.Affine(rotate=(0, 364), fit_output=True, backend=backend) img = np.zeros((80, 80), dtype=np.uint8) img[0:5, 0:5] = 255 img[-5:, 0:5] = 255 img[0:5, -5:] = 255 img[-5:, -5:] = 255 segmap = SegmentationMapsOnImage( ( ia.imresize_single_image( img, (40, 40), interpolation="cubic" ) > 100 ).astype(np.int32), shape=(80, 80) ) img_aug = aug.augment_image(img) segmap_aug = aug.augment_segmentation_maps([segmap])[0] img_aug_mask = img_aug > 100 segmap_aug_mask = ia.imresize_single_image( segmap_aug.arr, img_aug.shape[0:2], interpolation="nearest" ) > 0 same = np.sum(img_aug_mask == segmap_aug_mask[:, :, 0]) assert (same / img_aug_mask.size) >= 0.95 def test_keypoints_rot90_without_fit_output(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=90, backend=backend) kps = ia.KeypointsOnImage([ia.Keypoint(10, 10)], shape=(100, 200, 3)) kps_aug = aug.augment_keypoints(kps) assert kps_aug.shape == (100, 200, 3) assert not np.allclose( [kps_aug.keypoints[0].x, kps_aug.keypoints[0].y], [kps.keypoints[0].x, kps.keypoints[0].y], atol=1e-2, rtol=0) def test_keypoints_rot90(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=90, fit_output=True, backend=backend) kps = ia.KeypointsOnImage([ia.Keypoint(10, 10)], shape=(100, 200, 3)) kps_aug = aug.augment_keypoints(kps) assert kps_aug.shape == (200, 100, 3) assert not np.allclose( [kps_aug.keypoints[0].x, kps_aug.keypoints[0].y], [kps.keypoints[0].x, kps.keypoints[0].y], atol=1e-2, rtol=0) def test_empty_keypoints_rot90(self): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=90, fit_output=True, backend=backend) kps = ia.KeypointsOnImage([], shape=(100, 200, 3)) kps_aug = aug.augment_keypoints(kps) assert kps_aug.shape == (200, 100, 3) assert len(kps_aug.keypoints) == 0 def _test_cbaoi_rot90_without_fit_output(self, cbaoi, augf_name): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): # verify that shape in PolygonsOnImages changes aug = iaa.Affine(rotate=90, backend=backend) cbaoi_aug = getattr(aug, augf_name)([cbaoi, cbaoi]) assert len(cbaoi_aug) == 2 for cbaoi_aug_i in cbaoi_aug: if isinstance(cbaoi, (ia.PolygonsOnImage, ia.LineStringsOnImage)): assert cbaoi_aug_i.shape == cbaoi.shape assert not cbaoi_aug_i.items[0].coords_almost_equals( cbaoi.items[0].coords, max_distance=1e-2) else: assert_cbaois_equal(cbaoi_aug_i, cbaoi) def test_polygons_rot90_without_fit_output(self): psoi = ia.PolygonsOnImage([ ia.Polygon([(10, 10), (20, 10), (20, 20)]) ], shape=(100, 200, 3)) self._test_cbaoi_rot90_without_fit_output(psoi, "augment_polygons") def test_line_strings_rot90_without_fit_output(self): lsoi = ia.LineStringsOnImage([ ia.LineString([(10, 10), (20, 10), (20, 20), (10, 10)]) ], shape=(100, 200, 3)) self._test_cbaoi_rot90_without_fit_output(lsoi, "augment_line_strings") def _test_cbaoi_rot90(self, cbaoi, expected, augf_name): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=90, fit_output=True, backend=backend) cbaoi_aug = getattr(aug, augf_name)([cbaoi, cbaoi]) assert len(cbaoi_aug) == 2 for cbaoi_aug_i in cbaoi_aug: assert_cbaois_equal(cbaoi_aug_i, expected) def test_polygons_rot90(self): psoi = ia.PolygonsOnImage([ ia.Polygon([(10, 10), (20, 10), (20, 20)]) ], shape=(100, 200, 3)) expected = ia.PolygonsOnImage([ ia.Polygon([(100-10-1, 10), (100-10-1, 20), (100-20-1, 20)]) ], shape=(200, 100, 3)) self._test_cbaoi_rot90(psoi, expected, "augment_polygons") def test_line_strings_rot90(self): lsoi = ia.LineStringsOnImage([ ia.LineString([(10, 10), (20, 10), (20, 20), (10, 10)]) ], shape=(100, 200, 3)) expected = ia.LineStringsOnImage([ ia.LineString([(100-10-1, 10), (100-10-1, 20), (100-20-1, 20), (100-10-1, 10)]) ], shape=(200, 100, 3)) self._test_cbaoi_rot90(lsoi, expected, "augment_line_strings") def test_bounding_boxes_rot90(self): lsoi = ia.BoundingBoxesOnImage([ ia.BoundingBox(x1=10, y1=10, x2=20, y2=20) ], shape=(100, 200, 3)) expected = ia.BoundingBoxesOnImage([ ia.BoundingBox(x1=100-20-1, y1=10, x2=100-10-1, y2=20) ], shape=(200, 100, 3)) self._test_cbaoi_rot90(lsoi, expected, "augment_bounding_boxes") def _test_empty_cbaoi_rot90(self, cbaoi, expected, augf_name): for backend in ["auto", "cv2", "skimage"]: with self.subTest(backend=backend): aug = iaa.Affine(rotate=90, fit_output=True, backend=backend) cbaoi_aug = getattr(aug, augf_name)(cbaoi) assert_cbaois_equal(cbaoi_aug, expected) def test_empty_polygons_rot90(self): psoi = ia.PolygonsOnImage([], shape=(100, 200, 3)) expected = ia.PolygonsOnImage([], shape=(200, 100, 3)) self._test_empty_cbaoi_rot90(psoi, expected, "augment_polygons") def test_empty_line_strings_rot90(self): lsoi = ia.LineStringsOnImage([], shape=(100, 200, 3)) expected = ia.LineStringsOnImage([], shape=(200, 100, 3)) self._test_empty_cbaoi_rot90(lsoi, expected, "augment_line_strings") def test_empty_bounding_boxes_rot90(self): bbsoi = ia.BoundingBoxesOnImage([], shape=(100, 200, 3)) expected = ia.BoundingBoxesOnImage([], shape=(200, 100, 3)) self._test_empty_cbaoi_rot90(bbsoi, expected, "augment_bounding_boxes") # TODO merge these into TestAffine_rotate since they are rotations? # or extend to contain other affine params too? class TestAffine_alignment(unittest.TestCase): def setUp(self): reseed() def test_image_segmap_alignment_with_translate_px(self): image = np.zeros((80, 100, 3), dtype=np.uint8) image[40-10:40+10, 50-10:50+10, :] = 255 hm = np.zeros((40, 50, 1), dtype=np.float32) hm[20-5:20+5, 25-5:25+5, 0] = 1.0 hm = ia.HeatmapsOnImage(hm, shape=image.shape) # note that if x is an odd value (e.g. 1), the projection is a bit # less accurate as x=1 projected to a half-sized segmap is x=0.5, # leading to interpolation effects xvals = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, [0, 10, 20]] for xvals_i in xvals: with self.subTest(x=xvals_i): aug = iaa.Affine(translate_px={"x": xvals_i}) iterations = 2 if ia.is_single_number(xvals_i) else 20 for _ in np.arange(iterations): image_aug, hm_aug = aug(image=image, heatmaps=hm) hm_aug_arr_rs = ia.imresize_single_image( hm_aug.get_arr(), (80, 100), interpolation="nearest") overlap_true = np.sum( np.logical_and( (image_aug[..., 0] > 220), (hm_aug_arr_rs[..., 0] > 0.9) ) ) p_same_on_zero_cells = np.average( (image_aug[..., 0] > 220) == (hm_aug_arr_rs[..., 0] > 0.9)) assert overlap_true > 19*19 assert p_same_on_zero_cells > 0.98 def test_image_segmap_alignment_with_translate_percent(self): image = np.zeros((80, 100, 3), dtype=np.uint8) image[40-10:40+10, 50-10:50+10, :] = 255 hm = np.zeros((40, 50, 1), dtype=np.float32) hm[20-5:20+5, 25-5:25+5, 0] = 1.0 hm = ia.HeatmapsOnImage(hm, shape=image.shape) # note that if x is an odd value (e.g. 1), the projection is a bit # less accurate as x=1 projected to a half-sized segmap is x=0.5, # leading to interpolation effects width = image.shape[1] xvals = [0/width, 2/width, 4/width, 6/width, 8/width, 10/width, 12/width, 14/width, 16/width, 18/width, 20/width, [0/width, 10/width, 20/width]] for xvals_i in xvals: with self.subTest(x=xvals_i): aug = iaa.Affine(translate_percent={"x": xvals_i}) iterations = 2 if ia.is_single_number(xvals_i) else 20 for _ in np.arange(iterations): image_aug, hm_aug = aug(image=image, heatmaps=hm) hm_aug_arr_rs = ia.imresize_single_image( hm_aug.get_arr(), (80, 100), interpolation="nearest") overlap_true = np.sum( np.logical_and( (image_aug[..., 0] > 220), (hm_aug_arr_rs[..., 0] > 0.9) ) ) p_same_on_zero_cells = np.average( (image_aug[..., 0] > 220) == (hm_aug_arr_rs[..., 0] > 0.9)) assert overlap_true > 19*19 assert p_same_on_zero_cells > 0.98 def test_image_keypoint_alignment(self): aug = iaa.Affine(rotate=[0, 180], order=0) img = np.zeros((10, 10), dtype=np.uint8) img[0:5, 5] = 255 img[2, 4:6] = 255 img_rot = [np.copy(img), np.copy(np.flipud(np.fliplr(img)))] kpsoi = ia.KeypointsOnImage([ia.Keypoint(x=5, y=2)], shape=img.shape) kpsoi_rot = [(5, 2), (5, 10-2)] img_aug_indices = [] kpsois_aug_indices = [] for _ in sm.xrange(40): aug_det = aug.to_deterministic() imgs_aug = aug_det.augment_images([img, img]) kpsois_aug = aug_det.augment_keypoints([kpsoi, kpsoi]) assert kpsois_aug[0].shape == img.shape assert kpsois_aug[1].shape == img.shape for img_aug in imgs_aug: if np.array_equal(img_aug, img_rot[0]): img_aug_indices.append(0) elif np.array_equal(img_aug, img_rot[1]): img_aug_indices.append(1) else: assert False for kpsoi_aug in kpsois_aug: similar_to_rot_0 = np.allclose( [kpsoi_aug.keypoints[0].x, kpsoi_aug.keypoints[0].y], kpsoi_rot[0]) similar_to_rot_180 = np.allclose( [kpsoi_aug.keypoints[0].x, kpsoi_aug.keypoints[0].y], kpsoi_rot[1]) if similar_to_rot_0: kpsois_aug_indices.append(0) elif similar_to_rot_180: kpsois_aug_indices.append(1) else: assert False assert np.array_equal(img_aug_indices, kpsois_aug_indices) assert len(set(img_aug_indices)) == 2 assert len(set(kpsois_aug_indices)) == 2 @classmethod def _test_image_cbaoi_alignment(cls, cbaoi, cbaoi_rot, augf_name): aug = iaa.Affine(rotate=[0, 180], order=0) img = np.zeros((10, 10), dtype=np.uint8) img[0:5, 5] = 255 img[2, 4:6] = 255 img_rot = [np.copy(img), np.copy(np.flipud(np.fliplr(img)))] img_aug_indices = [] cbaois_aug_indices = [] for _ in sm.xrange(40): aug_det = aug.to_deterministic() imgs_aug = aug_det.augment_images([img, img]) cbaois_aug = getattr(aug_det, augf_name)([cbaoi, cbaoi]) assert cbaois_aug[0].shape == img.shape assert cbaois_aug[1].shape == img.shape if hasattr(cbaois_aug[0].items[0], "is_valid"): assert cbaois_aug[0].items[0].is_valid assert cbaois_aug[1].items[0].is_valid for img_aug in imgs_aug: if np.array_equal(img_aug, img_rot[0]): img_aug_indices.append(0) elif np.array_equal(img_aug, img_rot[1]): img_aug_indices.append(1) else: assert False for cbaoi_aug in cbaois_aug: if cbaoi_aug.items[0].coords_almost_equals(cbaoi_rot[0]): cbaois_aug_indices.append(0) elif cbaoi_aug.items[0].coords_almost_equals(cbaoi_rot[1]): cbaois_aug_indices.append(1) else: assert False assert np.array_equal(img_aug_indices, cbaois_aug_indices) assert len(set(img_aug_indices)) == 2 assert len(set(cbaois_aug_indices)) == 2 def test_image_polygon_alignment(self): psoi = ia.PolygonsOnImage([ia.Polygon([(1, 1), (9, 1), (5, 5)])], shape=(10, 10)) psoi_rot = [ psoi.polygons[0].deepcopy(), ia.Polygon([(10-1, 10-1), (10-9, 10-1), (10-5, 10-5)]) ] self._test_image_cbaoi_alignment(psoi, psoi_rot, "augment_polygons") def test_image_line_string_alignment(self): lsoi = ia.LineStringsOnImage([ia.LineString([(1, 1), (9, 1), (5, 5)])], shape=(10, 10)) lsoi_rot = [ lsoi.items[0].deepcopy(), ia.LineString([(10-1, 10-1), (10-9, 10-1), (10-5, 10-5)]) ] self._test_image_cbaoi_alignment(lsoi, lsoi_rot, "augment_line_strings") def test_image_bounding_box_alignment(self): bbsoi = ia.BoundingBoxesOnImage([ ia.BoundingBox(x1=1, y1=1, x2=9, y2=5)], shape=(10, 10)) bbsoi_rot = [ bbsoi.items[0].deepcopy(), ia.BoundingBox(x1=10-9, y1=10-5, x2=10-1, y2=10-1)] self._test_image_cbaoi_alignment(bbsoi, bbsoi_rot, "augment_bounding_boxes") class TestAffine_other_dtypes(unittest.TestCase): @property def translate_mask(self): mask = np.zeros((3, 3), dtype=bool) mask[1, 2] = True return mask @property def image(self): image = np.zeros((17, 17), dtype=bool) image[2:15, 5:13] = True return image @property def rot_mask_inner(self): img_flipped = iaa.Fliplr(1.0)(image=self.image) return img_flipped == 1 @property def rot_mask_outer(self): img_flipped = iaa.Fliplr(1.0)(image=self.image) return img_flipped == 0 @property def rot_thresh_inner(self): return 0.9 @property def rot_thresh_outer(self): return 0.9 def rot_thresh_inner_float(self, order): return 0.85 if order == 1 else 0.7 def rot_thresh_outer_float(self, order): return 0.85 if order == 1 else 0.4 def test_translate_skimage_order_0_bool(self): aug = iaa.Affine(translate_px={"x": 1}, order=0, mode="constant", backend="skimage") image = np.zeros((3, 3), dtype=bool) image[1, 1] = True image_aug = aug.augment_image(image) assert image_aug.dtype.name == image.dtype.name assert np.all(image_aug[~self.translate_mask] == 0) assert np.all(image_aug[self.translate_mask] == 1) def test_translate_skimage_order_0_uint_int(self): dtypes = ["uint8", "uint16", "uint32", "int8", "int16", "int32"] for dtype in dtypes: aug = iaa.Affine(translate_px={"x": 1}, order=0, mode="constant", backend="skimage") min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) if np.dtype(dtype).kind == "i": values = [1, 5, 10, 100, int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value - 100, max_value] values = values + [(-1) * value for value in values] else: values = [1, 5, 10, 100, int(center_value), int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value - 100, max_value] for value in values: image = np.zeros((3, 3), dtype=dtype) image[1, 1] = value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert np.all(image_aug[~self.translate_mask] == 0) assert np.all(image_aug[self.translate_mask] == value) def test_translate_skimage_order_0_float(self): # float dtypes = ["float16", "float32", "float64"] for dtype in dtypes: aug = iaa.Affine(translate_px={"x": 1}, order=0, mode="constant", backend="skimage") min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) def _isclose(a, b): atol = 1e-4 if dtype == "float16" else 1e-8 return np.isclose(a, b, atol=atol, rtol=0) isize = np.dtype(dtype).itemsize values = [ 0.01, 1.0, 10.0, 100.0, 500 ** (isize - 1), float(np.float64(1000 ** (isize - 1))) ] values = values + [(-1) * value for value in values] values = values + [min_value, max_value] for value in values: with self.subTest(dtype=dtype, value=value): image = np.zeros((3, 3), dtype=dtype) image[1, 1] = value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert np.all(_isclose(image_aug[~self.translate_mask], 0)) assert np.all(_isclose(image_aug[self.translate_mask], value)) def test_rotate_skimage_order_not_0_bool(self): # skimage, order!=0 and rotate=180 for order in [1, 3, 4, 5]: aug = iaa.Affine(rotate=180, order=order, mode="constant", backend="skimage") aug_flip = iaa.Sequential([iaa.Flipud(1.0), iaa.Fliplr(1.0)]) image = np.zeros((17, 17), dtype=bool) image[2:15, 5:13] = True image_aug = aug.augment_image(image) image_exp = aug_flip.augment_image(image) assert image_aug.dtype.name == image.dtype.name assert ( np.sum(image_aug == image_exp)/image.size ) > self.rot_thresh_inner def test_rotate_skimage_order_not_0_uint_int(self): def _compute_matching(image_aug, image_exp, mask): return np.sum( np.isclose(image_aug[mask], image_exp[mask], rtol=0, atol=1.001) ) / np.sum(mask) dtypes = ["uint8", "uint16", "uint32", "int8", "int16", "int32"] for dtype in dtypes: for order in [1, 3, 4, 5]: aug = iaa.Affine(rotate=180, order=order, mode="constant", backend="skimage") aug_flip = iaa.Sequential([iaa.Flipud(1.0), iaa.Fliplr(1.0)]) min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) if np.dtype(dtype).kind == "i": values = [1, 5, 10, 100, int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value - 100, max_value] values = values + [(-1) * value for value in values] else: values = [1, 5, 10, 100, int(center_value), int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value - 100, max_value] for value in values: with self.subTest(dtype=dtype, order=order, value=value): image = np.zeros((17, 17), dtype=dtype) image[2:15, 5:13] = value image_aug = aug.augment_image(image) image_exp = aug_flip.augment_image(image) assert image_aug.dtype.name == dtype assert _compute_matching( image_aug, image_exp, self.rot_mask_inner ) > self.rot_thresh_inner assert _compute_matching( image_aug, image_exp, self.rot_mask_outer ) > self.rot_thresh_outer def test_rotate_skimage_order_not_0_float(self): def _compute_matching(image_aug, image_exp, mask): return np.sum( _isclose(image_aug[mask], image_exp[mask]) ) / np.sum(mask) for order in [1, 3, 4, 5]: dtypes = ["float16", "float32", "float64"] if order == 5: # float64 caused too many interpolation inaccuracies for # order=5, not wrong but harder to test dtypes = ["float16", "float32"] for dtype in dtypes: aug = iaa.Affine(rotate=180, order=order, mode="constant", backend="skimage") aug_flip = iaa.Sequential([iaa.Flipud(1.0), iaa.Fliplr(1.0)]) min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) def _isclose(a, b): atol = 1e-4 if dtype == "float16" else 1e-8 if order not in [0, 1]: atol = 1e-2 return np.isclose(a, b, atol=atol, rtol=0) isize = np.dtype(dtype).itemsize values = [0.01, 1.0, 10.0, 100.0, 500 ** (isize - 1), 1000 ** (isize - 1)] values = values + [(-1) * value for value in values] if order not in [3, 4]: # results in NaNs otherwise values = values + [min_value, max_value] for value in values: with self.subTest(order=order, dtype=dtype, value=value): image = np.zeros((17, 17), dtype=dtype) image[2:15, 5:13] = value image_aug = aug.augment_image(image) image_exp = aug_flip.augment_image(image) assert image_aug.dtype.name == dtype assert _compute_matching( image_aug, image_exp, self.rot_mask_inner ) > self.rot_thresh_inner_float(order) assert _compute_matching( image_aug, image_exp, self.rot_mask_outer ) > self.rot_thresh_outer_float(order) def test_translate_cv2_order_0_bool(self): aug = iaa.Affine(translate_px={"x": 1}, order=0, mode="constant", backend="cv2") image = np.zeros((3, 3), dtype=bool) image[1, 1] = True image_aug = aug.augment_image(image) assert image_aug.dtype.name == image.dtype.name assert np.all(image_aug[~self.translate_mask] == 0) assert np.all(image_aug[self.translate_mask] == 1) def test_translate_cv2_order_0_uint_int(self): aug = iaa.Affine(translate_px={"x": 1}, order=0, mode="constant", backend="cv2") dtypes = ["uint8", "uint16", "int8", "int16", "int32"] for dtype in dtypes: min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) if np.dtype(dtype).kind == "i": values = [1, 5, 10, 100, int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value - 100, max_value] values = values + [(-1) * value for value in values] else: values = [1, 5, 10, 100, int(center_value), int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value - 100, max_value] for value in values: with self.subTest(dtype=dtype, value=value): image = np.zeros((3, 3), dtype=dtype) image[1, 1] = value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert np.all(image_aug[~self.translate_mask] == 0) assert np.all(image_aug[self.translate_mask] == value) def test_translate_cv2_order_0_float(self): aug = iaa.Affine(translate_px={"x": 1}, order=0, mode="constant", backend="cv2") dtypes = ["float16", "float32", "float64"] for dtype in dtypes: min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) def _isclose(a, b): atol = 1e-4 if dtype == "float16" else 1e-8 return np.isclose(a, b, atol=atol, rtol=0) isize = np.dtype(dtype).itemsize values = [ 0.01, 1.0, 10.0, 100.0, 500 ** (isize - 1), float(np.float64(1000 ** (isize - 1))) ] values = values + [(-1) * value for value in values] values = values + [min_value, max_value] for value in values: with self.subTest(dtype=dtype, value=value): image = np.zeros((3, 3), dtype=dtype) image[1, 1] = value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert np.all(_isclose(image_aug[~self.translate_mask], 0)) assert np.all(_isclose(image_aug[self.translate_mask], value)) def test_rotate_cv2_order_1_and_3_bool(self): # cv2, order=1 and rotate=180 for order in [1, 3]: aug = iaa.Affine(rotate=180, order=order, mode="constant", backend="cv2") aug_flip = iaa.Sequential([iaa.Flipud(1.0), iaa.Fliplr(1.0)]) image = np.zeros((17, 17), dtype=bool) image[2:15, 5:13] = True image_aug = aug.augment_image(image) image_exp = aug_flip.augment_image(image) assert image_aug.dtype.name == image.dtype.name assert (np.sum(image_aug == image_exp) / image.size) > 0.9 def test_rotate_cv2_order_1_and_3_uint_int(self): # cv2, order=1 and rotate=180 for order in [1, 3]: aug = iaa.Affine(rotate=180, order=order, mode="constant", backend="cv2") aug_flip = iaa.Sequential([iaa.Flipud(1.0), iaa.Fliplr(1.0)]) dtypes = ["uint8", "uint16", "int8", "int16"] for dtype in dtypes: min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) if np.dtype(dtype).kind == "i": values = [1, 5, 10, 100, int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value - 100, max_value] values = values + [(-1) * value for value in values] else: values = [1, 5, 10, 100, int(center_value), int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value - 100, max_value] for value in values: with self.subTest(order=order, dtype=dtype, value=value): image = np.zeros((17, 17), dtype=dtype) image[2:15, 5:13] = value image_aug = aug.augment_image(image) image_exp = aug_flip.augment_image(image) assert image_aug.dtype.name == dtype assert ( np.sum(image_aug == image_exp) / image.size ) > 0.9 def test_rotate_cv2_order_1_and_3_float(self): # cv2, order=1 and rotate=180 for order in [1, 3]: aug = iaa.Affine(rotate=180, order=order, mode="constant", backend="cv2") aug_flip = iaa.Sequential([iaa.Flipud(1.0), iaa.Fliplr(1.0)]) dtypes = ["float16", "float32", "float64"] for dtype in dtypes: min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) def _isclose(a, b): atol = 1e-4 if dtype == "float16" else 1e-8 return np.isclose(a, b, atol=atol, rtol=0) isize = np.dtype(dtype).itemsize values = [0.01, 1.0, 10.0, 100.0, 500 ** (isize - 1), 1000 ** (isize - 1)] values = values + [(-1) * value for value in values] values = values + [min_value, max_value] for value in values: with self.subTest(order=order, dtype=dtype, value=value): image = np.zeros((17, 17), dtype=dtype) image[2:15, 5:13] = value image_aug = aug.augment_image(image) image_exp = aug_flip.augment_image(image) assert image_aug.dtype.name == dtype assert ( np.sum(_isclose(image_aug, image_exp)) / image.size ) > 0.9 class TestAffine_other(unittest.TestCase): def test_unusual_channel_numbers(self): with assertWarns(self, iaa.SuspiciousSingleImageShapeWarning): nb_channels_lst = [4, 5, 512, 513] orders = [0, 1, 3] backends = ["auto", "skimage", "cv2"] gen = itertools.product(nb_channels_lst, orders, backends) for nb_channels, order, backend in gen: with self.subTest(nb_channels=nb_channels, order=order, backend=backend): aug = iaa.Affine(translate_px={"x": -1}, mode="constant", cval=255, order=order, backend=backend) image = np.full((3, 3, nb_channels), 128, dtype=np.uint8) heatmap_arr = np.full((3, 3, nb_channels), 0.5, dtype=np.float32) heatmap = ia.HeatmapsOnImage(heatmap_arr, shape=image.shape) image_aug, heatmap_aug = aug(image=image, heatmaps=heatmap) hm_aug_arr = heatmap_aug.arr_0to1 assert image_aug.shape == (3, 3, nb_channels) assert heatmap_aug.arr_0to1.shape == (3, 3, nb_channels) assert heatmap_aug.shape == image.shape assert np.allclose(image_aug[:, 0:2, :], 128, rtol=0, atol=2) assert np.allclose(image_aug[:, 2:3, 0:3], 255, rtol=0, atol=2) assert np.allclose(image_aug[:, 2:3, 3:], 255, rtol=0, atol=2) assert np.allclose(hm_aug_arr[:, 0:2, :], 0.5, rtol=0, atol=0.025) assert np.allclose(hm_aug_arr[:, 2:3, :], 0.0, rtol=0, atol=0.025) def test_zero_sized_axes(self): shapes = [ (0, 0), (0, 1), (1, 0), (0, 1, 1), (1, 0, 1) ] for fit_output in [False, True]: for shape in shapes: with self.subTest(shape=shape, fit_output=fit_output): image = np.zeros(shape, dtype=np.uint8) aug = iaa.Affine(rotate=45, fit_output=fit_output) image_aug = aug(image=image) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape def test_pickleable(self): aug = iaa.Affine(scale=(0.9, 1.1), translate_px=(-4, 4), rotate=(-10, 10), shear=(-10, 10), order=[0, 1]) runtest_pickleable_uint8_img(aug, iterations=20) class TestScaleX(unittest.TestCase): def setUp(self): reseed() def test___init__(self): aug = iaa.ScaleX(1.5) assert isinstance(aug, iaa.Affine) assert np.isclose(aug.scale[0].value, 1.5) assert aug.order.value == 1 assert aug.cval.value == 0 assert aug.mode.value == "constant" assert aug.fit_output is False def test_integrationtest(self): image = np.zeros((10, 10), dtype=np.uint8) image[5, 5] = 255 aug = iaa.ScaleX(4.0, order=0) image_aug = aug(image=image) xx = np.nonzero(np.max(image_aug, axis=0) > 200)[0] yy = np.nonzero(np.max(image_aug, axis=1) > 200)[0] x1, x2 = xx[0], xx[-1] y1, y2 = yy[0], yy[-1] # not >=3, because if e.g. index 1 is spread to 0 to 3 after scaling, # it covers four cells (0, 1, 2, 3), but 3-0 is 3 assert x2 - x1 >= 3 assert y2 - y1 < 1 class TestScaleY(unittest.TestCase): def setUp(self): reseed() def test___init__(self): aug = iaa.ScaleY(1.5) assert isinstance(aug, iaa.Affine) assert np.isclose(aug.scale[1].value, 1.5) assert aug.order.value == 1 assert aug.cval.value == 0 assert aug.mode.value == "constant" assert aug.fit_output is False def test_integrationtest(self): image = np.zeros((10, 10), dtype=np.uint8) image[5, 5] = 255 aug = iaa.ScaleY(4.0, order=0) image_aug = aug(image=image) xx = np.nonzero(np.max(image_aug, axis=0) > 200)[0] yy = np.nonzero(np.max(image_aug, axis=1) > 200)[0] x1, x2 = xx[0], xx[-1] y1, y2 = yy[0], yy[-1] # not >=3, because if e.g. index 1 is spread to 0 to 3 after scaling, # it covers four cells (0, 1, 2, 3), but 3-0 is 3 assert y2 - y1 >= 3 assert x2 - x1 < 1 class TestTranslateX(unittest.TestCase): def setUp(self): reseed() def test___init___translate_percent(self): aug = iaa.TranslateX(percent=0.5) assert isinstance(aug, iaa.Affine) assert np.isclose(aug.translate[0].value, 0.5) assert aug.order.value == 1 assert aug.cval.value == 0 assert aug.mode.value == "constant" assert aug.fit_output is False def test___init___translate_px(self): aug = iaa.TranslateX(px=2) assert isinstance(aug, iaa.Affine) assert np.isclose(aug.translate[0].value, 2) assert aug.order.value == 1 assert aug.cval.value == 0 assert aug.mode.value == "constant" assert aug.fit_output is False def test___init___both_none(self): aug = iaa.TranslateX() assert np.isclose(aug.translate[0].a.value, -0.25) assert np.isclose(aug.translate[0].b.value, 0.25) def test_integrationtest_translate_percent(self): image = np.full((50, 50), 255, dtype=np.uint8) aug = iaa.TranslateX(percent=0.5, order=1, cval=0) image_aug = aug(image=image) expected = np.copy(image) expected[:, 0:25] = 0 overlap = np.average(np.isclose(image_aug, expected, atol=1.01)) assert overlap > (1.0 - (1/50) - 1e-4) def test_integrationtest_translate_px(self): image = np.full((50, 50), 255, dtype=np.uint8) aug = iaa.TranslateX(px=25, order=1, cval=0) image_aug = aug(image=image) expected = np.copy(image) expected[:, 0:25] = 0 overlap = np.average(np.isclose(image_aug, expected, atol=1.01)) assert overlap > (1.0 - (1/50) - 1e-4) class TestTranslateY(unittest.TestCase): def setUp(self): reseed() def test___init___translate_percent(self): aug = iaa.TranslateY(percent=0.5) assert isinstance(aug, iaa.Affine) assert np.isclose(aug.translate[1].value, 0.5) assert aug.order.value == 1 assert aug.cval.value == 0 assert aug.mode.value == "constant" assert aug.fit_output is False def test___init___translate_px(self): aug = iaa.TranslateY(px=2) assert isinstance(aug, iaa.Affine) assert np.isclose(aug.translate[1].value, 2) assert aug.order.value == 1 assert aug.cval.value == 0 assert aug.mode.value == "constant" assert aug.fit_output is False def test___init___both_none(self): aug = iaa.TranslateY() assert np.isclose(aug.translate[1].a.value, -0.25) assert np.isclose(aug.translate[1].b.value, 0.25) def test_integrationtest_translate_percent(self): image = np.full((50, 50), 255, dtype=np.uint8) aug = iaa.TranslateY(percent=0.5, order=1, cval=0) image_aug = aug(image=image) expected = np.copy(image) expected[0:25, :] = 0 overlap = np.average(np.isclose(image_aug, expected, atol=1.01)) assert overlap > (1.0 - (1/50) - 1e-4) def test_integrationtest_translate_px(self): image = np.full((50, 50), 255, dtype=np.uint8) aug = iaa.TranslateY(px=25, order=1, cval=0) image_aug = aug(image=image) expected = np.copy(image) expected[0:25, :] = 0 overlap = np.average(np.isclose(image_aug, expected, atol=1.01)) assert overlap > (1.0 - (1/50) - 1e-4) class TestRotate(unittest.TestCase): def setUp(self): reseed() def test___init___(self): aug = iaa.Rotate(rotate=45) assert isinstance(aug, iaa.Affine) assert np.isclose(aug.rotate.value, 45) assert aug.order.value == 1 assert aug.cval.value == 0 assert aug.mode.value == "constant" assert aug.fit_output is False def test_integrationtest(self): image = np.zeros((40, 20), dtype=np.uint8) image[:, 10:10+1] = 255 aug = iaa.Rotate(90, order=0) image_aug = aug(image=image) assert image_aug.shape == (40, 20) assert np.isclose(np.sum(image_aug[20-1:20+2, :]), 255*20, atol=1) class TestShearX(unittest.TestCase): def setUp(self): reseed() def test___init__(self): aug = iaa.ShearX(40) assert isinstance(aug, iaa.Affine) assert aug.shear[0].value == 40 assert aug.order.value == 1 assert aug.cval.value == 0 assert aug.mode.value == "constant" assert aug.fit_output is False def test_integrationtest(self): def _find_coords(arr): xx = np.nonzero(np.max(arr, axis=0) > 200)[0] yy = np.nonzero(np.max(arr, axis=1) > 200)[0] x1 = xx[0] x2 = xx[-1] y1 = yy[0] y2 = yy[-1] return x1+(x2-x1)/2, y1+(y2-y1)/2 image = np.zeros((50, 50, 4), dtype=np.uint8) image[10:10+1, 20:20+1, 0] = 255 image[10:10+1, 30:30+1, 1] = 255 image[40:40+1, 30:30+1, 2] = 255 image[40:40+1, 20:20+1, 3] = 255 aug = iaa.ShearX(30, order=0) image_aug = aug(image=image) x1, y1 = _find_coords(image_aug[..., 0]) x2, y2 = _find_coords(image_aug[..., 1]) x3, y3 = _find_coords(image_aug[..., 2]) x4, y4 = _find_coords(image_aug[..., 3]) assert x1 > 20 assert np.isclose(y1, 10.0) assert np.isclose(y2, 10.0) assert x3 < 30 assert np.isclose(y3, 40.0) assert np.isclose(y4, 40.0) assert not np.isclose(x1, x4) assert not np.isclose(x2, x3) class TestShearY(unittest.TestCase): def setUp(self): reseed() def test___init__(self): aug = iaa.ShearY(40) assert isinstance(aug, iaa.Affine) assert aug.shear[1].value == 40 assert aug.order.value == 1 assert aug.cval.value == 0 assert aug.mode.value == "constant" assert aug.fit_output is False def test_integrationtest(self): def _find_coords(arr): xx = np.nonzero(np.max(arr, axis=0) > 200)[0] yy = np.nonzero(np.max(arr, axis=1) > 200)[0] x1 = xx[0] x2 = xx[-1] y1 = yy[0] y2 = yy[-1] return x1+(x2-x1)/2, y1+(y2-y1)/2 image = np.zeros((50, 50, 4), dtype=np.uint8) image[20:20+1, 10:10+1, 0] = 255 image[20:20+1, 40:40+1, 1] = 255 image[30:30+1, 40:40+1, 2] = 255 image[30:30+1, 10:10+1, 3] = 255 aug = iaa.ShearY(30, order=0) image_aug = aug(image=image) x1, y1 = _find_coords(image_aug[..., 0]) x2, y2 = _find_coords(image_aug[..., 1]) x3, y3 = _find_coords(image_aug[..., 2]) x4, y4 = _find_coords(image_aug[..., 3]) assert y1 < 20 assert np.isclose(x1, 10.0) assert np.isclose(x4, 10.0) assert y2 > 20 assert np.isclose(x2, 40.0) assert np.isclose(x3, 40.0) assert not np.isclose(y1, y2) assert not np.isclose(y3, y4) # TODO migrate to unittest and split up tests or remove AffineCv2 def test_AffineCv2(): reseed() with warnings.catch_warnings(record=True) as caught_warnings: warnings.simplefilter("always") _ = iaa.AffineCv2() assert "is deprecated" in str(caught_warnings[0].message) with warnings.catch_warnings(): warnings.simplefilter("ignore", category=ia.DeprecationWarning) base_img = np.array([[0, 0, 0], [0, 255, 0], [0, 0, 0]], dtype=np.uint8) base_img = base_img[:, :, np.newaxis] images = np.array([base_img]) images_list = [base_img] outer_pixels = ([], []) for i in sm.xrange(base_img.shape[0]): for j in sm.xrange(base_img.shape[1]): if i != j: outer_pixels[0].append(i) outer_pixels[1].append(j) kps = [ia.Keypoint(x=0, y=0), ia.Keypoint(x=1, y=1), ia.Keypoint(x=2, y=2)] keypoints = [ia.KeypointsOnImage(kps, shape=base_img.shape)] # no translation/scale/rotate/shear, shouldnt change nothing aug = iaa.AffineCv2(scale=1.0, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug.augment_images(images) expected = images assert np.array_equal(observed, expected) observed = aug_det.augment_images(images) expected = images assert np.array_equal(observed, expected) observed = aug.augment_images(images_list) expected = images_list assert array_equal_lists(observed, expected) observed = aug_det.augment_images(images_list) expected = images_list assert array_equal_lists(observed, expected) observed = aug.augment_keypoints(keypoints) expected = keypoints assert keypoints_equal(observed, expected) observed = aug_det.augment_keypoints(keypoints) expected = keypoints assert keypoints_equal(observed, expected) # --------------------- # scale # --------------------- # zoom in aug = iaa.AffineCv2(scale=1.75, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug.augment_images(images) assert observed[0][1, 1] > 250 assert (observed[0][outer_pixels[0], outer_pixels[1]] > 20).all() assert (observed[0][outer_pixels[0], outer_pixels[1]] < 150).all() observed = aug_det.augment_images(images) assert observed[0][1, 1] > 250 assert (observed[0][outer_pixels[0], outer_pixels[1]] > 20).all() assert (observed[0][outer_pixels[0], outer_pixels[1]] < 150).all() observed = aug.augment_images(images_list) assert observed[0][1, 1] > 250 assert (observed[0][outer_pixels[0], outer_pixels[1]] > 20).all() assert (observed[0][outer_pixels[0], outer_pixels[1]] < 150).all() observed = aug_det.augment_images(images_list) assert observed[0][1, 1] > 250 assert (observed[0][outer_pixels[0], outer_pixels[1]] > 20).all() assert (observed[0][outer_pixels[0], outer_pixels[1]] < 150).all() observed = aug.augment_keypoints(keypoints) assert observed[0].keypoints[0].x < 0 assert observed[0].keypoints[0].y < 0 assert observed[0].keypoints[1].x == 1 assert observed[0].keypoints[1].y == 1 assert observed[0].keypoints[2].x > 2 assert observed[0].keypoints[2].y > 2 observed = aug_det.augment_keypoints(keypoints) assert observed[0].keypoints[0].x < 0 assert observed[0].keypoints[0].y < 0 assert observed[0].keypoints[1].x == 1 assert observed[0].keypoints[1].y == 1 assert observed[0].keypoints[2].x > 2 assert observed[0].keypoints[2].y > 2 # zoom in only on x axis aug = iaa.AffineCv2(scale={"x": 1.75, "y": 1.0}, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug.augment_images(images) assert observed[0][1, 1] > 250 assert (observed[0][[1, 1], [0, 2]] > 20).all() assert (observed[0][[1, 1], [0, 2]] < 150).all() assert (observed[0][0, :] < 5).all() assert (observed[0][2, :] < 5).all() observed = aug_det.augment_images(images) assert observed[0][1, 1] > 250 assert (observed[0][[1, 1], [0, 2]] > 20).all() assert (observed[0][[1, 1], [0, 2]] < 150).all() assert (observed[0][0, :] < 5).all() assert (observed[0][2, :] < 5).all() observed = aug.augment_images(images_list) assert observed[0][1, 1] > 250 assert (observed[0][[1, 1], [0, 2]] > 20).all() assert (observed[0][[1, 1], [0, 2]] < 150).all() assert (observed[0][0, :] < 5).all() assert (observed[0][2, :] < 5).all() observed = aug_det.augment_images(images_list) assert observed[0][1, 1] > 250 assert (observed[0][[1, 1], [0, 2]] > 20).all() assert (observed[0][[1, 1], [0, 2]] < 150).all() assert (observed[0][0, :] < 5).all() assert (observed[0][2, :] < 5).all() observed = aug.augment_keypoints(keypoints) assert observed[0].keypoints[0].x < 0 assert observed[0].keypoints[0].y == 0 assert observed[0].keypoints[1].x == 1 assert observed[0].keypoints[1].y == 1 assert observed[0].keypoints[2].x > 2 assert observed[0].keypoints[2].y == 2 observed = aug_det.augment_keypoints(keypoints) assert observed[0].keypoints[0].x < 0 assert observed[0].keypoints[0].y == 0 assert observed[0].keypoints[1].x == 1 assert observed[0].keypoints[1].y == 1 assert observed[0].keypoints[2].x > 2 assert observed[0].keypoints[2].y == 2 # zoom in only on y axis aug = iaa.AffineCv2(scale={"x": 1.0, "y": 1.75}, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() observed = aug.augment_images(images) assert observed[0][1, 1] > 250 assert (observed[0][[0, 2], [1, 1]] > 20).all() assert (observed[0][[0, 2], [1, 1]] < 150).all() assert (observed[0][:, 0] < 5).all() assert (observed[0][:, 2] < 5).all() observed = aug_det.augment_images(images) assert observed[0][1, 1] > 250 assert (observed[0][[0, 2], [1, 1]] > 20).all() assert (observed[0][[0, 2], [1, 1]] < 150).all() assert (observed[0][:, 0] < 5).all() assert (observed[0][:, 2] < 5).all() observed = aug.augment_images(images_list) assert observed[0][1, 1] > 250 assert (observed[0][[0, 2], [1, 1]] > 20).all() assert (observed[0][[0, 2], [1, 1]] < 150).all() assert (observed[0][:, 0] < 5).all() assert (observed[0][:, 2] < 5).all() observed = aug_det.augment_images(images_list) assert observed[0][1, 1] > 250 assert (observed[0][[0, 2], [1, 1]] > 20).all() assert (observed[0][[0, 2], [1, 1]] < 150).all() assert (observed[0][:, 0] < 5).all() assert (observed[0][:, 2] < 5).all() observed = aug.augment_keypoints(keypoints) assert observed[0].keypoints[0].x == 0 assert observed[0].keypoints[0].y < 0 assert observed[0].keypoints[1].x == 1 assert observed[0].keypoints[1].y == 1 assert observed[0].keypoints[2].x == 2 assert observed[0].keypoints[2].y > 2 observed = aug_det.augment_keypoints(keypoints) assert observed[0].keypoints[0].x == 0 assert observed[0].keypoints[0].y < 0 assert observed[0].keypoints[1].x == 1 assert observed[0].keypoints[1].y == 1 assert observed[0].keypoints[2].x == 2 assert observed[0].keypoints[2].y > 2 # zoom out # this one uses a 4x4 area of all 255, which is zoomed out to a 4x4 # area in which the center 2x2 area is 255 # zoom in should probably be adapted to this style # no separate tests here for x/y axis, should work fine if zoom in # works with that aug = iaa.AffineCv2(scale=0.49, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() image = np.ones((4, 4, 1), dtype=np.uint8) * 255 images = np.array([image]) images_list = [image] outer_pixels = ([], []) for y in sm.xrange(4): xs = sm.xrange(4) if y in [0, 3] else [0, 3] for x in xs: outer_pixels[0].append(y) outer_pixels[1].append(x) inner_pixels = ([1, 1, 2, 2], [1, 2, 1, 2]) kps = [ia.Keypoint(x=0, y=0), ia.Keypoint(x=3, y=0), ia.Keypoint(x=0, y=3), ia.Keypoint(x=3, y=3)] keypoints = [ia.KeypointsOnImage(kps, shape=image.shape)] kps_aug = [ia.Keypoint(x=0.765, y=0.765), ia.Keypoint(x=2.235, y=0.765), ia.Keypoint(x=0.765, y=2.235), ia.Keypoint(x=2.235, y=2.235)] keypoints_aug = [ia.KeypointsOnImage(kps_aug, shape=image.shape)] observed = aug.augment_images(images) assert (observed[0][outer_pixels] < 25).all() assert (observed[0][inner_pixels] > 200).all() observed = aug_det.augment_images(images) assert (observed[0][outer_pixels] < 25).all() assert (observed[0][inner_pixels] > 200).all() observed = aug.augment_images(images_list) assert (observed[0][outer_pixels] < 25).all() assert (observed[0][inner_pixels] > 200).all() observed = aug_det.augment_images(images_list) assert (observed[0][outer_pixels] < 25).all() assert (observed[0][inner_pixels] > 200).all() observed = aug.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) observed = aug_det.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) # varying scales aug = iaa.AffineCv2(scale={"x": (0.5, 1.5), "y": (0.5, 1.5)}, translate_px=0, rotate=0, shear=0) aug_det = aug.to_deterministic() image = np.array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 2, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], dtype=np.uint8) * 100 image = image[:, :, np.newaxis] images = np.array([image]) last_aug = None last_aug_det = None nb_changed_aug = 0 nb_changed_aug_det = 0 nb_iterations = 1000 for i in sm.xrange(nb_iterations): observed_aug = aug.augment_images(images) observed_aug_det = aug_det.augment_images(images) if i == 0: last_aug = observed_aug last_aug_det = observed_aug_det else: if not np.array_equal(observed_aug, last_aug): nb_changed_aug += 1 if not np.array_equal(observed_aug_det, last_aug_det): nb_changed_aug_det += 1 last_aug = observed_aug last_aug_det = observed_aug_det assert nb_changed_aug >= int(nb_iterations * 0.8) assert nb_changed_aug_det == 0 aug = iaa.AffineCv2(scale=iap.Uniform(0.7, 0.9)) assert is_parameter_instance(aug.scale, iap.Uniform) assert is_parameter_instance(aug.scale.a, iap.Deterministic) assert is_parameter_instance(aug.scale.b, iap.Deterministic) assert 0.7 - 1e-8 < aug.scale.a.value < 0.7 + 1e-8 assert 0.9 - 1e-8 < aug.scale.b.value < 0.9 + 1e-8 # --------------------- # translate # --------------------- # move one pixel to the right aug = iaa.AffineCv2(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0) aug_det = aug.to_deterministic() image = np.zeros((3, 3, 1), dtype=np.uint8) image_aug = np.copy(image) image[1, 1] = 255 image_aug[1, 2] = 255 images = np.array([image]) images_aug = np.array([image_aug]) images_list = [image] images_aug_list = [image_aug] keypoints = [ia.KeypointsOnImage([ia.Keypoint(x=1, y=1)], shape=base_img.shape)] keypoints_aug = [ia.KeypointsOnImage([ia.Keypoint(x=2, y=1)], shape=base_img.shape)] observed = aug.augment_images(images) assert np.array_equal(observed, images_aug) observed = aug_det.augment_images(images) assert np.array_equal(observed, images_aug) observed = aug.augment_images(images_list) assert array_equal_lists(observed, images_aug_list) observed = aug_det.augment_images(images_list) assert array_equal_lists(observed, images_aug_list) observed = aug.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) observed = aug_det.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) # move one pixel to the right aug = iaa.AffineCv2(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0) observed = aug.augment_images(images) assert np.array_equal(observed, images_aug) # move one pixel to the right aug = iaa.AffineCv2(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0) observed = aug.augment_images(images) assert np.array_equal(observed, images_aug) # move one pixel to the right # with order=ALL aug = iaa.AffineCv2(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0, order=ia.ALL) observed = aug.augment_images(images) assert np.array_equal(observed, images_aug) # move one pixel to the right # with order=list aug = iaa.AffineCv2(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0, order=[0, 1, 2]) observed = aug.augment_images(images) assert np.array_equal(observed, images_aug) # move one pixel to the right # with order=StochasticParameter aug = iaa.AffineCv2(scale=1.0, translate_px={"x": 1, "y": 0}, rotate=0, shear=0, order=iap.Choice([0, 1, 2])) observed = aug.augment_images(images) assert np.array_equal(observed, images_aug) # move one pixel to the bottom aug = iaa.AffineCv2(scale=1.0, translate_px={"x": 0, "y": 1}, rotate=0, shear=0) aug_det = aug.to_deterministic() image = np.zeros((3, 3, 1), dtype=np.uint8) image_aug = np.copy(image) image[1, 1] = 255 image_aug[2, 1] = 255 images = np.array([image]) images_aug = np.array([image_aug]) images_list = [image] images_aug_list = [image_aug] keypoints = [ia.KeypointsOnImage([ia.Keypoint(x=1, y=1)], shape=base_img.shape)] keypoints_aug = [ia.KeypointsOnImage([ia.Keypoint(x=1, y=2)], shape=base_img.shape)] observed = aug.augment_images(images) assert np.array_equal(observed, images_aug) observed = aug_det.augment_images(images) assert np.array_equal(observed, images_aug) observed = aug.augment_images(images_list) assert array_equal_lists(observed, images_aug_list) observed = aug_det.augment_images(images_list) assert array_equal_lists(observed, images_aug_list) observed = aug.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) observed = aug_det.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) # move 33% (one pixel) to the right aug = iaa.AffineCv2(scale=1.0, translate_percent={"x": 0.3333, "y": 0}, rotate=0, shear=0) aug_det = aug.to_deterministic() image = np.zeros((3, 3, 1), dtype=np.uint8) image_aug = np.copy(image) image[1, 1] = 255 image_aug[1, 2] = 255 images = np.array([image]) images_aug = np.array([image_aug]) images_list = [image] images_aug_list = [image_aug] keypoints = [ia.KeypointsOnImage([ia.Keypoint(x=1, y=1)], shape=base_img.shape)] keypoints_aug = [ia.KeypointsOnImage([ia.Keypoint(x=2, y=1)], shape=base_img.shape)] observed = aug.augment_images(images) assert np.array_equal(observed, images_aug) observed = aug_det.augment_images(images) assert np.array_equal(observed, images_aug) observed = aug.augment_images(images_list) assert array_equal_lists(observed, images_aug_list) observed = aug_det.augment_images(images_list) assert array_equal_lists(observed, images_aug_list) observed = aug.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) observed = aug_det.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) # move 33% (one pixel) to the bottom aug = iaa.AffineCv2(scale=1.0, translate_percent={"x": 0, "y": 0.3333}, rotate=0, shear=0) aug_det = aug.to_deterministic() image = np.zeros((3, 3, 1), dtype=np.uint8) image_aug = np.copy(image) image[1, 1] = 255 image_aug[2, 1] = 255 images = np.array([image]) images_aug = np.array([image_aug]) images_list = [image] images_aug_list = [image_aug] keypoints = [ia.KeypointsOnImage([ia.Keypoint(x=1, y=1)], shape=base_img.shape)] keypoints_aug = [ia.KeypointsOnImage([ia.Keypoint(x=1, y=2)], shape=base_img.shape)] observed = aug.augment_images(images) assert np.array_equal(observed, images_aug) observed = aug_det.augment_images(images) assert np.array_equal(observed, images_aug) observed = aug.augment_images(images_list) assert array_equal_lists(observed, images_aug_list) observed = aug_det.augment_images(images_list) assert array_equal_lists(observed, images_aug_list) observed = aug.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) observed = aug_det.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) # 0-1px to left/right and 0-1px to top/bottom aug = iaa.AffineCv2(scale=1.0, translate_px={"x": (-1, 1), "y": (-1, 1)}, rotate=0, shear=0) aug_det = aug.to_deterministic() last_aug = None last_aug_det = None nb_changed_aug = 0 nb_changed_aug_det = 0 nb_iterations = 1000 centers_aug = np.copy(image).astype(np.int32) * 0 centers_aug_det = np.copy(image).astype(np.int32) * 0 for i in sm.xrange(nb_iterations): observed_aug = aug.augment_images(images) observed_aug_det = aug_det.augment_images(images) if i == 0: last_aug = observed_aug last_aug_det = observed_aug_det else: if not np.array_equal(observed_aug, last_aug): nb_changed_aug += 1 if not np.array_equal(observed_aug_det, last_aug_det): nb_changed_aug_det += 1 last_aug = observed_aug last_aug_det = observed_aug_det assert len(observed_aug[0].nonzero()[0]) == 1 assert len(observed_aug_det[0].nonzero()[0]) == 1 centers_aug += (observed_aug[0] > 0) centers_aug_det += (observed_aug_det[0] > 0) assert nb_changed_aug >= int(nb_iterations * 0.7) assert nb_changed_aug_det == 0 assert (centers_aug > int(nb_iterations * (1/9 * 0.6))).all() assert (centers_aug < int(nb_iterations * (1/9 * 1.4))).all() aug = iaa.AffineCv2(translate_percent=iap.Uniform(0.7, 0.9)) assert is_parameter_instance(aug.translate, iap.Uniform) assert is_parameter_instance(aug.translate.a, iap.Deterministic) assert is_parameter_instance(aug.translate.b, iap.Deterministic) assert 0.7 - 1e-8 < aug.translate.a.value < 0.7 + 1e-8 assert 0.9 - 1e-8 < aug.translate.b.value < 0.9 + 1e-8 aug = iaa.AffineCv2(translate_px=iap.DiscreteUniform(1, 10)) assert is_parameter_instance(aug.translate, iap.DiscreteUniform) assert is_parameter_instance(aug.translate.a, iap.Deterministic) assert is_parameter_instance(aug.translate.b, iap.Deterministic) assert aug.translate.a.value == 1 assert aug.translate.b.value == 10 # --------------------- # translate heatmaps # --------------------- heatmaps = HeatmapsOnImage( np.float32([ [0.0, 0.5, 0.75], [0.0, 0.5, 0.75], [0.75, 0.75, 0.75], ]), shape=(3, 3, 3) ) arr_expected_1px_right = np.float32([ [0.0, 0.0, 0.5], [0.0, 0.0, 0.5], [0.0, 0.75, 0.75], ]) aug = iaa.AffineCv2(translate_px={"x": 1}) observed = aug.augment_heatmaps([heatmaps])[0] assert observed.shape == heatmaps.shape assert np.isclose(observed.min_value, heatmaps.min_value, rtol=0, atol=1e-6) assert np.isclose(observed.max_value, heatmaps.max_value, rtol=0, atol=1e-6) assert np.array_equal(observed.get_arr(), arr_expected_1px_right) # should still use mode=constant cval=0 even when other settings chosen aug = iaa.AffineCv2(translate_px={"x": 1}, cval=255) observed = aug.augment_heatmaps([heatmaps])[0] assert observed.shape == heatmaps.shape assert np.isclose(observed.min_value, heatmaps.min_value, rtol=0, atol=1e-6) assert np.isclose(observed.max_value, heatmaps.max_value, rtol=0, atol=1e-6) assert np.array_equal(observed.get_arr(), arr_expected_1px_right) aug = iaa.AffineCv2(translate_px={"x": 1}, mode="replicate", cval=255) observed = aug.augment_heatmaps([heatmaps])[0] assert observed.shape == heatmaps.shape assert np.isclose(observed.min_value, heatmaps.min_value, rtol=0, atol=1e-6) assert np.isclose(observed.max_value, heatmaps.max_value, rtol=0, atol=1e-6) assert np.array_equal(observed.get_arr(), arr_expected_1px_right) # --------------------- # translate segmaps # --------------------- segmaps = SegmentationMapsOnImage( np.int32([ [0, 1, 2], [0, 1, 2], [2, 2, 2], ]), shape=(3, 3, 3) ) arr_expected_1px_right = np.int32([ [0, 0, 1], [0, 0, 1], [0, 2, 2], ]) aug = iaa.AffineCv2(translate_px={"x": 1}) observed = aug.augment_segmentation_maps([segmaps])[0] assert observed.shape == segmaps.shape assert np.array_equal(observed.get_arr(), arr_expected_1px_right) # should still use mode=constant cval=0 even when other settings chosen aug = iaa.AffineCv2(translate_px={"x": 1}, cval=255) observed = aug.augment_segmentation_maps([segmaps])[0] assert observed.shape == segmaps.shape assert np.array_equal(observed.get_arr(), arr_expected_1px_right) aug = iaa.AffineCv2(translate_px={"x": 1}, mode="replicate", cval=255) observed = aug.augment_segmentation_maps([segmaps])[0] assert observed.shape == segmaps.shape assert np.array_equal(observed.get_arr(), arr_expected_1px_right) # --------------------- # rotate # --------------------- # rotate by 45 degrees aug = iaa.AffineCv2(scale=1.0, translate_px=0, rotate=90, shear=0) aug_det = aug.to_deterministic() image = np.zeros((3, 3, 1), dtype=np.uint8) image_aug = np.copy(image) image[1, :] = 255 image_aug[0, 1] = 255 image_aug[1, 1] = 255 image_aug[2, 1] = 255 images = np.array([image]) images_aug = np.array([image_aug]) images_list = [image] images_aug_list = [image_aug] kps = [ia.Keypoint(x=0, y=1), ia.Keypoint(x=1, y=1), ia.Keypoint(x=2, y=1)] keypoints = [ia.KeypointsOnImage(kps, shape=base_img.shape)] kps_aug = [ia.Keypoint(x=1, y=0), ia.Keypoint(x=1, y=1), ia.Keypoint(x=1, y=2)] keypoints_aug = [ia.KeypointsOnImage(kps_aug, shape=base_img.shape)] observed = aug.augment_images(images) observed[observed >= 100] = 255 observed[observed < 100] = 0 assert np.array_equal(observed, images_aug) observed = aug_det.augment_images(images) observed[observed >= 100] = 255 observed[observed < 100] = 0 assert np.array_equal(observed, images_aug) observed = aug.augment_images(images_list) observed[0][observed[0] >= 100] = 255 observed[0][observed[0] < 100] = 0 assert array_equal_lists(observed, images_aug_list) observed = aug_det.augment_images(images_list) observed[0][observed[0] >= 100] = 255 observed[0][observed[0] < 100] = 0 assert array_equal_lists(observed, images_aug_list) observed = aug.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) observed = aug_det.augment_keypoints(keypoints) assert keypoints_equal(observed, keypoints_aug) # rotate by StochasticParameter aug = iaa.AffineCv2(scale=1.0, translate_px=0, rotate=iap.Uniform(10, 20), shear=0) assert is_parameter_instance(aug.rotate, iap.Uniform) assert is_parameter_instance(aug.rotate.a, iap.Deterministic) assert aug.rotate.a.value == 10 assert is_parameter_instance(aug.rotate.b, iap.Deterministic) assert aug.rotate.b.value == 20 # random rotation 0-364 degrees aug = iaa.AffineCv2(scale=1.0, translate_px=0, rotate=(0, 364), shear=0) aug_det = aug.to_deterministic() last_aug = None last_aug_det = None nb_changed_aug = 0 nb_changed_aug_det = 0 nb_iterations = 1000 pixels_sums_aug = np.copy(image).astype(np.int32) * 0 pixels_sums_aug_det = np.copy(image).astype(np.int32) * 0 for i in sm.xrange(nb_iterations): observed_aug = aug.augment_images(images) observed_aug_det = aug_det.augment_images(images) if i == 0: last_aug = observed_aug last_aug_det = observed_aug_det else: if not np.array_equal(observed_aug, last_aug): nb_changed_aug += 1 if not np.array_equal(observed_aug_det, last_aug_det): nb_changed_aug_det += 1 last_aug = observed_aug last_aug_det = observed_aug_det pixels_sums_aug += (observed_aug[0] > 100) pixels_sums_aug_det += (observed_aug_det[0] > 100) assert nb_changed_aug >= int(nb_iterations * 0.9) assert nb_changed_aug_det == 0 # center pixel, should always be white when rotating line around center assert pixels_sums_aug[1, 1] > (nb_iterations * 0.98) assert pixels_sums_aug[1, 1] < (nb_iterations * 1.02) # outer pixels, should sometimes be white # the values here had to be set quite tolerant, the middle pixels at # top/left/bottom/right get more activation than expected outer_pixels = ([0, 0, 0, 1, 1, 2, 2, 2], [0, 1, 2, 0, 2, 0, 1, 2]) assert ( pixels_sums_aug[outer_pixels] > int(nb_iterations * (2/8 * 0.4)) ).all() assert ( pixels_sums_aug[outer_pixels] < int(nb_iterations * (2/8 * 2.0)) ).all() # --------------------- # shear # --------------------- # TODO # shear by StochasticParameter aug = iaa.AffineCv2(scale=1.0, translate_px=0, rotate=0, shear=iap.Uniform(10, 20)) assert is_parameter_instance(aug.shear, iap.Uniform) assert is_parameter_instance(aug.shear.a, iap.Deterministic) assert aug.shear.a.value == 10 assert is_parameter_instance(aug.shear.b, iap.Deterministic) assert aug.shear.b.value == 20 # --------------------- # cval # --------------------- aug = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=128) aug_det = aug.to_deterministic() image = np.ones((3, 3, 1), dtype=np.uint8) * 255 image_aug = np.copy(image) images = np.array([image]) images_list = [image] observed = aug.augment_images(images) assert (observed[0] > 128 - 30).all() assert (observed[0] < 128 + 30).all() observed = aug_det.augment_images(images) assert (observed[0] > 128 - 30).all() assert (observed[0] < 128 + 30).all() observed = aug.augment_images(images_list) assert (observed[0] > 128 - 30).all() assert (observed[0] < 128 + 30).all() observed = aug_det.augment_images(images_list) assert (observed[0] > 128 - 30).all() assert (observed[0] < 128 + 30).all() # random cvals aug = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=(0, 255)) aug_det = aug.to_deterministic() last_aug = None last_aug_det = None nb_changed_aug = 0 nb_changed_aug_det = 0 nb_iterations = 1000 averages = [] for i in sm.xrange(nb_iterations): observed_aug = aug.augment_images(images) observed_aug_det = aug_det.augment_images(images) if i == 0: last_aug = observed_aug last_aug_det = observed_aug_det else: if not np.array_equal(observed_aug, last_aug): nb_changed_aug += 1 if not np.array_equal(observed_aug_det, last_aug_det): nb_changed_aug_det += 1 last_aug = observed_aug last_aug_det = observed_aug_det averages.append(int(np.average(observed_aug))) assert nb_changed_aug >= int(nb_iterations * 0.9) assert nb_changed_aug_det == 0 # center pixel, should always be white when rotating line around center assert pixels_sums_aug[1, 1] > (nb_iterations * 0.98) assert pixels_sums_aug[1, 1] < (nb_iterations * 1.02) assert len(set(averages)) > 200 aug = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=ia.ALL) assert is_parameter_instance(aug.cval, iap.DiscreteUniform) assert is_parameter_instance(aug.cval.a, iap.Deterministic) assert is_parameter_instance(aug.cval.b, iap.Deterministic) assert aug.cval.a.value == 0 assert aug.cval.b.value == 255 aug = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=iap.DiscreteUniform(1, 5)) assert is_parameter_instance(aug.cval, iap.DiscreteUniform) assert is_parameter_instance(aug.cval.a, iap.Deterministic) assert is_parameter_instance(aug.cval.b, iap.Deterministic) assert aug.cval.a.value == 1 assert aug.cval.b.value == 5 # ------------ # mode # ------------ aug = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode=ia.ALL) assert is_parameter_instance(aug.mode, iap.Choice) aug = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode="replicate") assert is_parameter_instance(aug.mode, iap.Deterministic) assert aug.mode.value == "replicate" aug = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode=["replicate", "reflect"]) assert is_parameter_instance(aug.mode, iap.Choice) assert ( len(aug.mode.a) == 2 and "replicate" in aug.mode.a and "reflect" in aug.mode.a) aug = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode=iap.Choice(["replicate", "reflect"])) assert is_parameter_instance(aug.mode, iap.Choice) assert ( len(aug.mode.a) == 2 and "replicate" in aug.mode.a and "reflect" in aug.mode.a) # ------------ # exceptions for bad inputs # ------------ # scale got_exception = False try: _ = iaa.AffineCv2(scale=False) except Exception: got_exception = True assert got_exception # translate_px got_exception = False try: _ = iaa.AffineCv2(translate_px=False) except Exception: got_exception = True assert got_exception # translate_percent got_exception = False try: _ = iaa.AffineCv2(translate_percent=False) except Exception: got_exception = True assert got_exception # rotate got_exception = False try: _ = iaa.AffineCv2(scale=1.0, translate_px=0, rotate=False, shear=0, cval=0) except Exception: got_exception = True assert got_exception # shear got_exception = False try: _ = iaa.AffineCv2(scale=1.0, translate_px=0, rotate=0, shear=False, cval=0) except Exception: got_exception = True assert got_exception # cval got_exception = False try: _ = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=None) except Exception: got_exception = True assert got_exception # mode got_exception = False try: _ = iaa.AffineCv2(scale=1.0, translate_px=100, rotate=0, shear=0, cval=0, mode=False) except Exception: got_exception = True assert got_exception # non-existent order got_exception = False try: _ = iaa.AffineCv2(order=-1) except Exception: got_exception = True assert got_exception # bad order datatype got_exception = False try: _ = iaa.AffineCv2(order="test") except Exception: got_exception = True assert got_exception # ---------- # get_parameters # ---------- aug = iaa.AffineCv2(scale=1, translate_px=2, rotate=3, shear=4, order=1, cval=0, mode="constant") params = aug.get_parameters() assert is_parameter_instance(params[0], iap.Deterministic) # scale assert is_parameter_instance(params[1], iap.Deterministic) # translate assert is_parameter_instance(params[2], iap.Deterministic) # rotate assert is_parameter_instance(params[3], iap.Deterministic) # shear assert params[0].value == 1 # scale assert params[1].value == 2 # translate assert params[2].value == 3 # rotate assert params[3].value == 4 # shear assert params[4].value == 1 # order assert params[5].value == 0 # cval assert params[6].value == "constant" # mode class TestPiecewiseAffine(unittest.TestCase): def setUp(self): reseed() @property def image(self): img = np.zeros((60, 80), dtype=np.uint8) img[:, 9:11+1] = 255 img[:, 69:71+1] = 255 return img @property def mask(self): return self.image > 0 @property def heatmaps(self): return HeatmapsOnImage((self.image / 255.0).astype(np.float32), shape=(60, 80, 3)) @property def segmaps(self): return SegmentationMapsOnImage(self.mask.astype(np.int32), shape=(60, 80, 3)) # ----- # __init__ # ----- def test___init___scale_is_list(self): # scale as list aug = iaa.PiecewiseAffine(scale=[0.01, 0.10], nb_rows=12, nb_cols=4) assert is_parameter_instance(aug.scale, iap.Choice) assert 0.01 - 1e-8 < aug.scale.a[0] < 0.01 + 1e-8 assert 0.10 - 1e-8 < aug.scale.a[1] < 0.10 + 1e-8 def test___init___scale_is_tuple(self): # scale as tuple aug = iaa.PiecewiseAffine(scale=(0.01, 0.10), nb_rows=12, nb_cols=4) assert is_parameter_instance(aug.jitter.scale, iap.Uniform) assert is_parameter_instance(aug.jitter.scale.a, iap.Deterministic) assert is_parameter_instance(aug.jitter.scale.b, iap.Deterministic) assert 0.01 - 1e-8 < aug.jitter.scale.a.value < 0.01 + 1e-8 assert 0.10 - 1e-8 < aug.jitter.scale.b.value < 0.10 + 1e-8 def test___init___scale_is_stochastic_parameter(self): # scale as StochasticParameter aug = iaa.PiecewiseAffine(scale=iap.Uniform(0.01, 0.10), nb_rows=12, nb_cols=4) assert is_parameter_instance(aug.jitter.scale, iap.Uniform) assert is_parameter_instance(aug.jitter.scale.a, iap.Deterministic) assert is_parameter_instance(aug.jitter.scale.b, iap.Deterministic) assert 0.01 - 1e-8 < aug.jitter.scale.a.value < 0.01 + 1e-8 assert 0.10 - 1e-8 < aug.jitter.scale.b.value < 0.10 + 1e-8 def test___init___bad_datatype_for_scale_leads_to_failure(self): # bad datatype for scale got_exception = False try: _ = iaa.PiecewiseAffine(scale=False, nb_rows=12, nb_cols=4) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___nb_rows_is_list(self): # rows as list aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=[4, 20], nb_cols=4) assert is_parameter_instance(aug.nb_rows, iap.Choice) assert aug.nb_rows.a[0] == 4 assert aug.nb_rows.a[1] == 20 def test___init___nb_rows_is_tuple(self): # rows as tuple aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=(4, 20), nb_cols=4) assert is_parameter_instance(aug.nb_rows, iap.DiscreteUniform) assert is_parameter_instance(aug.nb_rows.a, iap.Deterministic) assert is_parameter_instance(aug.nb_rows.b, iap.Deterministic) assert aug.nb_rows.a.value == 4 assert aug.nb_rows.b.value == 20 def test___init___nb_rows_is_stochastic_parameter(self): # rows as StochasticParameter aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=iap.DiscreteUniform(4, 20), nb_cols=4) assert is_parameter_instance(aug.nb_rows, iap.DiscreteUniform) assert is_parameter_instance(aug.nb_rows.a, iap.Deterministic) assert is_parameter_instance(aug.nb_rows.b, iap.Deterministic) assert aug.nb_rows.a.value == 4 assert aug.nb_rows.b.value == 20 def test___init___bad_datatype_for_nb_rows_leads_to_failure(self): # bad datatype for rows got_exception = False try: _ = iaa.PiecewiseAffine(scale=0.05, nb_rows=False, nb_cols=4) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___nb_cols_is_list(self): aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=[4, 20]) assert is_parameter_instance(aug.nb_cols, iap.Choice) assert aug.nb_cols.a[0] == 4 assert aug.nb_cols.a[1] == 20 def test___init___nb_cols_is_tuple(self): # cols as tuple aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=(4, 20)) assert is_parameter_instance(aug.nb_cols, iap.DiscreteUniform) assert is_parameter_instance(aug.nb_cols.a, iap.Deterministic) assert is_parameter_instance(aug.nb_cols.b, iap.Deterministic) assert aug.nb_cols.a.value == 4 assert aug.nb_cols.b.value == 20 def test___init___nb_cols_is_stochastic_parameter(self): # cols as StochasticParameter aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=iap.DiscreteUniform(4, 20)) assert is_parameter_instance(aug.nb_cols, iap.DiscreteUniform) assert is_parameter_instance(aug.nb_cols.a, iap.Deterministic) assert is_parameter_instance(aug.nb_cols.b, iap.Deterministic) assert aug.nb_cols.a.value == 4 assert aug.nb_cols.b.value == 20 def test___init___bad_datatype_for_nb_cols_leads_to_failure(self): # bad datatype for cols got_exception = False try: _aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___order_is_int(self): # single int for order aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, order=0) assert is_parameter_instance(aug.order, iap.Deterministic) assert aug.order.value == 0 def test___init___order_is_list(self): # list for order aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, order=[0, 1, 3]) assert is_parameter_instance(aug.order, iap.Choice) assert all([v in aug.order.a for v in [0, 1, 3]]) def test___init___order_is_stochastic_parameter(self): # StochasticParameter for order aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, order=iap.Choice([0, 1, 3])) assert is_parameter_instance(aug.order, iap.Choice) assert all([v in aug.order.a for v in [0, 1, 3]]) def test___init___order_is_all(self): # ALL for order aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, order=ia.ALL) assert is_parameter_instance(aug.order, iap.Choice) assert all([v in aug.order.a for v in [0, 1, 3, 4, 5]]) def test___init___bad_datatype_for_order_leads_to_failure(self): # bad datatype for order got_exception = False try: _ = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, order=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___cval_is_list(self): # cval as list aug = iaa.PiecewiseAffine(scale=0.7, nb_rows=5, nb_cols=5, mode="constant", cval=[0, 10]) assert is_parameter_instance(aug.cval, iap.Choice) assert aug.cval.a[0] == 0 assert aug.cval.a[1] == 10 def test___init___cval_is_tuple(self): # cval as tuple aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, mode="constant", cval=(0, 10)) assert is_parameter_instance(aug.cval, iap.Uniform) assert is_parameter_instance(aug.cval.a, iap.Deterministic) assert is_parameter_instance(aug.cval.b, iap.Deterministic) assert aug.cval.a.value == 0 assert aug.cval.b.value == 10 def test___init___cval_is_stochastic_parameter(self): # cval as StochasticParameter aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, mode="constant", cval=iap.DiscreteUniform(0, 10)) assert is_parameter_instance(aug.cval, iap.DiscreteUniform) assert is_parameter_instance(aug.cval.a, iap.Deterministic) assert is_parameter_instance(aug.cval.b, iap.Deterministic) assert aug.cval.a.value == 0 assert aug.cval.b.value == 10 def test___init___cval_is_all(self): # ALL as cval aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, mode="constant", cval=ia.ALL) assert is_parameter_instance(aug.cval, iap.Uniform) assert is_parameter_instance(aug.cval.a, iap.Deterministic) assert is_parameter_instance(aug.cval.b, iap.Deterministic) assert aug.cval.a.value == 0 assert aug.cval.b.value == 255 def test___init___bad_datatype_for_cval_leads_to_failure(self): # bas datatype for cval got_exception = False try: _ = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, cval=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___mode_is_string(self): # single string for mode aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, mode="nearest") assert is_parameter_instance(aug.mode, iap.Deterministic) assert aug.mode.value == "nearest" def test___init___mode_is_list(self): # list for mode aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, mode=["nearest", "edge", "symmetric"]) assert is_parameter_instance(aug.mode, iap.Choice) assert all([ v in aug.mode.a for v in ["nearest", "edge", "symmetric"] ]) def test___init___mode_is_stochastic_parameter(self): # StochasticParameter for mode aug = iaa.PiecewiseAffine( scale=0.1, nb_rows=8, nb_cols=8, mode=iap.Choice(["nearest", "edge", "symmetric"])) assert is_parameter_instance(aug.mode, iap.Choice) assert all([ v in aug.mode.a for v in ["nearest", "edge", "symmetric"] ]) def test___init___mode_is_all(self): # ALL for mode aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, mode=ia.ALL) assert is_parameter_instance(aug.mode, iap.Choice) assert all([ v in aug.mode.a for v in ["constant", "edge", "symmetric", "reflect", "wrap"] ]) def test___init___bad_datatype_for_mode_leads_to_failure(self): # bad datatype for mode got_exception = False try: _ = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=8, mode=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception # ----- # scale # ----- def test_scale_is_small_image(self): # basic test aug = iaa.PiecewiseAffine(scale=0.01, nb_rows=12, nb_cols=4) observed = aug.augment_image(self.image) assert ( 100.0 < np.average(observed[self.mask]) < np.average(self.image[self.mask]) ) assert ( 100.0-75.0 > np.average(observed[~self.mask]) > np.average(self.image[~self.mask]) ) def test_scale_is_small_image_absolute_scale(self): aug = iaa.PiecewiseAffine(scale=1, nb_rows=12, nb_cols=4, absolute_scale=True) observed = aug.augment_image(self.image) assert ( 100.0 < np.average(observed[self.mask]) < np.average(self.image[self.mask]) ) assert ( 100.0-75.0 > np.average(observed[~self.mask]) > np.average(self.image[~self.mask]) ) def test_scale_is_small_heatmaps(self): # basic test, heatmaps aug = iaa.PiecewiseAffine(scale=0.01, nb_rows=12, nb_cols=4) observed = aug.augment_heatmaps([self.heatmaps])[0] observed_arr = observed.get_arr() assert observed.shape == self.heatmaps.shape _assert_same_min_max(observed, self.heatmaps) assert ( 100.0/255.0 < np.average(observed_arr[self.mask]) < np.average(self.heatmaps.get_arr()[self.mask])) assert ( (100.0-75.0)/255.0 > np.average(observed_arr[~self.mask]) > np.average(self.heatmaps.get_arr()[~self.mask])) def test_scale_is_small_segmaps(self): # basic test, segmaps aug = iaa.PiecewiseAffine(scale=0.001, nb_rows=12, nb_cols=4) observed = aug.augment_segmentation_maps([self.segmaps])[0] observed_arr = observed.get_arr() # left column starts at 9-11 and right one at 69-71 # result is 9-11 (curvy, i.e. like 50% filled) and 70-71 (straight, # i.e. 100% filled). Reason for that is unclear, maybe a scikit-image # problem. observed_arr_left_col = observed_arr[:, 9:11+1] observed_arr_right_col = observed_arr[:, 69:71+1] assert observed.shape == self.segmaps.shape assert np.average(observed_arr_left_col == 1) > 0.5 assert np.average(observed_arr_right_col == 1) > 0.5 assert np.average(observed_arr[~self.mask] == 0) > 0.9 def test_scale_is_zero_image(self): # scale 0 aug = iaa.PiecewiseAffine(scale=0, nb_rows=12, nb_cols=4) observed = aug.augment_image(self.image) assert np.array_equal(observed, self.image) def test_scale_is_zero_image_absolute_scale(self): aug = iaa.PiecewiseAffine(scale=0, nb_rows=12, nb_cols=4, absolute_scale=True) observed = aug.augment_image(self.image) assert np.array_equal(observed, self.image) def test_scale_is_zero_heatmaps(self): # scale 0, heatmaps aug = iaa.PiecewiseAffine(scale=0, nb_rows=12, nb_cols=4) observed = aug.augment_heatmaps([self.heatmaps])[0] observed_arr = observed.get_arr() assert observed.shape == self.heatmaps.shape _assert_same_min_max(observed, self.heatmaps) assert np.array_equal(observed_arr, self.heatmaps.get_arr()) def test_scale_is_zero_segmaps(self): # scale 0, segmaps aug = iaa.PiecewiseAffine(scale=0, nb_rows=12, nb_cols=4) observed = aug.augment_segmentation_maps([self.segmaps])[0] observed_arr = observed.get_arr() assert observed.shape == self.segmaps.shape assert np.array_equal(observed_arr, self.segmaps.get_arr()) def test_scale_is_zero_keypoints(self): # scale 0, keypoints aug = iaa.PiecewiseAffine(scale=0, nb_rows=12, nb_cols=4) kps = [ia.Keypoint(x=5, y=3), ia.Keypoint(x=3, y=8)] kpsoi = ia.KeypointsOnImage(kps, shape=(14, 14, 3)) kpsoi_aug = aug.augment_keypoints([kpsoi])[0] assert_cbaois_equal(kpsoi_aug, kpsoi) @classmethod def _test_scale_is_zero_cbaoi(cls, cbaoi, augf_name): aug = iaa.PiecewiseAffine(scale=0, nb_rows=10, nb_cols=10) observed = getattr(aug, augf_name)(cbaoi) assert_cbaois_equal(observed, cbaoi) def test_scale_is_zero_polygons(self): exterior = [(10, 10), (70, 10), (70, 20), (70, 30), (70, 40), (70, 50), (70, 60), (70, 70), (70, 80), (70, 90), (10, 90), (10, 80), (10, 70), (10, 60), (10, 50), (10, 40), (10, 30), (10, 20), (10, 10)] poly = ia.Polygon(exterior) psoi = ia.PolygonsOnImage([poly, poly.shift(x=1, y=1)], shape=(100, 80)) self._test_scale_is_zero_cbaoi(psoi, "augment_polygons") def test_scale_is_zero_line_strings(self): coords = [(10, 10), (70, 10), (70, 20), (70, 30), (70, 40), (70, 50), (70, 60), (70, 70), (70, 80), (70, 90), (10, 90), (10, 80), (10, 70), (10, 60), (10, 50), (10, 40), (10, 30), (10, 20), (10, 10)] ls = ia.LineString(coords) lsoi = ia.LineStringsOnImage([ls, ls.shift(x=1, y=1)], shape=(100, 80)) self._test_scale_is_zero_cbaoi(lsoi, "augment_line_strings") def test_scale_is_zero_bounding_boxes(self): bb = ia.BoundingBox(x1=10, y1=10, x2=70, y2=20) bbsoi = ia.BoundingBoxesOnImage([bb, bb.shift(x=1, y=1)], shape=(100, 80)) self._test_scale_is_zero_cbaoi(bbsoi, "augment_bounding_boxes") def test_scale_stronger_values_should_increase_changes_images(self): # stronger scale should lead to stronger changes aug1 = iaa.PiecewiseAffine(scale=0.01, nb_rows=12, nb_cols=4) aug2 = iaa.PiecewiseAffine(scale=0.10, nb_rows=12, nb_cols=4) observed1 = aug1.augment_image(self.image) observed2 = aug2.augment_image(self.image) assert ( np.average(observed1[~self.mask]) < np.average(observed2[~self.mask]) ) def test_scale_stronger_values_should_increase_changes_images_abs(self): aug1 = iaa.PiecewiseAffine(scale=1, nb_rows=12, nb_cols=4, absolute_scale=True) aug2 = iaa.PiecewiseAffine(scale=10, nb_rows=12, nb_cols=4, absolute_scale=True) observed1 = aug1.augment_image(self.image) observed2 = aug2.augment_image(self.image) assert ( np.average(observed1[~self.mask]) < np.average(observed2[~self.mask]) ) def test_scale_stronger_values_should_increase_changes_heatmaps(self): # stronger scale should lead to stronger changes, heatmaps aug1 = iaa.PiecewiseAffine(scale=0.01, nb_rows=12, nb_cols=4) aug2 = iaa.PiecewiseAffine(scale=0.10, nb_rows=12, nb_cols=4) observed1 = aug1.augment_heatmaps([self.heatmaps])[0] observed2 = aug2.augment_heatmaps([self.heatmaps])[0] observed1_arr = observed1.get_arr() observed2_arr = observed2.get_arr() assert observed1.shape == self.heatmaps.shape assert observed2.shape == self.heatmaps.shape _assert_same_min_max(observed1, self.heatmaps) _assert_same_min_max(observed2, self.heatmaps) assert ( np.average(observed1_arr[~self.mask]) < np.average(observed2_arr[~self.mask]) ) def test_scale_stronger_values_should_increase_changes_heatmaps_abs(self): aug1 = iaa.PiecewiseAffine(scale=1, nb_rows=12, nb_cols=4, absolute_scale=True) aug2 = iaa.PiecewiseAffine(scale=10, nb_rows=12, nb_cols=4, absolute_scale=True) observed1 = aug1.augment_heatmaps([self.heatmaps])[0] observed2 = aug2.augment_heatmaps([self.heatmaps])[0] observed1_arr = observed1.get_arr() observed2_arr = observed2.get_arr() assert observed1.shape == self.heatmaps.shape assert observed2.shape == self.heatmaps.shape _assert_same_min_max(observed1, self.heatmaps) _assert_same_min_max(observed2, self.heatmaps) assert ( np.average(observed1_arr[~self.mask]) < np.average(observed2_arr[~self.mask]) ) def test_scale_stronger_values_should_increase_changes_segmaps(self): # stronger scale should lead to stronger changes, segmaps aug1 = iaa.PiecewiseAffine(scale=0.01, nb_rows=12, nb_cols=4) aug2 = iaa.PiecewiseAffine(scale=0.10, nb_rows=12, nb_cols=4) observed1 = aug1.augment_segmentation_maps([self.segmaps])[0] observed2 = aug2.augment_segmentation_maps([self.segmaps])[0] observed1_arr = observed1.get_arr() observed2_arr = observed2.get_arr() assert observed1.shape == self.segmaps.shape assert observed2.shape == self.segmaps.shape assert ( np.average(observed1_arr[~self.mask] == 0) > np.average(observed2_arr[~self.mask] == 0) ) def test_scale_alignment_between_images_and_heatmaps(self): # strong scale, measure alignment between images and heatmaps aug = iaa.PiecewiseAffine(scale=0.10, nb_rows=12, nb_cols=4) aug_det = aug.to_deterministic() img_aug = aug_det.augment_image(self.image) hm_aug = aug_det.augment_heatmaps([self.heatmaps])[0] img_aug_mask = img_aug > 255*0.1 hm_aug_mask = hm_aug.arr_0to1 > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert hm_aug.shape == (60, 80, 3) _assert_same_min_max(hm_aug, self.heatmaps) assert (same / img_aug_mask.size) >= 0.98 def test_scale_alignment_between_images_and_segmaps(self): # strong scale, measure alignment between images and segmaps aug = iaa.PiecewiseAffine(scale=0.10, nb_rows=12, nb_cols=4) aug_det = aug.to_deterministic() img_aug = aug_det.augment_image(self.image) segmap_aug = aug_det.augment_segmentation_maps([self.segmaps])[0] img_aug_mask = (img_aug > 255*0.1) segmap_aug_mask = (segmap_aug.arr == 1) same = np.sum(img_aug_mask == segmap_aug_mask[:, :, 0]) assert segmap_aug.shape == (60, 80, 3) assert (same / img_aug_mask.size) >= 0.9 def test_scale_alignment_between_images_and_smaller_heatmaps(self): # strong scale, measure alignment between images and heatmaps # heatmaps here smaller than image aug = iaa.PiecewiseAffine(scale=0.10, nb_rows=12, nb_cols=4) aug_det = aug.to_deterministic() heatmaps_small = ia.HeatmapsOnImage( ( ia.imresize_single_image( self.image, (30, 40+10), interpolation="cubic" ) / 255.0 ).astype(np.float32), shape=(60, 80, 3) ) img_aug = aug_det.augment_image(self.image) hm_aug = aug_det.augment_heatmaps([heatmaps_small])[0] img_aug_mask = img_aug > 255*0.1 hm_aug_mask = ia.imresize_single_image( hm_aug.arr_0to1, (60, 80), interpolation="cubic" ) > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert hm_aug.shape == (60, 80, 3) assert hm_aug.arr_0to1.shape == (30, 40+10, 1) assert (same / img_aug_mask.size) >= 0.9 # seems to be 0.948 actually def test_scale_alignment_between_images_and_smaller_heatmaps_abs(self): # image is 60x80, so a scale of 8 is about 0.1*max(60,80) aug = iaa.PiecewiseAffine(scale=8, nb_rows=12, nb_cols=4, absolute_scale=True) aug_det = aug.to_deterministic() heatmaps_small = ia.HeatmapsOnImage( ( ia.imresize_single_image( self.image, (30, 40+10), interpolation="cubic" ) / 255.0 ).astype(np.float32), shape=(60, 80, 3) ) img_aug = aug_det.augment_image(self.image) hm_aug = aug_det.augment_heatmaps([heatmaps_small])[0] img_aug_mask = img_aug > 255*0.1 hm_aug_mask = ia.imresize_single_image( hm_aug.arr_0to1, (60, 80), interpolation="cubic" ) > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert hm_aug.shape == (60, 80, 3) assert hm_aug.arr_0to1.shape == (30, 40+10, 1) assert (same / img_aug_mask.size) >= 0.9 # seems to be 0.930 actually def test_scale_alignment_between_images_and_smaller_segmaps(self): # strong scale, measure alignment between images and segmaps # segmaps here smaller than image aug = iaa.PiecewiseAffine(scale=0.10, nb_rows=12, nb_cols=4) aug_det = aug.to_deterministic() segmaps_small = SegmentationMapsOnImage( ( ia.imresize_single_image( self.image, (30, 40+10), interpolation="cubic" ) > 100 ).astype(np.int32), shape=(60, 80, 3) ) img_aug = aug_det.augment_image(self.image) segmaps_aug = aug_det.augment_segmentation_maps([segmaps_small])[0] img_aug_mask = img_aug > 255*0.1 segmaps_aug_mask = ( ia.imresize_single_image( segmaps_aug.arr, (60, 80), interpolation="nearest" ) == 1 ) same = np.sum(img_aug_mask == segmaps_aug_mask[:, :, 0]) assert segmaps_aug.shape == (60, 80, 3) assert segmaps_aug.arr.shape == (30, 40+10, 1) assert (same / img_aug_mask.size) >= 0.9 def test_scale_alignment_between_images_and_keypoints(self): # strong scale, measure alignment between images and keypoints # fairly large scale here, as otherwise keypoints can end up # outside of the image plane aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=12, nb_cols=4) aug_det = aug.to_deterministic() kps = [ia.Keypoint(x=160, y=110), ia.Keypoint(x=140, y=90)] kpsoi = ia.KeypointsOnImage(kps, shape=(200, 300, 3)) img_kps = np.zeros((200, 300, 3), dtype=np.uint8) img_kps = kpsoi.draw_on_image(img_kps, color=[255, 255, 255]) img_kps_aug = aug_det.augment_image(img_kps) kpsoi_aug = aug_det.augment_keypoints([kpsoi])[0] assert kpsoi_aug.shape == (200, 300, 3) bb1 = ia.BoundingBox( x1=kpsoi_aug.keypoints[0].x-1, y1=kpsoi_aug.keypoints[0].y-1, x2=kpsoi_aug.keypoints[0].x+1, y2=kpsoi_aug.keypoints[0].y+1) bb2 = ia.BoundingBox( x1=kpsoi_aug.keypoints[1].x-1, y1=kpsoi_aug.keypoints[1].y-1, x2=kpsoi_aug.keypoints[1].x+1, y2=kpsoi_aug.keypoints[1].y+1) patch1 = bb1.extract_from_image(img_kps_aug) patch2 = bb2.extract_from_image(img_kps_aug) assert np.max(patch1) > 150 assert np.max(patch2) > 150 assert np.average(img_kps_aug) < 40 # this test was apparently added later on (?) without noticing that # a similar test already existed def test_scale_alignment_between_images_and_keypoints2(self): img = np.zeros((100, 80), dtype=np.uint8) img[:, 9:11+1] = 255 img[:, 69:71+1] = 255 kps = [ia.Keypoint(x=10, y=20), ia.Keypoint(x=10, y=40), ia.Keypoint(x=70, y=20), ia.Keypoint(x=70, y=40)] kpsoi = ia.KeypointsOnImage(kps, shape=img.shape) aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=10, nb_cols=10) aug_det = aug.to_deterministic() observed_img = aug_det.augment_image(img) observed_kpsoi = aug_det.augment_keypoints([kpsoi]) assert not keypoints_equal([kpsoi], observed_kpsoi) for kp in observed_kpsoi[0].keypoints: assert observed_img[int(kp.y), int(kp.x)] > 0 @classmethod def _test_scale_alignment_between_images_and_poly_or_line_strings( cls, cba_class, cbaoi_class, augf_name): img = np.zeros((100, 80), dtype=np.uint8) img[:, 10-5:10+5] = 255 img[:, 70-5:70+5] = 255 coords = [(10, 10), (70, 10), (70, 20), (70, 30), (70, 40), (70, 50), (70, 60), (70, 70), (70, 80), (70, 90), (10, 90), (10, 80), (10, 70), (10, 60), (10, 50), (10, 40), (10, 30), (10, 20), (10, 10)] cba = cba_class(coords) cbaoi = cbaoi_class([cba, cba.shift(x=1, y=1)], shape=img.shape) aug = iaa.PiecewiseAffine(scale=0.03, nb_rows=10, nb_cols=10) aug_det = aug.to_deterministic() observed_imgs = aug_det.augment_images([img, img]) observed_cbaois = getattr(aug_det, augf_name)([cbaoi, cbaoi]) for observed_img, observed_cbaoi in zip(observed_imgs, observed_cbaois): assert observed_cbaoi.shape == img.shape for cba_aug in observed_cbaoi.items: if hasattr(cba_aug, "is_valid"): assert cba_aug.is_valid for point_aug in cba_aug.coords: x = int(np.round(point_aug[0])) y = int(np.round(point_aug[1])) assert observed_img[y, x] > 0 def test_scale_alignment_between_images_and_polygons(self): self._test_scale_alignment_between_images_and_poly_or_line_strings( ia.Polygon, ia.PolygonsOnImage, "augment_polygons") def test_scale_alignment_between_images_and_line_strings(self): self._test_scale_alignment_between_images_and_poly_or_line_strings( ia.LineString, ia.LineStringsOnImage, "augment_line_strings") def test_scale_alignment_between_images_and_bounding_boxes(self): img = np.zeros((100, 80), dtype=np.uint8) s = 0 img[10-s:10+s+1, 20-s:20+s+1] = 255 img[60-s:60+s+1, 70-s:70+s+1] = 255 bb = ia.BoundingBox(y1=10, x1=20, y2=60, x2=70) bbsoi = ia.BoundingBoxesOnImage([bb], shape=img.shape) aug = iaa.PiecewiseAffine(scale=0.03, nb_rows=10, nb_cols=10) observed_imgs, observed_bbsois = aug( images=[img], bounding_boxes=[bbsoi]) for observed_img, observed_bbsoi in zip(observed_imgs, observed_bbsois): assert observed_bbsoi.shape == img.shape observed_img_x = np.max(observed_img, axis=0) observed_img_y = np.max(observed_img, axis=1) nonz_x = np.nonzero(observed_img_x)[0] nonz_y = np.nonzero(observed_img_y)[0] img_x1 = min(nonz_x) img_x2 = max(nonz_x) img_y1 = min(nonz_y) img_y2 = max(nonz_y) expected = ia.BoundingBox(x1=img_x1, y1=img_y1, x2=img_x2, y2=img_y2) for bb_aug in observed_bbsoi.bounding_boxes: # we don't expect perfect IoU here, because the actual # underlying KP aug used distance maps # most IoUs seem to end up in the range 0.9-0.95 assert bb_aug.iou(expected) > 0.8 def test_scale_is_list(self): aug1 = iaa.PiecewiseAffine(scale=0.01, nb_rows=12, nb_cols=4) aug2 = iaa.PiecewiseAffine(scale=0.10, nb_rows=12, nb_cols=4) aug = iaa.PiecewiseAffine(scale=[0.01, 0.10], nb_rows=12, nb_cols=4) avg1 = np.average([ np.average( aug1.augment_image(self.image) * (~self.mask).astype(np.float32) ) for _ in sm.xrange(3) ]) avg2 = np.average([ np.average( aug2.augment_image(self.image) * (~self.mask).astype(np.float32) ) for _ in sm.xrange(3) ]) seen = [0, 0] for _ in sm.xrange(15): observed = aug.augment_image(self.image) avg = np.average(observed * (~self.mask).astype(np.float32)) diff1 = abs(avg - avg1) diff2 = abs(avg - avg2) if diff1 < diff2: seen[0] += 1 else: seen[1] += 1 assert seen[0] > 0 assert seen[1] > 0 # ----- # rows and cols # ----- @classmethod def _compute_observed_std_ygrad_in_mask(cls, observed, mask): grad_vert = ( observed[1:, :].astype(np.float32) - observed[:-1, :].astype(np.float32) ) grad_vert = grad_vert * (~mask[1:, :]).astype(np.float32) return np.std(grad_vert) def _compute_std_ygrad_in_mask(self, aug, image, mask, nb_iterations): stds = [] for _ in sm.xrange(nb_iterations): observed = aug.augment_image(image) stds.append( self._compute_observed_std_ygrad_in_mask(observed, mask) ) return np.average(stds) def test_nb_rows_affects_images(self): # verify effects of rows aug1 = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=4) aug2 = iaa.PiecewiseAffine(scale=0.05, nb_rows=30, nb_cols=4) std1 = self._compute_std_ygrad_in_mask(aug1, self.image, self.mask, 3) std2 = self._compute_std_ygrad_in_mask(aug2, self.image, self.mask, 3) assert std1 < std2 def test_nb_rows_is_list_affects_images(self): # rows as list aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=[4, 20], nb_cols=4) aug1 = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=4) aug2 = iaa.PiecewiseAffine(scale=0.05, nb_rows=30, nb_cols=4) std1 = self._compute_std_ygrad_in_mask(aug1, self.image, self.mask, 3) std2 = self._compute_std_ygrad_in_mask(aug2, self.image, self.mask, 3) seen = [0, 0] for _ in sm.xrange(20): observed = aug.augment_image(self.image) std = self._compute_observed_std_ygrad_in_mask(observed, self.mask) diff1 = abs(std - std1) diff2 = abs(std - std2) if diff1 < diff2: seen[0] += 1 else: seen[1] += 1 assert seen[0] > 0 assert seen[1] > 0 def test_nb_cols_affects_images(self): # verify effects of cols image = self.image.T mask = self.mask.T aug1 = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=4) aug2 = iaa.PiecewiseAffine(scale=0.05, nb_rows=20, nb_cols=4) std1 = self._compute_std_ygrad_in_mask(aug1, image, mask, 3) std2 = self._compute_std_ygrad_in_mask(aug2, image, mask, 3) assert std1 < std2 def test_nb_cols_is_list_affects_images(self): # cols as list image = self.image.T mask = self.mask.T aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=[4, 20]) aug1 = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=4) aug2 = iaa.PiecewiseAffine(scale=0.05, nb_rows=4, nb_cols=30) std1 = self._compute_std_ygrad_in_mask(aug1, image, mask, 3) std2 = self._compute_std_ygrad_in_mask(aug2, image, mask, 3) seen = [0, 0] for _ in sm.xrange(20): observed = aug.augment_image(image) std = self._compute_observed_std_ygrad_in_mask(observed, mask) diff1 = abs(std - std1) diff2 = abs(std - std2) if diff1 < diff2: seen[0] += 1 else: seen[1] += 1 assert seen[0] > 0 assert seen[1] > 0 # ----- # order # ----- # TODO # ----- # cval # ----- def test_cval_is_zero(self): # since scikit-image 0.16.2 and scipy 1.4.0(!), this test requires # several iterations to find one image that required filling with cval found = False for _ in np.arange(50): img = np.zeros((16, 16, 3), dtype=np.uint8) + 255 aug = iaa.PiecewiseAffine(scale=0.7, nb_rows=10, nb_cols=10, mode="constant", cval=0) observed = aug.augment_image(img) if np.sum([observed[:, :] == [0, 0, 0]]) > 0: found = True break assert found def test_cval_should_be_ignored_by_heatmaps(self): # cval as deterministic, heatmaps should always use cval=0 heatmaps = HeatmapsOnImage( np.zeros((50, 50, 1), dtype=np.float32), shape=(50, 50, 3)) aug = iaa.PiecewiseAffine(scale=0.7, nb_rows=10, nb_cols=10, mode="constant", cval=255) observed = aug.augment_heatmaps([heatmaps])[0] assert np.sum([observed.get_arr()[:, :] >= 0.01]) == 0 def test_cval_should_be_ignored_by_segmaps(self): # cval as deterministic, segmaps should always use cval=0 segmaps = SegmentationMapsOnImage( np.zeros((50, 50, 1), dtype=np.int32), shape=(50, 50, 3)) aug = iaa.PiecewiseAffine(scale=0.7, nb_rows=10, nb_cols=10, mode="constant", cval=255) observed = aug.augment_segmentation_maps([segmaps])[0] assert np.sum([observed.get_arr()[:, :] > 0]) == 0 def test_cval_is_list(self): # cval as list img = np.zeros((20, 20), dtype=np.uint8) + 255 aug = iaa.PiecewiseAffine(scale=0.7, nb_rows=5, nb_cols=5, mode="constant", cval=[0, 10]) seen = [0, 0, 0] for _ in sm.xrange(30): observed = aug.augment_image(img) nb_0 = np.sum([observed[:, :] == 0]) nb_10 = np.sum([observed[:, :] == 10]) if nb_0 > 0: seen[0] += 1 elif nb_10 > 0: seen[1] += 1 else: seen[2] += 1 assert seen[0] > 5 assert seen[1] > 5 assert seen[2] <= 4 # ----- # mode # ----- # TODO # --------- # remaining keypoints tests # --------- def test_keypoints_outside_of_image(self): # keypoints outside of image aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=10, nb_cols=10) kps = [ia.Keypoint(x=-10, y=-20)] kpsoi = ia.KeypointsOnImage(kps, shape=(10, 10, 3)) observed = aug.augment_keypoints(kpsoi) assert_cbaois_equal(observed, kpsoi) def test_keypoints_empty(self): # empty keypoints aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=10, nb_cols=10) kpsoi = ia.KeypointsOnImage([], shape=(10, 10, 3)) observed = aug.augment_keypoints(kpsoi) assert_cbaois_equal(observed, kpsoi) # --------- # remaining polygons tests # --------- def test_polygons_outside_of_image(self): aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=10, nb_cols=10) exterior = [(-10, -10), (110, -10), (110, 90), (-10, 90)] poly = ia.Polygon(exterior) psoi = ia.PolygonsOnImage([poly], shape=(10, 10, 3)) observed = aug.augment_polygons(psoi) assert_cbaois_equal(observed, psoi) def test_empty_polygons(self): aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=10, nb_cols=10) psoi = ia.PolygonsOnImage([], shape=(10, 10, 3)) observed = aug.augment_polygons(psoi) assert_cbaois_equal(observed, psoi) # --------- # remaining line string tests # --------- def test_line_strings_outside_of_image(self): aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=10, nb_cols=10) coords = [(-10, -10), (110, -10), (110, 90), (-10, 90)] ls = ia.LineString(coords) lsoi = ia.LineStringsOnImage([ls], shape=(10, 10, 3)) observed = aug.augment_line_strings(lsoi) assert_cbaois_equal(observed, lsoi) def test_empty_line_strings(self): aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=10, nb_cols=10) lsoi = ia.LineStringsOnImage([], shape=(10, 10, 3)) observed = aug.augment_line_strings(lsoi) assert_cbaois_equal(observed, lsoi) # --------- # remaining bounding box tests # --------- def test_bounding_boxes_outside_of_image(self): aug = iaa.PiecewiseAffine(scale=0.05, nb_rows=10, nb_cols=10) bbs = ia.BoundingBox(x1=-10, y1=-10, x2=15, y2=15) bbsoi = ia.BoundingBoxesOnImage([bbs], shape=(10, 10, 3)) observed = aug.augment_bounding_boxes(bbsoi) assert_cbaois_equal(observed, bbsoi) def test_empty_bounding_boxes(self): aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=10, nb_cols=10) bbsoi = ia.BoundingBoxesOnImage([], shape=(10, 10, 3)) observed = aug.augment_bounding_boxes(bbsoi) assert_cbaois_equal(observed, bbsoi) # --------- # zero-sized axes # --------- 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.PiecewiseAffine(scale=0.05, nb_rows=2, nb_cols=2) image_aug = aug(image=image) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape def test_zero_sized_axes_absolute_scale(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.PiecewiseAffine(scale=5, nb_rows=2, nb_cols=2, absolute_scale=True) image_aug = aug(image=image) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape # --------- # other methods # --------- def test_get_parameters(self): aug = iaa.PiecewiseAffine(scale=0.1, nb_rows=8, nb_cols=10, order=1, cval=2, mode="constant", absolute_scale=False) params = aug.get_parameters() assert params[0] is aug.jitter.scale assert params[1] is aug.nb_rows assert params[2] is aug.nb_cols assert params[3] is aug.order assert params[4] is aug.cval assert params[5] is aug.mode assert params[6] is False assert 0.1 - 1e-8 < params[0].value < 0.1 + 1e-8 assert params[1].value == 8 assert params[2].value == 10 assert params[3].value == 1 assert params[4].value == 2 assert params[5].value == "constant" # --------- # other dtypes # --------- @property def other_dtypes_mask(self): mask = np.zeros((21, 21), dtype=bool) mask[:, 7:13] = True return mask def test_other_dtypes_bool(self): aug = iaa.PiecewiseAffine(scale=0.2, nb_rows=8, nb_cols=4, order=0, mode="constant") image = np.zeros((21, 21), dtype=bool) image[self.other_dtypes_mask] = True image_aug = aug.augment_image(image) assert image_aug.dtype.name == image.dtype.name assert not np.all(image_aug == 1) assert np.any(image_aug[~self.other_dtypes_mask] == 1) def test_other_dtypes_uint_int(self): aug = iaa.PiecewiseAffine(scale=0.2, nb_rows=8, nb_cols=4, order=0, mode="constant") dtypes = ["uint8", "uint16", "uint32", "int8", "int16", "int32"] for dtype in dtypes: min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) if np.dtype(dtype).kind == "i": values = [1, 5, 10, 100, int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value-100, max_value] values = values + [(-1)*value for value in values] else: values = [1, 5, 10, 100, int(center_value), int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value-100, max_value] for value in values: with self.subTest(dtype=dtype, value=value): image = np.zeros((21, 21), dtype=dtype) image[:, 7:13] = value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert not np.all(image_aug == value) assert np.any(image_aug[~self.other_dtypes_mask] == value) def test_other_dtypes_float(self): aug = iaa.PiecewiseAffine(scale=0.2, nb_rows=8, nb_cols=4, order=0, mode="constant") dtypes = ["float16", "float32", "float64"] for dtype in dtypes: min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) def _isclose(a, b): atol = 1e-4 if dtype == "float16" else 1e-8 return np.isclose(a, b, atol=atol, rtol=0) isize = np.dtype(dtype).itemsize values = [ 0.01, 1.0, 10.0, 100.0, 500 ** (isize - 1), float(np.float64(1000 ** (isize - 1))) ] values = values + [(-1) * value for value in values] values = values + [min_value, max_value] for value in values: with self.subTest(dtype=dtype, value=value): image = np.zeros((21, 21), dtype=dtype) image[:, 7:13] = value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert not np.all(_isclose(image_aug, value)) assert np.any(_isclose(image_aug[~self.other_dtypes_mask], value)) def test_pickleable(self): aug = iaa.PiecewiseAffine(scale=0.2, nb_rows=4, nb_cols=4, seed=1) runtest_pickleable_uint8_img(aug, iterations=3, shape=(25, 25, 1)) class TestPerspectiveTransform(unittest.TestCase): def setUp(self): reseed() @property def image(self): img = np.zeros((30, 30), dtype=np.uint8) img[10:20, 10:20] = 255 return img @property def heatmaps(self): return HeatmapsOnImage((self.image / 255.0).astype(np.float32), shape=self.image.shape) @property def segmaps(self): return SegmentationMapsOnImage((self.image > 0).astype(np.int32), shape=self.image.shape) # -------- # __init__ # -------- def test___init___scale_is_tuple(self): # tuple for scale aug = iaa.PerspectiveTransform(scale=(0.1, 0.2)) assert is_parameter_instance(aug.jitter.scale, iap.Uniform) assert is_parameter_instance(aug.jitter.scale.a, iap.Deterministic) assert is_parameter_instance(aug.jitter.scale.b, iap.Deterministic) assert 0.1 - 1e-8 < aug.jitter.scale.a.value < 0.1 + 1e-8 assert 0.2 - 1e-8 < aug.jitter.scale.b.value < 0.2 + 1e-8 def test___init___scale_is_list(self): # list for scale aug = iaa.PerspectiveTransform(scale=[0.1, 0.2, 0.3]) assert is_parameter_instance(aug.jitter.scale, iap.Choice) assert len(aug.jitter.scale.a) == 3 assert 0.1 - 1e-8 < aug.jitter.scale.a[0] < 0.1 + 1e-8 assert 0.2 - 1e-8 < aug.jitter.scale.a[1] < 0.2 + 1e-8 assert 0.3 - 1e-8 < aug.jitter.scale.a[2] < 0.3 + 1e-8 def test___init___scale_is_stochastic_parameter(self): # StochasticParameter for scale aug = iaa.PerspectiveTransform(scale=iap.Choice([0.1, 0.2, 0.3])) assert is_parameter_instance(aug.jitter.scale, iap.Choice) assert len(aug.jitter.scale.a) == 3 assert 0.1 - 1e-8 < aug.jitter.scale.a[0] < 0.1 + 1e-8 assert 0.2 - 1e-8 < aug.jitter.scale.a[1] < 0.2 + 1e-8 assert 0.3 - 1e-8 < aug.jitter.scale.a[2] < 0.3 + 1e-8 def test___init___bad_datatype_for_scale_leads_to_failure(self): # bad datatype for scale got_exception = False try: _ = iaa.PerspectiveTransform(scale=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___mode_is_all(self): aug = iaa.PerspectiveTransform(cval=0, mode=ia.ALL) assert is_parameter_instance(aug.mode, iap.Choice) def test___init___mode_is_string(self): aug = iaa.PerspectiveTransform(cval=0, mode="replicate") assert is_parameter_instance(aug.mode, iap.Deterministic) assert aug.mode.value == "replicate" def test___init___mode_is_list(self): aug = iaa.PerspectiveTransform(cval=0, mode=["replicate", "constant"]) assert is_parameter_instance(aug.mode, iap.Choice) assert ( len(aug.mode.a) == 2 and "replicate" in aug.mode.a and "constant" in aug.mode.a) def test___init___mode_is_stochastic_parameter(self): aug = iaa.PerspectiveTransform( cval=0, mode=iap.Choice(["replicate", "constant"])) assert is_parameter_instance(aug.mode, iap.Choice) assert ( len(aug.mode.a) == 2 and "replicate" in aug.mode.a and "constant" in aug.mode.a) # -------- # image, heatmaps, segmaps # -------- def test_image_without_keep_size(self): # without keep_size aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) observed = aug.augment_image(self.image) y1 = int(30*0.2) y2 = int(30*0.8) x1 = int(30*0.2) x2 = int(30*0.8) expected = self.image[y1:y2, x1:x2] assert all([ abs(s1-s2) <= 1 for s1, s2 in zip(observed.shape, expected.shape) ]) if observed.shape != expected.shape: observed = ia.imresize_single_image( observed, expected.shape[0:2], interpolation="cubic") # differences seem to mainly appear around the border of the inner # rectangle, possibly due to interpolation assert np.average( np.abs(observed.astype(np.int32) - expected.astype(np.int32)) ) < 30.0 def test_image_heatmaps_alignment_without_keep_size(self): aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) hm = HeatmapsOnImage( self.image.astype(np.float32)/255.0, shape=(30, 30) ) observed = aug.augment_image(self.image) hm_aug = aug.augment_heatmaps([hm])[0] y1 = int(30*0.2) y2 = int(30*0.8) x1 = int(30*0.2) x2 = int(30*0.8) expected = (y2 - y1, x2 - x1) assert all([ abs(s1-s2) <= 1 for s1, s2 in zip(hm_aug.shape, expected) ]) assert all([ abs(s1-s2) <= 1 for s1, s2 in zip(hm_aug.arr_0to1.shape, expected + (1,)) ]) img_aug_mask = observed > 255*0.1 hm_aug_mask = hm_aug.arr_0to1 > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert (same / img_aug_mask.size) >= 0.99 def test_image_segmaps_alignment_without_keep_size(self): aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) segmaps = SegmentationMapsOnImage( (self.image > 100).astype(np.int32), shape=(30, 30) ) observed = aug.augment_image(self.image) segmaps_aug = aug.augment_segmentation_maps([segmaps])[0] y1 = int(30*0.2) y2 = int(30*0.8) x1 = int(30*0.2) x2 = int(30*0.8) expected = (y2 - y1, x2 - x1) assert all([ abs(s1-s2) <= 1 for s1, s2 in zip(segmaps_aug.shape, expected) ]) assert all([ abs(s1-s2) <= 1 for s1, s2 in zip(segmaps_aug.arr.shape, expected + (1,)) ]) img_aug_mask = observed > 255*0.5 segmaps_aug_mask = segmaps_aug.arr > 0 same = np.sum(img_aug_mask == segmaps_aug_mask[:, :, 0]) assert (same / img_aug_mask.size) >= 0.99 def test_consecutive_calls_produce_different_results(self): # PerspectiveTransform works with random_state.copy(), so we # test explicitly that it doesn't always use the same samples aug = iaa.PerspectiveTransform((0.0, 0.2)) image = np.mod(np.arange(16*16), 255).astype(np.uint8).reshape((16, 16)) nb_same = 0 last_image = aug(image=image) for _ in np.arange(100): image_aug = aug(image=image) nb_same += int(np.array_equal(image_aug, last_image)) assert nb_same <= 1 def test_heatmaps_smaller_than_image_without_keep_size(self): # without keep_size, different heatmap size aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) height, width = 300, 200 height_small, width_small = 150, 100 y1 = int(height*0.2) y2 = int(height*0.8) x1 = int(width*0.2) x2 = int(width*0.8) y1_small = int(height_small*0.2) y2_small = int(height_small*0.8) x1_small = int(width_small*0.2) x2_small = int(width_small*0.8) img_small = ia.imresize_single_image( self.image, (height_small, width_small), interpolation="cubic") hm = ia.HeatmapsOnImage( img_small.astype(np.float32)/255.0, shape=(height, width)) img_aug = aug.augment_image(self.image) hm_aug = aug.augment_heatmaps([hm])[0] expected = (y2 - y1, x2 - x1) expected_small = (y2_small - y1_small, x2_small - x1_small, 1) assert all([ abs(s1-s2) <= 1 for s1, s2 in zip(hm_aug.shape, expected) ]) assert all([ abs(s1-s2) <= 1 for s1, s2 in zip(hm_aug.arr_0to1.shape, expected_small) ]) img_aug_mask = img_aug > 255*0.1 hm_aug_mask = ia.imresize_single_image( hm_aug.arr_0to1, img_aug.shape[0:2], interpolation="linear" ) > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert (same / img_aug_mask.size) >= 0.96 def test_segmaps_smaller_than_image_without_keep_size(self): # without keep_size, different segmap size aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) y1 = int(30*0.2) y2 = int(30*0.8) x1 = int(30*0.2) x2 = int(30*0.8) x1_small = int(25*0.2) x2_small = int(25*0.8) y1_small = int(20*0.2) y2_small = int(20*0.8) img_small = ia.imresize_single_image( self.image, (20, 25), interpolation="cubic") seg = SegmentationMapsOnImage( (img_small > 100).astype(np.int32), shape=(30, 30)) img_aug = aug.augment_image(self.image) seg_aug = aug.augment_segmentation_maps([seg])[0] expected = (y2 - y1, x2 - x1) expected_small = (y2_small - y1_small, x2_small - x1_small, 1) assert all([ abs(s1-s2) <= 1 for s1, s2 in zip(seg_aug.shape, expected) ]) assert all([ abs(s1-s2) <= 1 for s1, s2 in zip(seg_aug.arr.shape, expected_small) ]) img_aug_mask = img_aug > 255*0.5 seg_aug_mask = ia.imresize_single_image( seg_aug.arr, img_aug.shape[0:2], interpolation="nearest") > 0 same = np.sum(img_aug_mask == seg_aug_mask[:, :, 0]) assert (same / img_aug_mask.size) >= 0.92 def test_image_with_keep_size(self): # with keep_size aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) aug.jitter = iap.Deterministic(0.2) observed = aug.augment_image(self.image) expected = self.image[int(30*0.2):int(30*0.8), int(30*0.2):int(30*0.8)] expected = ia.imresize_single_image( expected, self.image.shape[0:2], interpolation="cubic") assert observed.shape == self.image.shape # differences seem to mainly appear around the border of the inner # rectangle, possibly due to interpolation assert np.average( np.abs(observed.astype(np.int32) - expected.astype(np.int32)) ) < 30.0 def test_heatmaps_with_keep_size(self): # with keep_size, heatmaps aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) aug.jitter = iap.Deterministic(0.2) observed = aug.augment_heatmaps([self.heatmaps])[0] heatmaps_arr = self.heatmaps.get_arr() expected = heatmaps_arr[int(30*0.2):int(30*0.8), int(30*0.2):int(30*0.8)] expected = ia.imresize_single_image( (expected*255).astype(np.uint8), self.image.shape[0:2], interpolation="cubic") expected = (expected / 255.0).astype(np.float32) assert observed.shape == self.heatmaps.shape _assert_same_min_max(observed, self.heatmaps) # differences seem to mainly appear around the border of the inner # rectangle, possibly due to interpolation assert np.average(np.abs(observed.get_arr() - expected)) < 30.0 def test_segmaps_with_keep_size(self): # with keep_size, segmaps aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) aug.jitter = iap.Deterministic(0.2) observed = aug.augment_segmentation_maps([self.segmaps])[0] segmaps_arr = self.segmaps.get_arr() expected = segmaps_arr[int(30*0.2):int(30*0.8), int(30*0.2):int(30*0.8)] expected = ia.imresize_single_image( (expected*255).astype(np.uint8), self.image.shape[0:2], interpolation="cubic") expected = (expected > 255*0.5).astype(np.int32) assert observed.shape == self.segmaps.shape assert np.average(observed.get_arr() != expected) < 0.05 def test_image_rgb_with_keep_size(self): # with keep_size, RGB images aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) aug.jitter = iap.Deterministic(0.2) imgs = np.tile(self.image[np.newaxis, :, :, np.newaxis], (2, 1, 1, 3)) observed = aug.augment_images(imgs) for img_idx in sm.xrange(2): for c in sm.xrange(3): observed_i = observed[img_idx, :, :, c] expected = imgs[img_idx, int(30*0.2):int(30*0.8), int(30*0.2):int(30*0.8), c] expected = ia.imresize_single_image( expected, imgs.shape[1:3], interpolation="cubic") assert observed_i.shape == imgs.shape[1:3] # differences seem to mainly appear around the border of the # inner rectangle, possibly due to interpolation assert np.average( np.abs( observed_i.astype(np.int32) - expected.astype(np.int32) ) ) < 30.0 # -------- # keypoints # -------- def test_keypoints_without_keep_size(self): # keypoint augmentation without keep_size # TODO deviations of around 0.4-0.7 in this and the next test (between # expected and observed coordinates) -- why? kps = [ia.Keypoint(x=10, y=10), ia.Keypoint(x=14, y=11)] kpsoi = ia.KeypointsOnImage(kps, shape=self.image.shape) aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) observed = aug.augment_keypoints([kpsoi]) kps_expected = [ ia.Keypoint(x=10-0.2*30, y=10-0.2*30), ia.Keypoint(x=14-0.2*30, y=11-0.2*30) ] gen = zip(observed[0].keypoints, kps_expected) # TODO deviations of around 0.5 here from expected values, why? for kp_observed, kp_expected in gen: assert kp_observed.coords_almost_equals( kp_expected, max_distance=1.5) def test_keypoints_with_keep_size(self): # keypoint augmentation with keep_size kps = [ia.Keypoint(x=10, y=10), ia.Keypoint(x=14, y=11)] kpsoi = ia.KeypointsOnImage(kps, shape=self.image.shape) aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) aug.jitter = iap.Deterministic(0.2) observed = aug.augment_keypoints([kpsoi]) kps_expected = [ ia.Keypoint(x=((10-0.2*30)/(30*0.6))*30, y=((10-0.2*30)/(30*0.6))*30), ia.Keypoint(x=((14-0.2*30)/(30*0.6))*30, y=((11-0.2*30)/(30*0.6))*30) ] gen = zip(observed[0].keypoints, kps_expected) # TODO deviations of around 0.5 here from expected values, why? for kp_observed, kp_expected in gen: assert kp_observed.coords_almost_equals( kp_expected, max_distance=1.5) def test_image_keypoint_alignment(self): img = np.zeros((100, 100), dtype=np.uint8) img[25-3:25+3, 25-3:25+3] = 255 img[50-3:50+3, 25-3:25+3] = 255 img[75-3:75+3, 25-3:25+3] = 255 img[25-3:25+3, 75-3:75+3] = 255 img[50-3:50+3, 75-3:75+3] = 255 img[75-3:75+3, 75-3:75+3] = 255 img[50-3:75+3, 50-3:75+3] = 255 kps = [ ia.Keypoint(y=25, x=25), ia.Keypoint(y=50, x=25), ia.Keypoint(y=75, x=25), ia.Keypoint(y=25, x=75), ia.Keypoint(y=50, x=75), ia.Keypoint(y=75, x=75), ia.Keypoint(y=50, x=50) ] kpsoi = ia.KeypointsOnImage(kps, shape=img.shape) aug = iaa.PerspectiveTransform(scale=(0.05, 0.15), keep_size=True) for _ in sm.xrange(10): aug_det = aug.to_deterministic() imgs_aug = aug_det.augment_images([img, img]) kpsois_aug = aug_det.augment_keypoints([kpsoi, kpsoi]) for img_aug, kpsoi_aug in zip(imgs_aug, kpsois_aug): assert kpsoi_aug.shape == img.shape for kp_aug in kpsoi_aug.keypoints: x, y = int(np.round(kp_aug.x)), int(np.round(kp_aug.y)) if 0 <= x < img.shape[1] and 0 <= y < img.shape[0]: assert img_aug[y, x] > 10 def test_empty_keypoints(self): # test empty keypoints kpsoi = ia.KeypointsOnImage([], shape=(20, 10, 3)) aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) observed = aug.augment_keypoints(kpsoi) assert_cbaois_equal(observed, kpsoi) # -------- # abstract test methods for polygons and line strings # -------- @classmethod def _test_cbaois_without_keep_size(cls, cba_class, cbaoi_class, augf_name): points = np.float32([ [10, 10], [25, 10], [25, 25], [10, 25] ]) cbaoi = cbaoi_class([cba_class(points)], shape=(30, 30, 3)) aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) observed = getattr(aug, augf_name)(cbaoi) assert observed.shape == (30 - 12, 30 - 12, 3) assert len(observed.items) == 1 if hasattr(observed.items[0], "is_valid"): assert observed.items[0].is_valid points_expected = np.copy(points) points_expected[:, 0] -= 0.2 * 30 points_expected[:, 1] -= 0.2 * 30 # TODO deviations of around 0.5 here from expected values, why? assert observed.items[0].coords_almost_equals( points_expected, max_distance=1.5) @classmethod def _test_cbaois_with_keep_size(cls, cba_class, cbaoi_class, augf_name): # polygon augmentation with keep_size points = np.float32([ [10, 10], [25, 10], [25, 25], [10, 25] ]) cbaoi = cbaoi_class([cba_class(points)], shape=(30, 30, 3)) aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) aug.jitter = iap.Deterministic(0.2) observed = getattr(aug, augf_name)(cbaoi) assert observed.shape == (30, 30, 3) assert len(observed.items) == 1 if hasattr(observed.items[0], "is_valid"): assert observed.items[0].is_valid points_expected = np.copy(points) points_expected[:, 0] = ( (points_expected[:, 0] - 0.2 * 30) / (30 * 0.6) ) * 30 points_expected[:, 1] = ( (points_expected[:, 1] - 0.2 * 30) / (30 * 0.6) ) * 30 # TODO deviations of around 0.5 here from expected values, why? assert observed.items[0].coords_almost_equals( points_expected, max_distance=2.5) @classmethod def _test_image_cba_alignment(cls, cba_class, cbaoi_class, augf_name): img = np.zeros((100, 100), dtype=np.uint8) img[25-3:25+3, 25-3:25+3] = 255 img[50-3:50+3, 25-3:25+3] = 255 img[75-3:75+3, 25-3:25+3] = 255 img[25-3:25+3, 75-3:75+3] = 255 img[50-3:50+3, 75-3:75+3] = 255 img[75-3:75+3, 75-3:75+3] = 255 points = [ [25, 25], [75, 25], [75, 50], [75, 75], [25, 75], [25, 50] ] cbaoi = cbaoi_class([cba_class(points)], shape=img.shape) aug = iaa.PerspectiveTransform(scale=0.1, keep_size=True) for _ in sm.xrange(10): aug_det = aug.to_deterministic() imgs_aug = aug_det.augment_images([img] * 4) cbaois_aug = getattr(aug_det, augf_name)([cbaoi] * 4) for img_aug, cbaoi_aug in zip(imgs_aug, cbaois_aug): assert cbaoi_aug.shape == img.shape for cba_aug in cbaoi_aug.items: if hasattr(cba_aug, "is_valid"): assert cba_aug.is_valid for x, y in cba_aug.coords: if 0 <= x < img.shape[1] and 0 <= y < img.shape[0]: bb = ia.BoundingBox(x1=x-2, x2=x+2, y1=y-2, y2=y+2) img_ex = bb.extract_from_image(img_aug) assert np.any(img_ex > 10) @classmethod def _test_empty_cba(cls, cbaoi, augf_name): # test empty polygons aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) observed = getattr(aug, augf_name)(cbaoi) assert_cbaois_equal(observed, cbaoi) # -------- # polygons # -------- def test_polygons_without_keep_size(self): self._test_cbaois_without_keep_size(ia.Polygon, ia.PolygonsOnImage, "augment_polygons") def test_polygons_with_keep_size(self): self._test_cbaois_with_keep_size(ia.Polygon, ia.PolygonsOnImage, "augment_polygons") def test_image_polygon_alignment(self): self._test_image_cba_alignment(ia.Polygon, ia.PolygonsOnImage, "augment_polygons") def test_empty_polygons(self): psoi = ia.PolygonsOnImage([], shape=(20, 10, 3)) self._test_empty_cba(psoi, "augment_polygons") def test_polygons_under_extreme_scale_values(self): # test extreme scales # TODO when setting .min_height and .min_width in PerspectiveTransform # to 1x1, at least one of the output polygons was invalid and had # only 3 instead of the expected 4 points - why? for scale in [0.1, 0.2, 0.3, 0.4]: with self.subTest(scale=scale): exterior = np.float32([ [10, 10], [25, 10], [25, 25], [10, 25] ]) psoi = ia.PolygonsOnImage([ia.Polygon(exterior)], shape=(30, 30, 3)) aug = iaa.PerspectiveTransform(scale=scale, keep_size=True) aug.jitter = iap.Deterministic(scale) observed = aug.augment_polygons(psoi) assert observed.shape == (30, 30, 3) assert len(observed.polygons) == 1 assert observed.polygons[0].is_valid # FIXME this part is currently deactivated due to too large # deviations from expectations. As the alignment check # works, this is probably some error on the test side """ exterior_expected = np.copy(exterior) exterior_expected[:, 0] = ( (exterior_expected[:, 0] - scale * 30) / (30*(1-2*scale)) ) * 30 exterior_expected[:, 1] = ( (exterior_expected[:, 1] - scale * 30) / (30*(1-2*scale)) ) * 30 poly0 = observed.polygons[0] # TODO deviations of around 0.5 here from expected values, why? assert poly0.exterior_almost_equals( exterior_expected, max_distance=2.0) """ # -------- # line strings # -------- def test_line_strings_without_keep_size(self): self._test_cbaois_without_keep_size(ia.LineString, ia.LineStringsOnImage, "augment_line_strings") def test_line_strings_with_keep_size(self): self._test_cbaois_with_keep_size(ia.LineString, ia.LineStringsOnImage, "augment_line_strings") def test_image_line_string_alignment(self): self._test_image_cba_alignment(ia.LineString, ia.LineStringsOnImage, "augment_line_strings") def test_empty_line_strings(self): lsoi = ia.LineStringsOnImage([], shape=(20, 10, 3)) self._test_empty_cba(lsoi, "augment_line_strings") # -------- # bounding boxes # -------- def test_bounding_boxes_without_keep_size(self): # BB augmentation without keep_size # TODO deviations of around 0.4-0.7 in this and the next test (between # expected and observed coordinates) -- why? bbs = [ia.BoundingBox(x1=0, y1=10, x2=20, y2=20)] bbsoi = ia.BoundingBoxesOnImage(bbs, shape=self.image.shape) aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) observed = aug.augment_bounding_boxes([bbsoi]) bbs_expected = [ ia.BoundingBox(x1=0-0.2*30, y1=10-0.2*30, x2=20-0.2*30, y2=20-0.2*30) ] gen = zip(observed[0].bounding_boxes, bbs_expected) # TODO deviations of around 0.5 here from expected values, why? for bb_observed, bb_expected in gen: assert bb_observed.coords_almost_equals( bb_expected, max_distance=1.5) def test_bounding_boxes_with_keep_size(self): # BB augmentation with keep_size bbs = [ia.BoundingBox(x1=0, y1=10, x2=20, y2=20)] bbsoi = ia.BoundingBoxesOnImage(bbs, shape=self.image.shape) aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) aug.jitter = iap.Deterministic(0.2) observed = aug.augment_bounding_boxes([bbsoi]) bbs_expected = [ ia.BoundingBox( x1=((0-0.2*30)/(30*0.6))*30, y1=((10-0.2*30)/(30*0.6))*30, x2=((20-0.2*30)/(30*0.6))*30, y2=((20-0.2*30)/(30*0.6))*30 ) ] gen = zip(observed[0].bounding_boxes, bbs_expected) # TODO deviations of around 0.5 here from expected values, why? for bb_observed, bb_expected in gen: assert bb_observed.coords_almost_equals( bb_expected, max_distance=1.5) def test_image_bounding_box_alignment(self): img = np.zeros((100, 100), dtype=np.uint8) img[35:35+1, 35:65+1] = 255 img[65:65+1, 35:65+1] = 255 img[35:65+1, 35:35+1] = 255 img[35:65+1, 65:65+1] = 255 bbs = [ ia.BoundingBox(y1=35.5, x1=35.5, y2=65.5, x2=65.5), ] bbsoi = ia.BoundingBoxesOnImage(bbs, shape=img.shape) aug = iaa.PerspectiveTransform(scale=(0.05, 0.2), keep_size=True) for _ in sm.xrange(30): imgs_aug, bbsois_aug = aug( images=[img, img, img, img], bounding_boxes=[bbsoi, bbsoi, bbsoi, bbsoi]) nb_skipped = 0 for img_aug, bbsoi_aug in zip(imgs_aug, bbsois_aug): assert bbsoi_aug.shape == img_aug.shape for bb_aug in bbsoi_aug.bounding_boxes: if bb_aug.is_fully_within_image(img_aug): # top, bottom, left, right x1 = bb_aug.x1_int x2 = bb_aug.x2_int y1 = bb_aug.y1_int y2 = bb_aug.y2_int top_row = img_aug[y1-1:y1+1, x1-1:x2+1] btm_row = img_aug[y2-1:y2+1, x1-1:x2+1] lft_row = img_aug[y1-1:y2+1, x1-1:x1+1] rgt_row = img_aug[y1-1:y2+1, x2-1:x2+1] assert np.max(top_row) > 10 assert np.max(btm_row) > 10 assert np.max(lft_row) > 10 assert np.max(rgt_row) > 10 else: nb_skipped += 1 assert nb_skipped <= 3 def test_bounding_boxes_cover_extreme_points(self): # Test that for BBs, the augmented BB x coord is really the minimum # of the BB corner x-coords after augmentation and e.g. not just always # the augmented top-left corner's coordinate. h = w = 200 # height, width s = 5 # block size j_r = 0.1 # relative amount of jitter j = int(h * j_r) # absolute amount of jitter # Note that PerspectiveTransform currently places four points on the # image and back-projects to the image size (roughly). # That's why e.g. TopWiderThanBottom has coordinates that seem like # the top is thinner than the bottom (after projecting back to the # image rectangle, the top becomes wider). class _JitterTopWiderThanBottom(object): def draw_samples(self, size, random_state): return np.float32([ [ [j_r, 0.0], # top-left [j_r, 0.0], # top-right [0.0, 0.0], # bottom-right [0.0, 0.0], # bottom-left ] ]) class _JitterTopThinnerThanBottom(object): def draw_samples(self, size, random_state): return np.float32([ [ [0.0, 0.0], # top-left [0.0, 0.0], # top-right [j_r, 0.0], # bottom-right [j_r, 0.0], # bottom-left ] ]) class _JitterLeftWiderThanRight(object): def draw_samples(self, size, random_state): return np.float32([ [ [0.0, j_r], # top-left [0.0, 0.0], # top-right [0.0, 0.0], # bottom-right [0.0, j_r], # bottom-left ] ]) class _JitterLeftThinnerThanRight(object): def draw_samples(self, size, random_state): return np.float32([ [ [0.0, 0.0], # top-left [0.0, j_r], # top-right [0.0, j_r], # bottom-right [0.0, 0.0], # bottom-left ] ]) jitters = [ _JitterTopWiderThanBottom(), _JitterTopThinnerThanBottom(), _JitterLeftWiderThanRight(), _JitterLeftThinnerThanRight(), ] # expected coordinates after applying the above jitter # coordinates here are given as # (ystart, yend), (xstart, xend) coords = [ # top wider than bottom [ [(0+j, s+j+1), (0, s+1)], # top left [(0+j, s+j+1), (w-s, w+1)], # top right [(h-s-j, h-j+1), (w-s-j, w-j+1)], # bottom right [(h-s-j, h-j+1), (0+j, s+j+1)] # bottom left ], # top thinner than bottom [ [(0+j, s+j+1), (0+j, s+j+1)], [(0+j, s+j+1), (w-s-j, w-j+1)], [(h-s-j, h-j+1), (w-s, w+1)], [(h-s-j, h-j+1), (0, s+1)] ], # left wider than right [ [(0, s+1), (0+j, s+j+1)], [(0+j, s+j+1), (w-s-j, w-j+1)], [(h-s-j, h-j+1), (w-s-j, w-j+1)], [(h-s, h+1), (0+j, s+j+1)] ], # left thinner than right [ [(0+j, s+j+1), (0+j, s+j+1)], [(0, s+1), (w-s-j, w-j+1)], [(h-s, h+1), (w-s-j, w-j+1)], [(h-s-j, h-j+1), (0+j, s+j+1)] ], ] image = np.zeros((h-1, w-1, 4), dtype=np.uint8) image = iaa.pad(image, top=1, right=1, bottom=1, left=1, cval=50) image[0+j:s+j+1, 0+j:s+j+1, 0] = 255 image[0+j:s+j+1, w-s-j:w-j+1, 1] = 255 image[h-s-j:h-j+1, w-s-j:w-j+1, 2] = 255 image[h-s-j:h-j+1, 0+j:s+j+1, 3] = 255 bb = ia.BoundingBox(x1=0.0+j, y1=0.0+j, x2=w-j, y2=h-j) bbsoi = ia.BoundingBoxesOnImage([bb], shape=image.shape) i = 0 for jitter, coords_i in zip(jitters, coords): with self.subTest(jitter=jitter.__class__.__name__): aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) aug.jitter = jitter image_aug, bbsoi_aug = aug(image=image, bounding_boxes=bbsoi) assert image_aug.shape == image.shape (tl_y1, tl_y2), (tl_x1, tl_x2) = coords_i[0] (tr_y1, tr_y2), (tr_x1, tr_x2) = coords_i[1] (br_y1, br_y2), (br_x1, br_x2) = coords_i[2] (bl_y1, bl_y2), (bl_x1, bl_x2) = coords_i[3] # We have to be rather tolerant here (>100 instead of e.g. # >200), because the transformation seems to be not that # accurate and the blobs may be a few pixels off the expected # coorindates. assert np.max(image_aug[tl_y1:tl_y2, tl_x1:tl_x2, 0]) > 100 assert np.max(image_aug[tr_y1:tr_y2, tr_x1:tr_x2, 1]) > 100 assert np.max(image_aug[br_y1:br_y2, br_x1:br_x2, 2]) > 100 assert np.max(image_aug[bl_y1:bl_y2, bl_x1:bl_x2, 3]) > 100 # We have rather strong tolerances of 7.5 here, partially # because the blobs are wide and the true coordinates are in # the center of the blobs; partially, because of above # mentioned inaccuracy of PerspectiveTransform. bb_aug = bbsoi_aug.bounding_boxes[0] exp_x1 = min([tl_x1, tr_x1, br_x1, bl_x1]) exp_x2 = max([tl_x2, tr_x2, br_x2, bl_x2]) exp_y1 = min([tl_y1, tr_y1, br_y1, bl_y1]) exp_y2 = max([tl_y2, tr_y2, br_y2, bl_y2]) assert np.isclose(bb_aug.x1, exp_x1, atol=7.5) assert np.isclose(bb_aug.y1, exp_y1, atol=7.5) assert np.isclose(bb_aug.x2, exp_x2, atol=7.5) assert np.isclose(bb_aug.y2, exp_y2, atol=7.5) def test_empty_bounding_boxes(self): # test empty bounding boxes bbsoi = ia.BoundingBoxesOnImage([], shape=(20, 10, 3)) aug = iaa.PerspectiveTransform(scale=0.2, keep_size=True) observed = aug.augment_bounding_boxes(bbsoi) assert_cbaois_equal(observed, bbsoi) # ------------ # mode # ------------ def test_draw_samples_with_mode_being_int(self): aug = iaa.PerspectiveTransform(scale=0.001, mode=cv2.BORDER_REPLICATE) samples = aug._draw_samples([(10, 10, 3)], iarandom.RNG(0)) assert samples.modes.shape == (1,) assert samples.modes[0] == cv2.BORDER_REPLICATE def test_draw_samples_with_mode_being_string(self): aug = iaa.PerspectiveTransform(scale=0.001, mode="replicate") samples = aug._draw_samples([(10, 10, 3)], iarandom.RNG(0)) assert samples.modes.shape == (1,) assert samples.modes[0] == cv2.BORDER_REPLICATE def test_mode_replicate_copies_values(self): aug = iaa.PerspectiveTransform( scale=0.001, mode="replicate", cval=0, seed=31) img = np.ones((256, 256, 3), dtype=np.uint8) * 255 img_aug = aug.augment_image(img) assert (img_aug == 255).all() def test_mode_constant_uses_cval(self): aug255 = iaa.PerspectiveTransform( scale=0.001, mode="constant", cval=255, seed=31) aug0 = iaa.PerspectiveTransform( scale=0.001, mode="constant", cval=0, seed=31) img = np.ones((256, 256, 3), dtype=np.uint8) * 255 img_aug255 = aug255.augment_image(img) img_aug0 = aug0.augment_image(img) assert (img_aug255 == 255).all() # TODO This was originally "assert not (...)", but since # PerspectiveTransform has become more precise, there are no # filled pixels anymore at the edges. That is because PerspT # currently only zooms in and not out. Filled pixels at the sides # were previously due to a bug. assert (img_aug0 == 255).all() # --------- # fit_output # --------- def test_fit_output_with_fixed_jitter(self): aug = iaa.PerspectiveTransform(scale=0.2, fit_output=True, keep_size=False) aug.jitter = iap.Deterministic(0.2) image = np.zeros((40, 40, 3), dtype=np.uint8) image[0:3, 0:3, 0] = 255 image[0:3, 40-3:, 1] = 255 image[40-3:, 40-3:, 2] = 255 image_aug = aug(image=image) h, w = image_aug.shape[0:2] y0 = np.argmax(image_aug[:, 0, 0]) x0 = np.argmax(image_aug[0, :, 0]) y1 = np.argmax(image_aug[:, w-1, 1]) x1 = np.argmax(image_aug[0, :, 1]) y2 = np.argmax(image_aug[:, w-1, 2]) x2 = np.argmax(image_aug[h-1, :, 2]) # different shape assert image_aug.shape == image.shape # corners roughly still at top-left, top-right, bottom-right assert 0 <= y0 <= 3 assert 0 <= x0 <= 3 assert 0 <= y1 <= 3 assert image_aug.shape[1]-3 <= x1 <= image_aug.shape[1] assert image_aug.shape[1]-3 <= y2 <= image_aug.shape[1] assert image_aug.shape[1]-3 <= x2 <= image_aug.shape[1] # no corner pixels now in the center assert np.max(image_aug[8:h-8, 8:w-8, :]) == 0 def test_fit_output_with_random_jitter(self): aug = iaa.PerspectiveTransform(scale=0.1, fit_output=True, keep_size=False) image = np.zeros((50, 50, 4), dtype=np.uint8) image[0:5, 0:5, 0] = 255 image[0:5, 50-5:, 1] = 255 image[50-5:, 50-5:, 2] = 255 image[50-5:, 0:5, 3] = 255 for _ in sm.xrange(10): image_aug = aug(image=image) h, w = image_aug.shape[0:2] arr_nochan = np.max(image_aug, axis=2) y_idx = np.where(np.max(arr_nochan, axis=1))[0] x_idx = np.where(np.max(arr_nochan, axis=0))[0] y_min = np.min(y_idx) y_max = np.max(y_idx) x_min = np.min(x_idx) x_max = np.max(x_idx) tol = 0 assert 0 <= y_min <= 5+tol assert 0 <= x_min <= 5+tol assert h-5-tol <= y_max <= h-1 assert w-5-tol <= x_max <= w-1 def test_fit_output_with_random_jitter__segmentation_maps(self): aug = iaa.PerspectiveTransform(scale=0.1, fit_output=True, keep_size=False) arr = np.zeros((50, 50, 4), dtype=np.uint8) arr[0:5, 0:5, 0] = 1 arr[0:5, 50-5:, 1] = 1 arr[50-5:, 50-5:, 2] = 1 arr[50-5:, 0:5, 3] = 1 segmap = ia.SegmentationMapsOnImage(arr, shape=(50, 50, 3)) image = np.zeros((49, 49, 3), dtype=np.uint8) image = iaa.pad(image, top=1, right=1, bottom=1, left=1, cval=128) for _ in sm.xrange(10): image_aug, segmap_aug = aug(image=image, segmentation_maps=segmap) h, w = segmap_aug.arr.shape[0:2] arr_nochan = np.max(segmap_aug.arr, axis=2) y_idx = np.where(np.max(arr_nochan, axis=1))[0] x_idx = np.where(np.max(arr_nochan, axis=0))[0] y_min = np.min(y_idx) y_max = np.max(y_idx) x_min = np.min(x_idx) x_max = np.max(x_idx) tol = 0 assert 0 <= y_min <= 5+tol assert 0 <= x_min <= 5+tol assert h-5-tol <= y_max <= h-1 assert w-5-tol <= x_max <= w-1 def test_fit_output_with_fixed_jitter__keypoints(self): aug = iaa.PerspectiveTransform(scale=0.1, fit_output=True, keep_size=False) kpsoi = ia.KeypointsOnImage.from_xy_array([ (0, 0), (50, 0), (50, 50), (0, 50) ], shape=(50, 50, 3)) for i in sm.xrange(10): kpsoi_aug = aug(keypoints=kpsoi) h, w = kpsoi_aug.shape[0:2] y0, x0 = kpsoi_aug.keypoints[0].y, kpsoi_aug.keypoints[0].x y1, x1 = kpsoi_aug.keypoints[1].y, kpsoi_aug.keypoints[1].x y2, x2 = kpsoi_aug.keypoints[2].y, kpsoi_aug.keypoints[2].x y3, x3 = kpsoi_aug.keypoints[3].y, kpsoi_aug.keypoints[3].x y_min = min([y0, y1, y2, y3]) y_max = max([y0, y1, y2, y3]) x_min = min([x0, x1, x2, x3]) x_max = max([x0, x1, x2, x3]) tol = 0.5 assert 0-tol <= y_min <= tol, "Got y_min=%.4f at %d" % (y_min, i) assert 0-tol <= x_min <= tol, "Got x_min=%.4f at %d" % (x_min, i) assert h-tol <= y_max <= h+tol, ( "Got y_max=%.4f for h=%.2f at %d" % (y_max, h, i)) assert w-tol <= x_max <= w+tol, ( "Got x_max=%.4f for w=%.2f at %d" % (x_max, w, i)) # --------- # unusual channel numbers # --------- def test_unusual_channel_numbers(self): shapes = [ (1, 1, 4), (1, 1, 5), (1, 1, 512), (1, 1, 513) ] for shape in shapes: with self.subTest(shape=shape): image = np.zeros(shape, dtype=np.uint8) aug = iaa.PerspectiveTransform(scale=0.01) image_aug = aug(image=image) assert np.all(image_aug == 0) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape # --------- # zero-sized axes # --------- 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: for keep_size in [False, True]: with self.subTest(shape=shape, keep_size=keep_size): for _ in sm.xrange(3): image = np.zeros(shape, dtype=np.uint8) aug = iaa.PerspectiveTransform(scale=0.01) image_aug = aug(image=image) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape # -------- # get_parameters # -------- def test_get_parameters(self): aug = iaa.PerspectiveTransform(scale=0.1, keep_size=False) params = aug.get_parameters() assert is_parameter_instance(params[0], iap.Normal) assert is_parameter_instance(params[0].scale, iap.Deterministic) assert 0.1 - 1e-8 < params[0].scale.value < 0.1 + 1e-8 assert params[1] is False assert params[2].value == 0 assert params[3].value == "constant" assert params[4] is False # -------- # other dtypes # -------- def test_other_dtypes_bool(self): aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) y1 = int(30 * 0.2) y2 = int(30 * 0.8) x1 = int(30 * 0.2) x2 = int(30 * 0.8) image = np.zeros((30, 30), dtype=bool) image[12:18, :] = True image[:, 12:18] = True expected = image[y1:y2, x1:x2] image_aug = aug.augment_image(image) assert image_aug.dtype.name == image.dtype.name assert image_aug.shape == expected.shape assert (np.sum(image_aug == expected) / expected.size) > 0.9 def test_other_dtypes_uint_int(self): aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) y1 = int(30 * 0.2) y2 = int(30 * 0.8) x1 = int(30 * 0.2) x2 = int(30 * 0.8) dtypes = ["uint8", "uint16", "int8", "int16"] for dtype in dtypes: min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) if np.dtype(dtype).kind == "i": values = [0, 1, 5, 10, 100, int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value-100, max_value] values = values + [(-1)*value for value in values] else: values = [0, 1, 5, 10, 100, int(center_value), int(0.1 * max_value), int(0.2 * max_value), int(0.5 * max_value), max_value-100, max_value] for value in values: with self.subTest(dtype=dtype, value=value): image = np.zeros((30, 30), dtype=dtype) image[12:18, :] = value image[:, 12:18] = value expected = image[y1:y2, x1:x2] image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert image_aug.shape == expected.shape # rather high tolerance of 0.7 here because of # interpolation assert ( np.sum(image_aug == expected) / expected.size ) > 0.7 def test_other_dtypes_float(self): aug = iaa.PerspectiveTransform(scale=0.2, keep_size=False) aug.jitter = iap.Deterministic(0.2) y1 = int(30 * 0.2) y2 = int(30 * 0.8) x1 = int(30 * 0.2) x2 = int(30 * 0.8) dtypes = ["float16", "float32", "float64"] for dtype in dtypes: def _isclose(a, b): atol = 1e-4 if dtype == "float16" else 1e-8 return np.isclose(a, b, atol=atol, rtol=0) isize = np.dtype(dtype).itemsize values = [0.01, 1.0, 10.0, 100.0, 500 ** (isize - 1), 1000 ** (isize - 1)] values = values + [(-1) * value for value in values] for value in values: with self.subTest(dtype=dtype, value=value): image = np.zeros((30, 30), dtype=dtype) image[12:18, :] = value image[:, 12:18] = value expected = image[y1:y2, x1:x2] image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert image_aug.shape == expected.shape # rather high tolerance of 0.7 here because of # interpolation assert ( np.sum(_isclose(image_aug, expected)) / expected.size ) > 0.7 def test_pickleable(self): aug = iaa.PerspectiveTransform(0.2, seed=1) runtest_pickleable_uint8_img(aug, iterations=4, shape=(25, 25, 1)) class _elastic_trans_temp_thresholds(object): def __init__(self, alpha, sigma): self.alpha = alpha self.sigma = sigma self.old_alpha = None self.old_sigma = None def __enter__(self): self.old_alpha = iaa.ElasticTransformation.KEYPOINT_AUG_ALPHA_THRESH self.old_sigma = iaa.ElasticTransformation.KEYPOINT_AUG_SIGMA_THRESH iaa.ElasticTransformation.KEYPOINT_AUG_ALPHA_THRESH = self.alpha iaa.ElasticTransformation.KEYPOINT_AUG_SIGMA_THRESH = self.sigma def __exit__(self, exc_type, exc_val, exc_tb): iaa.ElasticTransformation.KEYPOINT_AUG_ALPHA_THRESH = self.old_alpha iaa.ElasticTransformation.KEYPOINT_AUG_SIGMA_THRESH = self.old_sigma # TODO add tests for order # TODO improve tests for cval # TODO add tests for mode class TestElasticTransformation(unittest.TestCase): def setUp(self): reseed() @property def image(self): img = np.zeros((50, 50), dtype=np.uint8) + 255 img = np.pad(img, ((100, 100), (100, 100)), mode="constant", constant_values=0) return img @property def mask(self): img = self.image mask = img > 0 return mask @property def heatmaps(self): img = self.image return HeatmapsOnImage(img.astype(np.float32) / 255.0, shape=img.shape) @property def segmaps(self): img = self.image return SegmentationMapsOnImage((img > 0).astype(np.int32), shape=img.shape) # ----------- # __init__ # ----------- def test___init___bad_datatype_for_alpha_leads_to_failure(self): # test alpha having bad datatype got_exception = False try: _ = iaa.ElasticTransformation(alpha=False, sigma=0.25) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___alpha_is_tuple(self): # test alpha being tuple aug = iaa.ElasticTransformation(alpha=(1.0, 2.0), sigma=0.25) assert is_parameter_instance(aug.alpha, iap.Uniform) assert is_parameter_instance(aug.alpha.a, iap.Deterministic) assert is_parameter_instance(aug.alpha.b, iap.Deterministic) assert 1.0 - 1e-8 < aug.alpha.a.value < 1.0 + 1e-8 assert 2.0 - 1e-8 < aug.alpha.b.value < 2.0 + 1e-8 def test___init___sigma_is_tuple(self): # test sigma being tuple aug = iaa.ElasticTransformation(alpha=0.25, sigma=(1.0, 2.0)) assert is_parameter_instance(aug.sigma, iap.Uniform) assert is_parameter_instance(aug.sigma.a, iap.Deterministic) assert is_parameter_instance(aug.sigma.b, iap.Deterministic) assert 1.0 - 1e-8 < aug.sigma.a.value < 1.0 + 1e-8 assert 2.0 - 1e-8 < aug.sigma.b.value < 2.0 + 1e-8 def test___init___bad_datatype_for_sigma_leads_to_failure(self): # test sigma having bad datatype got_exception = False try: _ = iaa.ElasticTransformation(alpha=0.25, sigma=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___order_is_all(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, order=ia.ALL) assert is_parameter_instance(aug.order, iap.Choice) assert all([order in aug.order.a for order in [0, 1, 2, 3, 4, 5]]) def test___init___order_is_int(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, order=1) assert is_parameter_instance(aug.order, iap.Deterministic) assert aug.order.value == 1 def test___init___order_is_list(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, order=[0, 1, 2]) assert is_parameter_instance(aug.order, iap.Choice) assert all([order in aug.order.a for order in [0, 1, 2]]) def test___init___order_is_stochastic_parameter(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, order=iap.Choice([0, 1, 2, 3])) assert is_parameter_instance(aug.order, iap.Choice) assert all([order in aug.order.a for order in [0, 1, 2, 3]]) def test___init___bad_datatype_for_order_leads_to_failure(self): got_exception = False try: _ = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, order=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___cval_is_all(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, cval=ia.ALL) assert is_parameter_instance(aug.cval, iap.Uniform) assert is_parameter_instance(aug.cval.a, iap.Deterministic) assert is_parameter_instance(aug.cval.b, iap.Deterministic) assert aug.cval.a.value == 0 assert aug.cval.b.value == 255 def test___init___cval_is_int(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, cval=128) assert is_parameter_instance(aug.cval, iap.Deterministic) assert aug.cval.value == 128 def test___init___cval_is_list(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, cval=[16, 32, 64]) assert is_parameter_instance(aug.cval, iap.Choice) assert all([cval in aug.cval.a for cval in [16, 32, 64]]) def test___init___cval_is_stochastic_parameter(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, cval=iap.Choice([16, 32, 64])) assert is_parameter_instance(aug.cval, iap.Choice) assert all([cval in aug.cval.a for cval in [16, 32, 64]]) def test___init___cval_is_tuple(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, cval=(128, 255)) assert is_parameter_instance(aug.cval, iap.Uniform) assert is_parameter_instance(aug.cval.a, iap.Deterministic) assert is_parameter_instance(aug.cval.b, iap.Deterministic) assert aug.cval.a.value == 128 assert aug.cval.b.value == 255 def test___init___bad_datatype_for_cval_leads_to_failure(self): got_exception = False try: _ = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, cval=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception def test___init___mode_is_all(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, mode=ia.ALL) assert is_parameter_instance(aug.mode, iap.Choice) assert all([ mode in aug.mode.a for mode in ["constant", "nearest", "reflect", "wrap"]]) def test___init___mode_is_string(self): aug = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, mode="nearest") assert is_parameter_instance(aug.mode, iap.Deterministic) assert aug.mode.value == "nearest" def test___init___mode_is_list(self): aug = iaa.ElasticTransformation( alpha=0.25, sigma=1.0, mode=["constant", "nearest"]) assert is_parameter_instance(aug.mode, iap.Choice) assert all([mode in aug.mode.a for mode in ["constant", "nearest"]]) def test___init___mode_is_stochastic_parameter(self): aug = iaa.ElasticTransformation( alpha=0.25, sigma=1.0, mode=iap.Choice(["constant", "nearest"])) assert is_parameter_instance(aug.mode, iap.Choice) assert all([mode in aug.mode.a for mode in ["constant", "nearest"]]) def test___init___bad_datatype_for_mode_leads_to_failure(self): got_exception = False try: _ = iaa.ElasticTransformation(alpha=0.25, sigma=1.0, mode=False) except Exception as exc: assert "Expected " in str(exc) got_exception = True assert got_exception # ----------- # alpha, sigma # ----------- def test_images(self): # test basic funtionality aug = iaa.ElasticTransformation(alpha=5, sigma=0.25) observed = aug.augment_image(self.image) mask = self.mask # assume that some white/255 pixels have been moved away from the # center and replaced by black/0 pixels assert np.sum(observed[mask]) < np.sum(self.image[mask]) # assume that some black/0 pixels have been moved away from the outer # area and replaced by white/255 pixels assert np.sum(observed[~mask]) > np.sum(self.image[~mask]) def test_images_nonsquare(self): # test basic funtionality with non-square images aug = iaa.ElasticTransformation(alpha=2.0, sigma=0.25, order=3) img_nonsquare = np.zeros((50, 100), dtype=np.uint8) + 255 img_nonsquare = np.pad(img_nonsquare, ((100, 100), (100, 100)), mode="constant", constant_values=0) mask_nonsquare = (img_nonsquare > 0) observed = aug.augment_image(img_nonsquare) assert ( np.sum(observed[mask_nonsquare]) < np.sum(img_nonsquare[mask_nonsquare])) assert ( np.sum(observed[~mask_nonsquare]) > np.sum(img_nonsquare[~mask_nonsquare])) def test_images_unusual_channel_numbers(self): # test unusual channels numbers aug = iaa.ElasticTransformation(alpha=5, sigma=0.5) for nb_channels in [1, 2, 4, 5, 7, 10, 11]: img_c = np.tile(self.image[..., np.newaxis], (1, 1, nb_channels)) assert img_c.shape == (250, 250, nb_channels) observed = aug.augment_image(img_c) assert observed.shape == (250, 250, nb_channels) for c in sm.xrange(1, nb_channels): assert np.array_equal(observed[..., c], observed[..., 0]) def test_heatmaps(self): # test basic funtionality, heatmaps aug = iaa.ElasticTransformation(alpha=0.5, sigma=0.25) observed = aug.augment_heatmaps([self.heatmaps])[0] mask = self.mask assert observed.shape == self.heatmaps.shape _assert_same_min_max(observed, self.heatmaps) assert ( np.sum(observed.get_arr()[mask]) < np.sum(self.heatmaps.get_arr()[mask])) assert ( np.sum(observed.get_arr()[~mask]) > np.sum(self.heatmaps.get_arr()[~mask])) def test_segmaps(self): # test basic funtionality, segmaps # alpha=1.5 instead of 0.5 as above here, because otherwise nothing # is moved aug = iaa.ElasticTransformation(alpha=1.5, sigma=0.25) observed = aug.augment_segmentation_maps([self.segmaps])[0] mask = self.mask assert observed.shape == self.segmaps.shape assert ( np.sum(observed.get_arr()[mask]) < np.sum(self.segmaps.get_arr()[mask])) assert ( np.sum(observed.get_arr()[~mask]) > np.sum(self.segmaps.get_arr()[~mask])) def test_images_weak_vs_strong_alpha(self): # test effects of increased alpha strength aug1 = iaa.ElasticTransformation(alpha=0.1, sigma=0.25) aug2 = iaa.ElasticTransformation(alpha=5.0, sigma=0.25) observed1 = aug1.augment_image(self.image) observed2 = aug2.augment_image(self.image) mask = self.mask # assume that the inner area has become more black-ish when using high # alphas (more white pixels were moved out of the inner area) assert np.sum(observed1[mask]) > np.sum(observed2[mask]) # assume that the outer area has become more white-ish when using high # alphas (more black pixels were moved into the inner area) assert np.sum(observed1[~mask]) < np.sum(observed2[~mask]) def test_heatmaps_weak_vs_strong_alpha(self): # test effects of increased alpha strength, heatmaps aug1 = iaa.ElasticTransformation(alpha=0.1, sigma=0.25) aug2 = iaa.ElasticTransformation(alpha=5.0, sigma=0.25) observed1 = aug1.augment_heatmaps([self.heatmaps])[0] observed2 = aug2.augment_heatmaps([self.heatmaps])[0] mask = self.mask assert observed1.shape == self.heatmaps.shape assert observed2.shape == self.heatmaps.shape _assert_same_min_max(observed1, self.heatmaps) _assert_same_min_max(observed2, self.heatmaps) assert ( np.sum(observed1.get_arr()[mask]) > np.sum(observed2.get_arr()[mask])) assert ( np.sum(observed1.get_arr()[~mask]) < np.sum(observed2.get_arr()[~mask])) def test_segmaps_weak_vs_strong_alpha(self): # test effects of increased alpha strength, segmaps aug1 = iaa.ElasticTransformation(alpha=0.1, sigma=0.25) aug2 = iaa.ElasticTransformation(alpha=5.0, sigma=0.25) observed1 = aug1.augment_segmentation_maps([self.segmaps])[0] observed2 = aug2.augment_segmentation_maps([self.segmaps])[0] mask = self.mask assert observed1.shape == self.segmaps.shape assert observed2.shape == self.segmaps.shape assert ( np.sum(observed1.get_arr()[mask]) > np.sum(observed2.get_arr()[mask])) assert ( np.sum(observed1.get_arr()[~mask]) < np.sum(observed2.get_arr()[~mask])) def test_images_low_vs_high_sigma(self): # test effects of increased sigmas aug1 = iaa.ElasticTransformation(alpha=3.0, sigma=0.1) aug2 = iaa.ElasticTransformation(alpha=3.0, sigma=3.0) observed1 = aug1.augment_image(self.image) observed2 = aug2.augment_image(self.image) observed1_std_hori = np.std( observed1.astype(np.float32)[:, 1:] - observed1.astype(np.float32)[:, :-1]) observed2_std_hori = np.std( observed2.astype(np.float32)[:, 1:] - observed2.astype(np.float32)[:, :-1]) observed1_std_vert = np.std( observed1.astype(np.float32)[1:, :] - observed1.astype(np.float32)[:-1, :]) observed2_std_vert = np.std( observed2.astype(np.float32)[1:, :] - observed2.astype(np.float32)[:-1, :]) observed1_std = (observed1_std_hori + observed1_std_vert) / 2 observed2_std = (observed2_std_hori + observed2_std_vert) / 2 assert observed1_std > observed2_std def test_images_alpha_is_stochastic_parameter(self): # test alpha being iap.Choice aug = iaa.ElasticTransformation(alpha=iap.Choice([0.001, 5.0]), sigma=0.25) seen = [0, 0] for _ in sm.xrange(100): observed = aug.augment_image(self.image) diff = np.average( np.abs( self.image.astype(np.float32) - observed.astype(np.float32) ) ) if diff < 1.0: seen[0] += 1 else: seen[1] += 1 assert seen[0] > 10 assert seen[1] > 10 def test_sigma_is_stochastic_parameter(self): # test sigma being iap.Choice for order in [0, 1, 3]: with self.subTest(order=order): aug = iaa.ElasticTransformation(alpha=50.0, sigma=iap.Choice([0.001, 5.0]), order=order) seen = [0, 0] for _ in sm.xrange(100): observed = aug.augment_image(self.image) observed_std_hori = np.std( observed.astype(np.float32)[:, 1:] - observed.astype(np.float32)[:, :-1]) observed_std_vert = np.std( observed.astype(np.float32)[1:, :] - observed.astype(np.float32)[:-1, :]) observed_std = (observed_std_hori + observed_std_vert) / 2 if observed_std > 25.0: seen[0] += 1 else: seen[1] += 1 assert seen[0] > 10 assert seen[1] > 10 # ----------- # cval # ----------- def test_images_cval_is_int_and_order_is_0(self): aug = iaa.ElasticTransformation(alpha=30.0, sigma=3.0, mode="constant", cval=255, order=0) img = np.zeros((100, 100), dtype=np.uint8) observed = aug.augment_image(img) assert np.sum(observed == 255) > 0 assert np.sum(np.logical_and(0 < observed, observed < 255)) == 0 def test_images_cval_is_int_and_order_is_0_weak_alpha(self): aug = iaa.ElasticTransformation(alpha=3.0, sigma=3.0, mode="constant", cval=0, order=0) img = np.zeros((100, 100), dtype=np.uint8) observed = aug.augment_image(img) assert np.sum(observed == 255) == 0 def test_images_cval_is_int_and_order_is_2(self): aug = iaa.ElasticTransformation(alpha=3.0, sigma=3.0, mode="constant", cval=255, order=2) img = np.zeros((100, 100), dtype=np.uint8) observed = aug.augment_image(img) assert np.sum(np.logical_and(0 < observed, observed < 255)) > 0 def test_images_cval_is_int_image_hw3(self): aug = iaa.ElasticTransformation(alpha=5.0, sigma=3.0, mode="constant", cval=255, order=0) img = np.zeros((100, 100, 3), dtype=np.uint8) observed = aug.augment_image(img) count_255 = np.sum(observed == 255, axis=2) mask_not_all_channels_same_intensity = np.logical_and( count_255 > 0, count_255 < 3) mask_all_channels_same_intensity = (count_255 == 3) assert not np.any(mask_not_all_channels_same_intensity) assert np.any(mask_all_channels_same_intensity) def test_heatmaps_ignore_cval(self): # cval with heatmaps heatmaps = HeatmapsOnImage( np.zeros((32, 32, 1), dtype=np.float32), shape=(32, 32, 3)) aug = iaa.ElasticTransformation(alpha=3.0, sigma=3.0, mode="constant", cval=255) observed = aug.augment_heatmaps([heatmaps])[0] assert observed.shape == heatmaps.shape _assert_same_min_max(observed, heatmaps) assert np.sum(observed.get_arr() > 0.01) == 0 def test_segmaps_ignore_cval(self): # cval with segmaps segmaps = SegmentationMapsOnImage( np.zeros((32, 32, 1), dtype=np.int32), shape=(32, 32, 3)) aug = iaa.ElasticTransformation(alpha=3.0, sigma=3.0, mode="constant", cval=255) observed = aug.augment_segmentation_maps([segmaps])[0] assert observed.shape == segmaps.shape assert np.sum(observed.get_arr() > 0) == 0 # ----------- # keypoints # ----------- def test_keypoints_no_movement_if_alpha_below_threshold(self): # for small alpha, should not move if below threshold with _elastic_trans_temp_thresholds(alpha=1.0, sigma=0.0): kps = [ ia.Keypoint(x=1, y=1), ia.Keypoint(x=15, y=25), ia.Keypoint(x=5, y=5), ia.Keypoint(x=7, y=4), ia.Keypoint(x=48, y=5), ia.Keypoint(x=21, y=37), ia.Keypoint(x=32, y=39), ia.Keypoint(x=6, y=8), ia.Keypoint(x=12, y=21), ia.Keypoint(x=3, y=45), ia.Keypoint(x=45, y=3), ia.Keypoint(x=7, y=48)] kpsoi = ia.KeypointsOnImage(kps, shape=(50, 50)) aug = iaa.ElasticTransformation(alpha=0.001, sigma=1.0) observed = aug.augment_keypoints([kpsoi])[0] d = kpsoi.to_xy_array() - observed.to_xy_array() d[:, 0] = d[:, 0] ** 2 d[:, 1] = d[:, 1] ** 2 d = np.sum(d, axis=1) d = np.average(d, axis=0) assert d < 1e-8 def test_keypoints_no_movement_if_sigma_below_threshold(self): # for small sigma, should not move if below threshold with _elastic_trans_temp_thresholds(alpha=0.0, sigma=1.0): kps = [ ia.Keypoint(x=1, y=1), ia.Keypoint(x=15, y=25), ia.Keypoint(x=5, y=5), ia.Keypoint(x=7, y=4), ia.Keypoint(x=48, y=5), ia.Keypoint(x=21, y=37), ia.Keypoint(x=32, y=39), ia.Keypoint(x=6, y=8), ia.Keypoint(x=12, y=21), ia.Keypoint(x=3, y=45), ia.Keypoint(x=45, y=3), ia.Keypoint(x=7, y=48)] kpsoi = ia.KeypointsOnImage(kps, shape=(50, 50)) aug = iaa.ElasticTransformation(alpha=1.0, sigma=0.001) observed = aug.augment_keypoints([kpsoi])[0] d = kpsoi.to_xy_array() - observed.to_xy_array() d[:, 0] = d[:, 0] ** 2 d[:, 1] = d[:, 1] ** 2 d = np.sum(d, axis=1) d = np.average(d, axis=0) assert d < 1e-8 def test_keypoints_small_movement_for_weak_alpha_if_threshold_zero(self): # for small alpha (at sigma 1.0), should barely move # if thresholds set to zero with _elastic_trans_temp_thresholds(alpha=0.0, sigma=0.0): kps = [ ia.Keypoint(x=1, y=1), ia.Keypoint(x=15, y=25), ia.Keypoint(x=5, y=5), ia.Keypoint(x=7, y=4), ia.Keypoint(x=48, y=5), ia.Keypoint(x=21, y=37), ia.Keypoint(x=32, y=39), ia.Keypoint(x=6, y=8), ia.Keypoint(x=12, y=21), ia.Keypoint(x=3, y=45), ia.Keypoint(x=45, y=3), ia.Keypoint(x=7, y=48)] kpsoi = ia.KeypointsOnImage(kps, shape=(50, 50)) aug = iaa.ElasticTransformation(alpha=0.001, sigma=1.0) observed = aug.augment_keypoints([kpsoi])[0] d = kpsoi.to_xy_array() - observed.to_xy_array() d[:, 0] = d[:, 0] ** 2 d[:, 1] = d[:, 1] ** 2 d = np.sum(d, axis=1) d = np.average(d, axis=0) assert d < 0.5 def test_image_keypoint_alignment(self): # test alignment between between images and keypoints image = np.zeros((120, 70), dtype=np.uint8) s = 3 image[:, 35-s:35+s+1] = 255 kps = [ia.Keypoint(x=35, y=20), ia.Keypoint(x=35, y=40), ia.Keypoint(x=35, y=60), ia.Keypoint(x=35, y=80), ia.Keypoint(x=35, y=100)] kpsoi = ia.KeypointsOnImage(kps, shape=image.shape) aug = iaa.ElasticTransformation(alpha=70, sigma=5) aug_det = aug.to_deterministic() images_aug = aug_det.augment_images([image, image]) kpsois_aug = aug_det.augment_keypoints([kpsoi, kpsoi]) count_bad = 0 for image_aug, kpsoi_aug in zip(images_aug, kpsois_aug): assert kpsoi_aug.shape == (120, 70) assert len(kpsoi_aug.keypoints) == 5 for kp_aug in kpsoi_aug.keypoints: x, y = int(np.round(kp_aug.x)), int(np.round(kp_aug.y)) bb = ia.BoundingBox(x1=x-2, x2=x+2+1, y1=y-2, y2=y+2+1) img_ex = bb.extract_from_image(image_aug) if np.any(img_ex > 10): pass # close to expected location else: count_bad += 1 assert count_bad <= 1 def test_empty_keypoints(self): aug = iaa.ElasticTransformation(alpha=10, sigma=10) kpsoi = ia.KeypointsOnImage([], shape=(10, 10, 3)) kpsoi_aug = aug.augment_keypoints(kpsoi) assert len(kpsoi_aug.keypoints) == 0 assert kpsoi_aug.shape == (10, 10, 3) # ----------- # abstract methods for polygons and line strings # ----------- @classmethod def _test_cbaois_no_movement_if_alpha_below_threshold( cls, cba_class, cbaoi_class, augf_name): # for small alpha, should not move if below threshold with _elastic_trans_temp_thresholds(alpha=1.0, sigma=0.0): cba = cba_class([(10, 15), (40, 15), (40, 35), (10, 35)]) cbaoi = cbaoi_class([cba], shape=(50, 50)) aug = iaa.ElasticTransformation(alpha=0.001, sigma=1.0) observed = getattr(aug, augf_name)(cbaoi) assert observed.shape == (50, 50) assert len(observed.items) == 1 assert observed.items[0].coords_almost_equals(cba) if hasattr(observed.items[0], "is_valid"): assert observed.items[0].is_valid @classmethod def _test_cbaois_no_movement_if_sigma_below_threshold( cls, cba_class, cbaoi_class, augf_name): # for small sigma, should not move if below threshold with _elastic_trans_temp_thresholds(alpha=0.0, sigma=1.0): cba = cba_class([(10, 15), (40, 15), (40, 35), (10, 35)]) cbaoi = cbaoi_class([cba], shape=(50, 50)) aug = iaa.ElasticTransformation(alpha=1.0, sigma=0.001) observed = getattr(aug, augf_name)(cbaoi) assert observed.shape == (50, 50) assert len(observed.items) == 1 assert observed.items[0].coords_almost_equals(cba) if hasattr(observed.items[0], "is_valid"): assert observed.items[0].is_valid @classmethod def _test_cbaois_small_movement_for_weak_alpha_if_threshold_zero( cls, cba_class, cbaoi_class, augf_name): # for small alpha (at sigma 1.0), should barely move # if thresholds set to zero with _elastic_trans_temp_thresholds(alpha=0.0, sigma=0.0): cba = cba_class([(10, 15), (40, 15), (40, 35), (10, 35)]) cbaoi = cbaoi_class([cba], shape=(50, 50)) aug = iaa.ElasticTransformation(alpha=0.001, sigma=1.0) observed = getattr(aug, augf_name)(cbaoi) assert observed.shape == (50, 50) assert len(observed.items) == 1 assert observed.items[0].coords_almost_equals( cba, max_distance=0.5) if hasattr(observed.items[0], "is_valid"): assert observed.items[0].is_valid @classmethod def _test_image_cbaoi_alignment(cls, cba_class, cbaoi_class, augf_name): # test alignment between between images and polygons height_step_size = 50 width_step_size = 30 height_steps = 2 # don't set >2, otherwise polygon will be broken width_steps = 10 height = (2+height_steps) * height_step_size width = (2+width_steps) * width_step_size s = 3 image = np.zeros((height, width), dtype=np.uint8) points = [] for w in sm.xrange(0, 2+width_steps): if w not in [0, width_steps+2-1]: x = width_step_size * w y = height_step_size points.append((x, y)) image[y-s:y+s+1, x-s:x+s+1] = 255 for w in sm.xrange(2+width_steps-1, 0, -1): if w not in [0, width_steps+2-1]: x = width_step_size * w y = height_step_size*2 points.append((x, y)) image[y-s:y+s+1, x-s:x+s+1] = 255 cba = cba_class(points) cbaoi = cbaoi_class([cba], shape=image.shape) aug = iaa.ElasticTransformation(alpha=100, sigma=7) aug_det = aug.to_deterministic() images_aug = aug_det.augment_images([image, image]) cbaois_aug = getattr(aug_det, augf_name)([cbaoi, cbaoi]) count_bad = 0 for image_aug, cbaoi_aug in zip(images_aug, cbaois_aug): assert cbaoi_aug.shape == image.shape assert len(cbaoi_aug.items) == 1 for cba_aug in cbaoi_aug.items: if hasattr(cba_aug, "is_valid"): assert cba_aug.is_valid for point_aug in cba_aug.coords: x, y = point_aug[0], point_aug[1] bb = ia.BoundingBox(x1=x-2, x2=x+2, y1=y-2, y2=y+2) img_ex = bb.extract_from_image(image_aug) if np.any(img_ex > 10): pass # close to expected location else: count_bad += 1 assert count_bad <= 3 @classmethod def _test_empty_cbaois(cls, cbaoi, augf_name): aug = iaa.ElasticTransformation(alpha=10, sigma=10) cbaoi_aug = getattr(aug, augf_name)(cbaoi) assert_cbaois_equal(cbaoi_aug, cbaoi) # ----------- # polygons # ----------- def test_polygons_no_movement_if_alpha_below_threshold(self): self._test_cbaois_no_movement_if_alpha_below_threshold( ia.Polygon, ia.PolygonsOnImage, "augment_polygons") def test_polygons_no_movement_if_sigma_below_threshold(self): self._test_cbaois_no_movement_if_sigma_below_threshold( ia.Polygon, ia.PolygonsOnImage, "augment_polygons") def test_polygons_small_movement_for_weak_alpha_if_threshold_zero(self): self._test_cbaois_small_movement_for_weak_alpha_if_threshold_zero( ia.Polygon, ia.PolygonsOnImage, "augment_polygons") def test_image_polygon_alignment(self): self._test_image_cbaoi_alignment( ia.Polygon, ia.PolygonsOnImage, "augment_polygons") def test_empty_polygons(self): cbaoi = ia.PolygonsOnImage([], shape=(10, 10, 3)) self._test_empty_cbaois(cbaoi, "augment_polygons") # ----------- # line strings # ----------- def test_line_strings_no_movement_if_alpha_below_threshold(self): self._test_cbaois_no_movement_if_alpha_below_threshold( ia.LineString, ia.LineStringsOnImage, "augment_line_strings") def test_line_strings_no_movement_if_sigma_below_threshold(self): self._test_cbaois_no_movement_if_sigma_below_threshold( ia.LineString, ia.LineStringsOnImage, "augment_line_strings") def test_line_strings_small_movement_for_weak_alpha_if_threshold_zero(self): self._test_cbaois_small_movement_for_weak_alpha_if_threshold_zero( ia.LineString, ia.LineStringsOnImage, "augment_line_strings") def test_image_line_string_alignment(self): self._test_image_cbaoi_alignment( ia.LineString, ia.LineStringsOnImage, "augment_line_strings") def test_empty_line_strings(self): cbaoi = ia.LineStringsOnImage([], shape=(10, 10, 3)) self._test_empty_cbaois(cbaoi, "augment_line_strings") # ----------- # bounding boxes # ----------- def test_bounding_boxes_no_movement_if_alpha_below_threshold(self): # for small alpha, should not move if below threshold with _elastic_trans_temp_thresholds(alpha=1.0, sigma=0.0): bbs = [ ia.BoundingBox(x1=10, y1=12, x2=20, y2=22), ia.BoundingBox(x1=20, y1=32, x2=40, y2=42) ] bbsoi = ia.BoundingBoxesOnImage(bbs, shape=(50, 50)) aug = iaa.ElasticTransformation(alpha=0.001, sigma=1.0) observed = aug.augment_bounding_boxes([bbsoi])[0] d = bbsoi.to_xyxy_array() - observed.to_xyxy_array() d = d.reshape((2*2, 2)) d[:, 0] = d[:, 0] ** 2 d[:, 1] = d[:, 1] ** 2 d = np.sum(d, axis=1) d = np.average(d, axis=0) assert d < 1e-8 def test_bounding_boxes_no_movement_if_sigma_below_threshold(self): # for small sigma, should not move if below threshold with _elastic_trans_temp_thresholds(alpha=0.0, sigma=1.0): bbs = [ ia.BoundingBox(x1=10, y1=12, x2=20, y2=22), ia.BoundingBox(x1=20, y1=32, x2=40, y2=42) ] bbsoi = ia.BoundingBoxesOnImage(bbs, shape=(50, 50)) aug = iaa.ElasticTransformation(alpha=1.0, sigma=0.001) observed = aug.augment_bounding_boxes([bbsoi])[0] d = bbsoi.to_xyxy_array() - observed.to_xyxy_array() d = d.reshape((2*2, 2)) d[:, 0] = d[:, 0] ** 2 d[:, 1] = d[:, 1] ** 2 d = np.sum(d, axis=1) d = np.average(d, axis=0) assert d < 1e-8 def test_bounding_boxes_small_movement_for_weak_alpha_if_threshold_zero( self): # for small alpha (at sigma 1.0), should barely move # if thresholds set to zero with _elastic_trans_temp_thresholds(alpha=0.0, sigma=0.0): bbs = [ ia.BoundingBox(x1=10, y1=12, x2=20, y2=22), ia.BoundingBox(x1=20, y1=32, x2=40, y2=42) ] bbsoi = ia.BoundingBoxesOnImage(bbs, shape=(50, 50)) aug = iaa.ElasticTransformation(alpha=0.001, sigma=1.0) observed = aug.augment_bounding_boxes([bbsoi])[0] d = bbsoi.to_xyxy_array() - observed.to_xyxy_array() d = d.reshape((2*2, 2)) d[:, 0] = d[:, 0] ** 2 d[:, 1] = d[:, 1] ** 2 d = np.sum(d, axis=1) d = np.average(d, axis=0) assert d < 0.5 def test_image_bounding_box_alignment(self): # test alignment between between images and bounding boxes image = np.zeros((100, 100), dtype=np.uint8) image[35:35+1, 35:65+1] = 255 image[65:65+1, 35:65+1] = 255 image[35:65+1, 35:35+1] = 255 image[35:65+1, 65:65+1] = 255 bbs = [ ia.BoundingBox(x1=35.5, y1=35.5, x2=65.5, y2=65.5) ] bbsoi = ia.BoundingBoxesOnImage(bbs, shape=image.shape) aug = iaa.ElasticTransformation(alpha=70, sigma=5) images_aug, bbsois_aug = aug(images=[image, image], bounding_boxes=[bbsoi, bbsoi]) count_bad = 0 for image_aug, bbsoi_aug in zip(images_aug, bbsois_aug): assert bbsoi_aug.shape == (100, 100) assert len(bbsoi_aug.bounding_boxes) == 1 for bb_aug in bbsoi_aug.bounding_boxes: if bb_aug.is_fully_within_image(image_aug): # top, bottom, left, right x1 = bb_aug.x1_int x2 = bb_aug.x2_int y1 = bb_aug.y1_int y2 = bb_aug.y2_int top_row = image_aug[y1-2:y1+2, x1-2:x2+2] btm_row = image_aug[y2-2:y2+2, x1-2:x2+2] lft_row = image_aug[y1-2:y2+2, x1-2:x1+2] rgt_row = image_aug[y1-2:y2+2, x2-2:x2+2] assert np.max(top_row) > 10 assert np.max(btm_row) > 10 assert np.max(lft_row) > 10 assert np.max(rgt_row) > 10 else: count_bad += 1 assert count_bad <= 1 def test_empty_bounding_boxes(self): aug = iaa.ElasticTransformation(alpha=10, sigma=10) bbsoi = ia.BoundingBoxesOnImage([], shape=(10, 10, 3)) bbsoi_aug = aug.augment_bounding_boxes(bbsoi) assert len(bbsoi_aug.bounding_boxes) == 0 assert bbsoi_aug.shape == (10, 10, 3) # ----------- # heatmaps alignment # ----------- def test_image_heatmaps_alignment(self): # test alignment between images and heatmaps for order in [0, 1, 3]: with self.subTest(order=order): img = np.zeros((80, 80), dtype=np.uint8) img[:, 30:50] = 255 img[30:50, :] = 255 hm = HeatmapsOnImage(img.astype(np.float32)/255.0, shape=(80, 80)) aug = iaa.ElasticTransformation( alpha=60.0, sigma=4.0, mode="constant", cval=0, order=order ) aug_det = aug.to_deterministic() img_aug = aug_det.augment_image(img) hm_aug = aug_det.augment_heatmaps([hm])[0] img_aug_mask = img_aug > 255*0.1 hm_aug_mask = hm_aug.arr_0to1 > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert hm_aug.shape == (80, 80) assert hm_aug.arr_0to1.shape == (80, 80, 1) assert (same / img_aug_mask.size) >= 0.97 def test_image_heatmaps_alignment_if_heatmaps_smaller_than_image(self): # test alignment between images and heatmaps # here with heatmaps that are smaller than the image for order in [0, 1, 3]: with self.subTest(order=order): img = np.zeros((80, 80), dtype=np.uint8) img[:, 30:50] = 255 img[30:50, :] = 255 img_small = ia.imresize_single_image( img, (40, 40), interpolation="nearest") hm = HeatmapsOnImage( img_small.astype(np.float32)/255.0, shape=(80, 80)) aug = iaa.ElasticTransformation( alpha=60.0, sigma=4.0, mode="constant", cval=0) aug_det = aug.to_deterministic() img_aug = aug_det.augment_image(img) hm_aug = aug_det.augment_heatmaps([hm])[0] img_aug_mask = img_aug > 255*0.1 hm_aug_mask = ia.imresize_single_image( hm_aug.arr_0to1, (80, 80), interpolation="nearest" ) > 0.1 same = np.sum(img_aug_mask == hm_aug_mask[:, :, 0]) assert hm_aug.shape == (80, 80) assert hm_aug.arr_0to1.shape == (40, 40, 1) # TODO this is a fairly low threshold, why is that the case? assert (same / img_aug_mask.size) >= 0.9 # ----------- # segmaps alignment # ----------- def test_image_segmaps_alignment(self): # test alignment between images and segmaps img = np.zeros((80, 80), dtype=np.uint8) img[:, 30:50] = 255 img[30:50, :] = 255 segmaps = SegmentationMapsOnImage( (img > 0).astype(np.int32), shape=(80, 80)) aug = iaa.ElasticTransformation( alpha=60.0, sigma=4.0, mode="constant", cval=0, order=0) aug_det = aug.to_deterministic() img_aug = aug_det.augment_image(img) segmaps_aug = aug_det.augment_segmentation_maps([segmaps])[0] img_aug_mask = img_aug > 255*0.1 segmaps_aug_mask = segmaps_aug.arr > 0 same = np.sum(img_aug_mask == segmaps_aug_mask[:, :, 0]) assert segmaps_aug.shape == (80, 80) assert segmaps_aug.arr.shape == (80, 80, 1) assert (same / img_aug_mask.size) >= 0.99 def test_image_segmaps_alignment_if_heatmaps_smaller_than_image(self): # test alignment between images and segmaps # here with segmaps that are smaller than the image img = np.zeros((80, 80), dtype=np.uint8) img[:, 30:50] = 255 img[30:50, :] = 255 img_small = ia.imresize_single_image( img, (40, 40), interpolation="nearest") segmaps = SegmentationMapsOnImage( (img_small > 0).astype(np.int32), shape=(80, 80)) aug = iaa.ElasticTransformation( alpha=60.0, sigma=4.0, mode="constant", cval=0, order=0) aug_det = aug.to_deterministic() img_aug = aug_det.augment_image(img) segmaps_aug = aug_det.augment_segmentation_maps([segmaps])[0] img_aug_mask = img_aug > 255*0.1 segmaps_aug_mask = ia.imresize_single_image( segmaps_aug.arr, (80, 80), interpolation="nearest") > 0 same = np.sum(img_aug_mask == segmaps_aug_mask[:, :, 0]) assert segmaps_aug.shape == (80, 80) assert segmaps_aug.arr.shape == (40, 40, 1) assert (same / img_aug_mask.size) >= 0.93 # --------- # unusual channel numbers # --------- def test_unusual_channel_numbers(self): shapes = [ (1, 1, 4), (1, 1, 5), (1, 1, 512), (1, 1, 513) ] for shape in shapes: with self.subTest(shape=shape): image = np.zeros(shape, dtype=np.uint8) aug = iaa.ElasticTransformation(alpha=2.0, sigma=2.0) image_aug = aug(image=image) assert np.all(image_aug == 0) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape # --------- # zero-sized axes # --------- 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: for keep_size in [False, True]: with self.subTest(shape=shape, keep_size=keep_size): for _ in sm.xrange(3): image = np.zeros(shape, dtype=np.uint8) aug = iaa.ElasticTransformation(alpha=2.0, sigma=2.0) image_aug = aug(image=image) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape # ----------- # get_parameters # ----------- def test_get_parameters(self): aug = iaa.ElasticTransformation( alpha=0.25, sigma=1.0, order=2, cval=10, mode="constant") params = aug.get_parameters() assert params[0] is aug.alpha assert params[1] is aug.sigma assert params[2] is aug.order assert params[3] is aug.cval assert params[4] is aug.mode assert 0.25 - 1e-8 < params[0].value < 0.25 + 1e-8 assert 1.0 - 1e-8 < params[1].value < 1.0 + 1e-8 assert params[2].value == 2 assert params[3].value == 10 assert params[4].value == "constant" # ----------- # other dtypes # ----------- def test_other_dtypes_bool(self): aug = iaa.ElasticTransformation(sigma=0.5, alpha=5, order=0) mask = np.zeros((21, 21), dtype=bool) mask[7:13, 7:13] = True image = np.zeros((21, 21), dtype=bool) image[mask] = True image_aug = aug.augment_image(image) assert image_aug.dtype.name == image.dtype.name assert not np.all(image_aug == 1) assert np.any(image_aug[~mask] == 1) def test_other_dtypes_uint_int(self): aug = iaa.ElasticTransformation(sigma=0.5, alpha=5, order=0) mask = np.zeros((21, 21), dtype=bool) mask[7:13, 7:13] = True dtypes = ["uint8", "uint16", "uint32", "int8", "int16", "int32"] for dtype in dtypes: min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) image = np.zeros((21, 21), dtype=dtype) image[7:13, 7:13] = max_value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert not np.all(image_aug == max_value) assert np.any(image_aug[~mask] == max_value) def test_other_dtypes_float(self): aug = iaa.ElasticTransformation(sigma=0.5, alpha=5, order=0) mask = np.zeros((21, 21), dtype=bool) mask[7:13, 7:13] = True for dtype in ["float16", "float32", "float64"]: def _isclose(a, b): atol = 1e-4 if dtype == "float16" else 1e-8 return np.isclose(a, b, atol=atol, rtol=0) isize = np.dtype(dtype).itemsize values = [ 0.01, 1.0, 10.0, 100.0, 500 ** (isize - 1), float(np.float64(1000 ** (isize - 1))) ] values = values + [(-1) * value for value in values] for value in values: with self.subTest(dtype=dtype, value=value): image = np.zeros((21, 21), dtype=dtype) image[7:13, 7:13] = value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert not np.all(_isclose(image_aug, value)) assert np.any(_isclose(image_aug[~mask], value)) def test_other_dtypes_bool_all_orders(self): mask = np.zeros((50, 50), dtype=bool) mask[10:40, 20:30] = True mask[20:30, 10:40] = True for order in [0, 1, 2, 3, 4, 5]: aug = iaa.ElasticTransformation(sigma=1.0, alpha=50, order=order) image = np.zeros((50, 50), dtype=bool) image[mask] = True image_aug = aug.augment_image(image) assert image_aug.dtype.name == image.dtype.name assert not np.all(image_aug == 1) assert np.any(image_aug[~mask] == 1) def test_other_dtypes_uint_int_all_orders(self): mask = np.zeros((50, 50), dtype=bool) mask[10:40, 20:30] = True mask[20:30, 10:40] = True for order in [0, 1, 2, 3, 4, 5]: aug = iaa.ElasticTransformation(sigma=1.0, alpha=50, order=order) dtypes = ["uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64"] if order == 0: dtypes = ["uint8", "uint16", "uint32", "int8", "int16", "int32"] for dtype in dtypes: with self.subTest(dtype=dtype): min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) dynamic_range = max_value - min_value image = np.zeros((50, 50), dtype=dtype) image[mask] = max_value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype if order == 0: assert not np.all(image_aug == max_value) assert np.any(image_aug[~mask] == max_value) else: atol = 0.1 * dynamic_range assert not np.all( np.isclose(image_aug, max_value, rtol=0, atol=atol) ) assert np.any( np.isclose(image_aug[~mask], max_value, rtol=0, atol=atol)) def test_other_dtypes_float_all_orders(self): mask = np.zeros((50, 50), dtype=bool) mask[10:40, 20:30] = True mask[20:30, 10:40] = True for order in [0, 1, 2, 3, 4, 5]: aug = iaa.ElasticTransformation(sigma=1.0, alpha=50, order=order) dtypes = ["float16", "float32", "float64"] for dtype in dtypes: with self.subTest(dtype=dtype): min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) def _isclose(a, b): atol = 1e-4 if dtype == "float16" else 1e-8 return np.isclose(a, b, atol=atol, rtol=0) value = ( 0.1 * max_value if dtype != "float64" else 0.0001 * max_value) image = np.zeros((50, 50), dtype=dtype) image[mask] = value image_aug = aug.augment_image(image) if order == 0: assert image_aug.dtype.name == dtype assert not np.all( _isclose(image_aug, value) ) assert np.any( _isclose(image_aug[~mask], value) ) else: atol = ( 10 if dtype == "float16" else 0.00001 * max_value) assert not np.all( np.isclose( image_aug, value, rtol=0, atol=atol )) assert np.any( np.isclose( image_aug[~mask], value, rtol=0, atol=atol )) def test_pickleable(self): aug = iaa.ElasticTransformation(alpha=(0.2, 1.5), sigma=(1.0, 10.0), seed=1) runtest_pickleable_uint8_img(aug, iterations=4, shape=(25, 25, 1)) class _TwoValueParam(iap.StochasticParameter): def __init__(self, v1, v2): super(_TwoValueParam, self).__init__() self.v1 = v1 self.v2 = v2 def _draw_samples(self, size, random_state): arr = np.full(size, self.v1, dtype=np.int32) arr[1::2] = self.v2 return arr class TestRot90(unittest.TestCase): @property def kp_offset(self): # set this to -1 when using integer-based KP rotation instead of # subpixel/float-based rotation return 0 @property def image(self): return np.arange(4*4*3).reshape((4, 4, 3)).astype(np.uint8) @property def heatmaps(self): return HeatmapsOnImage(self.image[..., 0:1].astype(np.float32) / 255, shape=(4, 4, 3)) @property def heatmaps_smaller(self): return HeatmapsOnImage( np.float32([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]), shape=(4, 8, 3)) @property def segmaps(self): return SegmentationMapsOnImage( self.image[..., 0:1].astype(np.int32), shape=(4, 4, 3)) @property def segmaps_smaller(self): return SegmentationMapsOnImage( np.int32([[0, 1, 2], [3, 4, 5]]), shape=(4, 8, 3)) @property def kpsoi(self): kps = [ia.Keypoint(x=1, y=2), ia.Keypoint(x=2, y=3)] return ia.KeypointsOnImage(kps, shape=(4, 8, 3)) @property def psoi(self): return ia.PolygonsOnImage( [ia.Polygon([(1, 1), (3, 1), (3, 3), (1, 3)])], shape=(4, 8, 3) ) @property def lsoi(self): return ia.LineStringsOnImage( [ia.LineString([(1, 1), (3, 1), (3, 3), (1, 3)])], shape=(4, 8, 3) ) @property def bbsoi(self): return ia.BoundingBoxesOnImage( [ia.BoundingBox(x1=1, y1=1, x2=3, y2=3)], shape=(4, 8, 3) ) @property def kpsoi_k1(self): # without keep size kp_offset = self.kp_offset expected_k1_kps = [(4-2+kp_offset, 1), (4-3+kp_offset, 2)] kps = [ia.Keypoint(x, y) for x, y in expected_k1_kps] return ia.KeypointsOnImage(kps, shape=(8, 4, 3)) @property def kpsoi_k2(self): # without keep size kp_offset = self.kp_offset expected_k1_kps = self.kpsoi_k1.to_xy_array() expected_k2_kps = [ (8-expected_k1_kps[0][1]+kp_offset, expected_k1_kps[0][0]), (8-expected_k1_kps[1][1]+kp_offset, expected_k1_kps[1][0])] kps = [ia.Keypoint(x, y) for x, y in expected_k2_kps] return ia.KeypointsOnImage(kps, shape=(4, 8, 3)) @property def kpsoi_k3(self): # without keep size kp_offset = self.kp_offset expected_k2_kps = self.kpsoi_k2.to_xy_array() expected_k3_kps = [ (4-expected_k2_kps[0][1]+kp_offset, expected_k2_kps[0][0]), (4-expected_k2_kps[1][1]+kp_offset, expected_k2_kps[1][0])] kps = [ia.Keypoint(x, y) for x, y in expected_k3_kps] return ia.KeypointsOnImage(kps, shape=(8, 4, 3)) @property def psoi_k1(self): # without keep size kp_offset = self.kp_offset expected_k1_polys = [(4-1+kp_offset, 1), (4-1+kp_offset, 3), (4-3+kp_offset, 3), (4-3+kp_offset, 1)] return ia.PolygonsOnImage([ia.Polygon(expected_k1_polys)], shape=(8, 4, 3)) @property def psoi_k2(self): # without keep size kp_offset = self.kp_offset expected_k1_polys = self.psoi_k1.polygons[0].exterior expected_k2_polys = [ (8-expected_k1_polys[0][1]+kp_offset, expected_k1_polys[0][0]), (8-expected_k1_polys[1][1]+kp_offset, expected_k1_polys[1][0]), (8-expected_k1_polys[2][1]+kp_offset, expected_k1_polys[2][0]), (8-expected_k1_polys[3][1]+kp_offset, expected_k1_polys[3][0])] return ia.PolygonsOnImage([ia.Polygon(expected_k2_polys)], shape=(4, 8, 3)) @property def psoi_k3(self): # without keep size kp_offset = self.kp_offset expected_k2_polys = self.psoi_k2.polygons[0].exterior expected_k3_polys = [ (4-expected_k2_polys[0][1]+kp_offset, expected_k2_polys[0][0]), (4-expected_k2_polys[1][1]+kp_offset, expected_k2_polys[1][0]), (4-expected_k2_polys[2][1]+kp_offset, expected_k2_polys[2][0]), (4-expected_k2_polys[3][1]+kp_offset, expected_k2_polys[3][0])] return ia.PolygonsOnImage([ia.Polygon(expected_k3_polys)], shape=(8, 4, 3)) @property def lsoi_k1(self): # without keep size kp_offset = self.kp_offset expected_k1_ls = [(4-1+kp_offset, 1), (4-1+kp_offset, 3), (4-3+kp_offset, 3), (4-3+kp_offset, 1)] return ia.LineStringsOnImage([ia.LineString(expected_k1_ls)], shape=(8, 4, 3)) @property def lsoi_k2(self): # without keep size kp_offset = self.kp_offset expected_k1_ls = self.psoi_k1.items[0].coords expected_k2_ls = [ (8-expected_k1_ls[0][1]+kp_offset, expected_k1_ls[0][0]), (8-expected_k1_ls[1][1]+kp_offset, expected_k1_ls[1][0]), (8-expected_k1_ls[2][1]+kp_offset, expected_k1_ls[2][0]), (8-expected_k1_ls[3][1]+kp_offset, expected_k1_ls[3][0])] return ia.LineStringsOnImage([ia.LineString(expected_k2_ls)], shape=(4, 8, 3)) @property def lsoi_k3(self): # without keep size kp_offset = self.kp_offset expected_k2_ls = self.lsoi_k2.items[0].coords expected_k3_ls = [ (4-expected_k2_ls[0][1]+kp_offset, expected_k2_ls[0][0]), (4-expected_k2_ls[1][1]+kp_offset, expected_k2_ls[1][0]), (4-expected_k2_ls[2][1]+kp_offset, expected_k2_ls[2][0]), (4-expected_k2_ls[3][1]+kp_offset, expected_k2_ls[3][0])] return ia.LineStringsOnImage([ia.LineString(expected_k3_ls)], shape=(8, 4, 3)) @property def bbsoi_k1(self): # without keep size kp_offset = self.kp_offset expected_k1_coords = [ (4-1+kp_offset, 1), (4-3+kp_offset, 3)] return ia.BoundingBoxesOnImage([ ia.BoundingBox( x1=min(expected_k1_coords[0][0], expected_k1_coords[1][0]), y1=min(expected_k1_coords[0][1], expected_k1_coords[1][1]), x2=max(expected_k1_coords[1][0], expected_k1_coords[0][0]), y2=max(expected_k1_coords[1][1], expected_k1_coords[0][1]) )], shape=(8, 4, 3)) @property def bbsoi_k2(self): # without keep size kp_offset = self.kp_offset coords = self.bbsoi_k1.bounding_boxes[0].coords expected_k2_coords = [ (8-coords[0][1]+kp_offset, coords[0][0]), (8-coords[1][1]+kp_offset, coords[1][0])] return ia.BoundingBoxesOnImage([ ia.BoundingBox( x1=min(expected_k2_coords[0][0], expected_k2_coords[1][0]), y1=min(expected_k2_coords[0][1], expected_k2_coords[1][1]), x2=max(expected_k2_coords[1][0], expected_k2_coords[0][0]), y2=max(expected_k2_coords[1][1], expected_k2_coords[0][1]) )], shape=(4, 8, 3)) @property def bbsoi_k3(self): # without keep size kp_offset = self.kp_offset coords = self.bbsoi_k2.bounding_boxes[0].coords expected_k3_coords = [ (4-coords[0][1]+kp_offset, coords[0][0]), (4-coords[1][1]+kp_offset, coords[1][0])] return ia.BoundingBoxesOnImage([ ia.BoundingBox( x1=min(expected_k3_coords[0][0], expected_k3_coords[1][0]), y1=min(expected_k3_coords[0][1], expected_k3_coords[1][1]), x2=max(expected_k3_coords[1][0], expected_k3_coords[0][0]), y2=max(expected_k3_coords[1][1], expected_k3_coords[0][1]) )], shape=(8, 4, 3)) def test___init___k_is_list(self): aug = iaa.Rot90([1, 3]) assert is_parameter_instance(aug.k, iap.Choice) assert len(aug.k.a) == 2 assert aug.k.a[0] == 1 assert aug.k.a[1] == 3 def test___init___k_is_all(self): aug = iaa.Rot90(ia.ALL) assert is_parameter_instance(aug.k, iap.Choice) assert len(aug.k.a) == 4 assert aug.k.a == [0, 1, 2, 3] def test_images_k_is_0_and_4(self): for k in [0, 4]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) img_aug = aug.augment_image(self.image) assert img_aug.dtype.name == "uint8" assert np.array_equal(img_aug, self.image) def test_heatmaps_k_is_0_and_4(self): for k in [0, 4]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) hms_aug = aug.augment_heatmaps([self.heatmaps])[0] assert (hms_aug.arr_0to1.dtype.name == self.heatmaps.arr_0to1.dtype.name) assert np.allclose(hms_aug.arr_0to1, self.heatmaps.arr_0to1) assert hms_aug.shape == self.heatmaps.shape def test_segmaps_k_is_0_and_4(self): for k in [0, 4]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) segmaps_aug = aug.augment_segmentation_maps( [self.segmaps] )[0] assert ( segmaps_aug.arr.dtype.name == self.segmaps.arr.dtype.name) assert np.allclose(segmaps_aug.arr, self.segmaps.arr) assert segmaps_aug.shape == self.segmaps.shape def test_keypoints_k_is_0_and_4(self): for k in [0, 4]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) kpsoi_aug = aug.augment_keypoints([self.kpsoi])[0] assert_cbaois_equal(kpsoi_aug, self.kpsoi) def test_polygons_k_is_0_and_4(self): for k in [0, 4]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) psoi_aug = aug.augment_polygons(self.psoi) assert_cbaois_equal(psoi_aug, self.psoi) def test_line_strings_k_is_0_and_4(self): for k in [0, 4]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) lsoi_aug = aug.augment_line_strings(self.lsoi) assert_cbaois_equal(lsoi_aug, self.lsoi) def test_bounding_boxes_k_is_0_and_4(self): for k in [0, 4]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) bbsoi_aug = aug.augment_bounding_boxes(self.bbsoi) assert_cbaois_equal(bbsoi_aug, self.bbsoi) def test_images_k_is_1_and_5(self): for k in [1, 5]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) img_aug = aug.augment_image(self.image) assert img_aug.dtype.name == "uint8" assert np.array_equal(img_aug, np.rot90(self.image, 1, axes=(1, 0))) def test_heatmaps_k_is_1_and_5(self): for k in [1, 5]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) hms_aug = aug.augment_heatmaps([self.heatmaps])[0] assert (hms_aug.arr_0to1.dtype.name == self.heatmaps.arr_0to1.dtype.name) assert np.allclose( hms_aug.arr_0to1, np.rot90(self.heatmaps.arr_0to1, 1, axes=(1, 0))) assert hms_aug.shape == (4, 4, 3) def test_heatmaps_smaller_than_image_k_is_1_and_5(self): for k in [1, 5]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) hms_smaller_aug = aug.augment_heatmaps( [self.heatmaps_smaller] )[0] assert ( hms_smaller_aug.arr_0to1.dtype.name == self.heatmaps_smaller.arr_0to1.dtype.name) assert np.allclose( hms_smaller_aug.arr_0to1, np.rot90(self.heatmaps_smaller.arr_0to1, 1, axes=(1, 0))) assert hms_smaller_aug.shape == (8, 4, 3) def test_segmaps_k_is_1_and_5(self): for k in [1, 5]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) segmaps_aug = aug.augment_segmentation_maps( [self.segmaps] )[0] assert ( segmaps_aug.arr.dtype.name == self.segmaps.arr.dtype.name) assert np.allclose( segmaps_aug.arr, np.rot90(self.segmaps.arr, 1, axes=(1, 0))) assert segmaps_aug.shape == (4, 4, 3) def test_segmaps_smaller_than_image_k_is_1_and_5(self): for k in [1, 5]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) segmaps_smaller_aug = aug.augment_segmentation_maps( self.segmaps_smaller) assert ( segmaps_smaller_aug.arr.dtype.name == self.segmaps_smaller.arr.dtype.name) assert np.allclose( segmaps_smaller_aug.arr, np.rot90(self.segmaps_smaller.arr, 1, axes=(1, 0))) assert segmaps_smaller_aug.shape == (8, 4, 3) def test_keypoints_k_is_1_and_5(self): for k in [1, 5]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) kpsoi_aug = aug.augment_keypoints([self.kpsoi])[0] assert_cbaois_equal(kpsoi_aug, self.kpsoi_k1) def test_polygons_k_is_1_and_5(self): for k in [1, 5]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) psoi_aug = aug.augment_polygons(self.psoi) assert_cbaois_equal(psoi_aug, self.psoi_k1) def test_line_strings_k_is_1_and_5(self): for k in [1, 5]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) lsoi_aug = aug.augment_line_strings(self.lsoi) assert_cbaois_equal(lsoi_aug, self.lsoi_k1) def test_bounding_boxes_k_is_1_and_5(self): for k in [1, 5]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) bbsoi_aug = aug.augment_bounding_boxes(self.bbsoi) assert_cbaois_equal(bbsoi_aug, self.bbsoi_k1) def test_images_k_is_2(self): aug = iaa.Rot90(2, keep_size=False) img = self.image img_aug = aug.augment_image(img) assert img_aug.dtype.name == "uint8" assert np.array_equal(img_aug, np.rot90(img, 2, axes=(1, 0))) def test_heatmaps_k_is_2(self): aug = iaa.Rot90(2, keep_size=False) hms = self.heatmaps hms_aug = aug.augment_heatmaps([hms])[0] assert hms_aug.arr_0to1.dtype.name == hms.arr_0to1.dtype.name assert np.allclose( hms_aug.arr_0to1, np.rot90(hms.arr_0to1, 2, axes=(1, 0))) assert hms_aug.shape == (4, 4, 3) def test_heatmaps_smaller_than_image_k_is_2(self): aug = iaa.Rot90(2, keep_size=False) hms_smaller = self.heatmaps_smaller hms_smaller_aug = aug.augment_heatmaps([hms_smaller])[0] assert (hms_smaller_aug.arr_0to1.dtype.name == hms_smaller.arr_0to1.dtype.name) assert np.allclose( hms_smaller_aug.arr_0to1, np.rot90(hms_smaller.arr_0to1, 2, axes=(1, 0))) assert hms_smaller_aug.shape == (4, 8, 3) def test_segmaps_k_is_2(self): aug = iaa.Rot90(2, keep_size=False) segmaps = self.segmaps segmaps_aug = aug.augment_segmentation_maps([segmaps])[0] assert segmaps_aug.arr.dtype.name == segmaps.arr.dtype.name assert np.allclose( segmaps_aug.arr, np.rot90(segmaps.arr, 2, axes=(1, 0))) assert segmaps_aug.shape == (4, 4, 3) def test_segmaps_smaller_than_image_k_is_2(self): aug = iaa.Rot90(2, keep_size=False) segmaps_smaller = self.segmaps_smaller segmaps_smaller_aug = aug.augment_segmentation_maps(segmaps_smaller) assert (segmaps_smaller_aug.arr.dtype.name == segmaps_smaller.arr.dtype.name) assert np.allclose( segmaps_smaller_aug.arr, np.rot90(segmaps_smaller.arr, 2, axes=(1, 0))) assert segmaps_smaller_aug.shape == (4, 8, 3) def test_keypoints_k_is_2(self): aug = iaa.Rot90(2, keep_size=False) kpsoi_aug = aug.augment_keypoints([self.kpsoi])[0] assert_cbaois_equal(kpsoi_aug, self.kpsoi_k2) def test_polygons_k_is_2(self): aug = iaa.Rot90(2, keep_size=False) psoi_aug = aug.augment_polygons(self.psoi) assert_cbaois_equal(psoi_aug, self.psoi_k2) def test_line_strings_k_is_2(self): aug = iaa.Rot90(2, keep_size=False) lsoi_aug = aug.augment_line_strings(self.lsoi) assert_cbaois_equal(lsoi_aug, self.lsoi_k2) def test_bounding_boxes_k_is_2(self): aug = iaa.Rot90(2, keep_size=False) bbsoi_aug = aug.augment_bounding_boxes(self.bbsoi) assert_cbaois_equal(bbsoi_aug, self.bbsoi_k2) def test_images_k_is_3_and_minus1(self): img = self.image for k in [3, -1]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) img_aug = aug.augment_image(img) assert img_aug.dtype.name == "uint8" assert np.array_equal(img_aug, np.rot90(img, 3, axes=(1, 0))) def test_heatmaps_k_is_3_and_minus1(self): hms = self.heatmaps for k in [3, -1]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) hms_aug = aug.augment_heatmaps([hms])[0] assert (hms_aug.arr_0to1.dtype.name == hms.arr_0to1.dtype.name) assert np.allclose( hms_aug.arr_0to1, np.rot90(hms.arr_0to1, 3, axes=(1, 0))) assert hms_aug.shape == (4, 4, 3) def test_heatmaps_smaller_than_image_k_is_3_and_minus1(self): hms_smaller = self.heatmaps_smaller for k in [3, -1]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) hms_smaller_aug = aug.augment_heatmaps([hms_smaller])[0] assert (hms_smaller_aug.arr_0to1.dtype.name == hms_smaller.arr_0to1.dtype.name) assert np.allclose( hms_smaller_aug.arr_0to1, np.rot90(hms_smaller.arr_0to1, 3, axes=(1, 0))) assert hms_smaller_aug.shape == (8, 4, 3) def test_segmaps_k_is_3_and_minus1(self): segmaps = self.segmaps for k in [3, -1]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) segmaps_aug = aug.augment_segmentation_maps([segmaps])[0] assert (segmaps_aug.arr.dtype.name == segmaps.arr.dtype.name) assert np.allclose( segmaps_aug.arr, np.rot90(segmaps.arr, 3, axes=(1, 0))) assert segmaps_aug.shape == (4, 4, 3) def test_segmaps_smaller_than_image_k_is_3_and_minus1(self): segmaps_smaller = self.segmaps_smaller for k in [3, -1]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) segmaps_smaller_aug = aug.augment_segmentation_maps( segmaps_smaller) assert (segmaps_smaller_aug.arr.dtype.name == segmaps_smaller.arr.dtype.name) assert np.allclose( segmaps_smaller_aug.arr, np.rot90(segmaps_smaller.arr, 3, axes=(1, 0))) assert segmaps_smaller_aug.shape == (8, 4, 3) def test_keypoints_k_is_3_and_minus1(self): for k in [3, -1]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) kpsoi_aug = aug.augment_keypoints([self.kpsoi])[0] assert_cbaois_equal(kpsoi_aug, self.kpsoi_k3) def test_polygons_k_is_3_and_minus1(self): for k in [3, -1]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) psoi_aug = aug.augment_polygons(self.psoi) assert_cbaois_equal(psoi_aug, self.psoi_k3) def test_line_strings_k_is_3_and_minus1(self): for k in [3, -1]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) lsoi_aug = aug.augment_line_strings(self.lsoi) assert_cbaois_equal(lsoi_aug, self.lsoi_k3) def test_bounding_boxes_k_is_3_and_minus1(self): for k in [3, -1]: with self.subTest(k=k): aug = iaa.Rot90(k, keep_size=False) bbsoi_aug = aug.augment_bounding_boxes(self.bbsoi) assert_cbaois_equal(bbsoi_aug, self.bbsoi_k3) def test_images_k_is_1_verify_without_using_numpy_rot90(self): # verify once without np.rot90 aug = iaa.Rot90(k=1, keep_size=False) image = np.uint8([[1, 0, 0], [0, 2, 0]]) img_aug = aug.augment_image(image) expected = np.uint8([[0, 1], [2, 0], [0, 0]]) assert np.array_equal(img_aug, expected) def test_images_k_is_1_keep_size_is_true(self): # keep_size=True, k=1 aug = iaa.Rot90(1, keep_size=True) img_nonsquare = np.arange(5*4*3).reshape((5, 4, 3)).astype(np.uint8) img_aug = aug.augment_image(img_nonsquare) assert img_aug.dtype.name == "uint8" assert np.array_equal( img_aug, ia.imresize_single_image( np.rot90(img_nonsquare, 1, axes=(1, 0)), (5, 4) ) ) def test_heatmaps_k_is_1_keep_size_is_true(self): aug = iaa.Rot90(1, keep_size=True) hms = self.heatmaps hms_aug = aug.augment_heatmaps([hms])[0] assert hms_aug.arr_0to1.dtype.name == hms.arr_0to1.dtype.name assert np.allclose( hms_aug.arr_0to1, np.rot90(hms.arr_0to1, 1, axes=(1, 0))) assert hms_aug.shape == (4, 4, 3) def test_heatmaps_smaller_than_image_k_is_1_keep_size_is_true(self): aug = iaa.Rot90(1, keep_size=True) hms_smaller = self.heatmaps_smaller hms_smaller_aug = aug.augment_heatmaps([hms_smaller])[0] hms_smaller_rot = np.rot90(hms_smaller.arr_0to1, 1, axes=(1, 0)) hms_smaller_rot = np.clip( ia.imresize_single_image( hms_smaller_rot, (2, 3), interpolation="cubic" ), 0.0, 1.0) assert (hms_smaller_aug.arr_0to1.dtype.name == hms_smaller.arr_0to1.dtype.name) assert np.allclose(hms_smaller_aug.arr_0to1, hms_smaller_rot) assert hms_smaller_aug.shape == (4, 8, 3) def test_segmaps_k_is_1_keep_size_is_true(self): aug = iaa.Rot90(1, keep_size=True) segmaps = self.segmaps segmaps_aug = aug.augment_segmentation_maps([segmaps])[0] assert (segmaps_aug.arr.dtype.name == segmaps.arr.dtype.name) assert np.allclose(segmaps_aug.arr, np.rot90(segmaps.arr, 1, axes=(1, 0))) assert segmaps_aug.shape == (4, 4, 3) def test_segmaps_smaller_than_image_k_is_1_keep_size_is_true(self): aug = iaa.Rot90(1, keep_size=True) segmaps_smaller = self.segmaps_smaller segmaps_smaller_aug = aug.augment_segmentation_maps(segmaps_smaller) segmaps_smaller_rot = np.rot90(segmaps_smaller.arr, 1, axes=(1, 0)) segmaps_smaller_rot = ia.imresize_single_image( segmaps_smaller_rot, (2, 3), interpolation="nearest") assert (segmaps_smaller_aug.arr.dtype.name == segmaps_smaller.arr.dtype.name) assert np.allclose(segmaps_smaller_aug.arr, segmaps_smaller_rot) assert segmaps_smaller_aug.shape == (4, 8, 3) def test_keypoints_k_is_1_keep_size_is_true(self): aug = iaa.Rot90(1, keep_size=True) kp_offset = self.kp_offset kpsoi = self.kpsoi kpsoi_aug = aug.augment_keypoints([kpsoi])[0] expected = [(4-2+kp_offset, 1), (4-3+kp_offset, 2)] expected = [(8*x/4, 4*y/8) for x, y in expected] assert kpsoi_aug.shape == (4, 8, 3) for kp_aug, kp in zip(kpsoi_aug.keypoints, expected): assert np.allclose([kp_aug.x, kp_aug.y], [kp[0], kp[1]]) def test_polygons_k_is_1_keep_size_is_true(self): aug = iaa.Rot90(1, keep_size=True) psoi = self.psoi kp_offset = self.kp_offset psoi_aug = aug.augment_polygons(psoi) expected = [(4-1+kp_offset, 1), (4-1+kp_offset, 3), (4-3+kp_offset, 3), (4-3+kp_offset, 1)] expected = [(8*x/4, 4*y/8) for x, y in expected] assert psoi_aug.shape == (4, 8, 3) assert len(psoi_aug.polygons) == 1 assert psoi_aug.polygons[0].is_valid assert psoi_aug.polygons[0].exterior_almost_equals(expected) def test_line_strings_k_is_1_keep_size_is_true(self): aug = iaa.Rot90(1, keep_size=True) lsoi = self.lsoi kp_offset = self.kp_offset lsoi_aug = aug.augment_line_strings(lsoi) expected = [(4-1+kp_offset, 1), (4-1+kp_offset, 3), (4-3+kp_offset, 3), (4-3+kp_offset, 1)] expected = [(8*x/4, 4*y/8) for x, y in expected] assert lsoi_aug.shape == (4, 8, 3) assert len(lsoi_aug.items) == 1 assert lsoi_aug.items[0].coords_almost_equals(expected) def test_bounding_boxes_k_is_1_keep_size_is_true(self): aug = iaa.Rot90(1, keep_size=True) bbsoi = self.bbsoi kp_offset = self.kp_offset bbsoi_aug = aug.augment_bounding_boxes(bbsoi) expected = [(4-1+kp_offset, 1), (4-3+kp_offset, 3)] expected = [(8*x/4, 4*y/8) for x, y in expected] expected = np.float32([ [min(expected[0][0], expected[1][0]), min(expected[0][1], expected[1][1])], [max(expected[0][0], expected[1][0]), max(expected[0][1], expected[1][1])] ]) assert bbsoi_aug.shape == (4, 8, 3) assert len(bbsoi_aug.bounding_boxes) == 1 assert bbsoi_aug.bounding_boxes[0].coords_almost_equals(expected) def test_images_k_is_list(self): aug = iaa.Rot90(_TwoValueParam(1, 2), keep_size=False) img = self.image imgs_aug = aug.augment_images([img] * 4) assert np.array_equal(imgs_aug[0], np.rot90(img, 1, axes=(1, 0))) assert np.array_equal(imgs_aug[1], np.rot90(img, 2, axes=(1, 0))) assert np.array_equal(imgs_aug[2], np.rot90(img, 1, axes=(1, 0))) assert np.array_equal(imgs_aug[3], np.rot90(img, 2, axes=(1, 0))) def test_heatmaps_smaller_than_image_k_is_list(self): def _rot_hm(hm, k): return np.rot90(hm.arr_0to1, k, axes=(1, 0)) aug = iaa.Rot90(_TwoValueParam(1, 2), keep_size=False) hms_smaller = self.heatmaps_smaller hms_aug = aug.augment_heatmaps([hms_smaller] * 4) assert hms_aug[0].shape == (8, 4, 3) assert hms_aug[1].shape == (4, 8, 3) assert hms_aug[2].shape == (8, 4, 3) assert hms_aug[3].shape == (4, 8, 3) assert np.allclose(hms_aug[0].arr_0to1, _rot_hm(hms_smaller, 1)) assert np.allclose(hms_aug[1].arr_0to1, _rot_hm(hms_smaller, 2)) assert np.allclose(hms_aug[2].arr_0to1, _rot_hm(hms_smaller, 1)) assert np.allclose(hms_aug[3].arr_0to1, _rot_hm(hms_smaller, 2)) def test_segmaps_smaller_than_image_k_is_list(self): def _rot_sm(segmap, k): return np.rot90(segmap.arr, k, axes=(1, 0)) aug = iaa.Rot90(_TwoValueParam(1, 2), keep_size=False) segmaps_smaller = self.segmaps_smaller segmaps_aug = aug.augment_segmentation_maps([segmaps_smaller] * 4) assert segmaps_aug[0].shape == (8, 4, 3) assert segmaps_aug[1].shape == (4, 8, 3) assert segmaps_aug[2].shape == (8, 4, 3) assert segmaps_aug[3].shape == (4, 8, 3) assert np.allclose(segmaps_aug[0].arr, _rot_sm(segmaps_smaller, 1)) assert np.allclose(segmaps_aug[1].arr, _rot_sm(segmaps_smaller, 2)) assert np.allclose(segmaps_aug[2].arr, _rot_sm(segmaps_smaller, 1)) assert np.allclose(segmaps_aug[3].arr, _rot_sm(segmaps_smaller, 2)) def test_keypoints_k_is_list(self): aug = iaa.Rot90(_TwoValueParam(1, 2), keep_size=False) kpsoi = self.kpsoi kpsoi_aug = aug.augment_keypoints([kpsoi] * 4) assert_cbaois_equal(kpsoi_aug[0], self.kpsoi_k1) assert_cbaois_equal(kpsoi_aug[1], self.kpsoi_k2) assert_cbaois_equal(kpsoi_aug[2], self.kpsoi_k1) assert_cbaois_equal(kpsoi_aug[3], self.kpsoi_k2) def test_polygons_k_is_list(self): aug = iaa.Rot90(_TwoValueParam(1, 2), keep_size=False) psoi = self.psoi psoi_aug = aug.augment_polygons([psoi] * 4) assert_cbaois_equal(psoi_aug[0], self.psoi_k1) assert_cbaois_equal(psoi_aug[1], self.psoi_k2) assert_cbaois_equal(psoi_aug[2], self.psoi_k1) assert_cbaois_equal(psoi_aug[3], self.psoi_k2) def test_line_strings_k_is_list(self): aug = iaa.Rot90(_TwoValueParam(1, 2), keep_size=False) lsoi = self.lsoi lsoi_aug = aug.augment_line_strings([lsoi] * 4) assert_cbaois_equal(lsoi_aug[0], self.lsoi_k1) assert_cbaois_equal(lsoi_aug[1], self.lsoi_k2) assert_cbaois_equal(lsoi_aug[2], self.lsoi_k1) assert_cbaois_equal(lsoi_aug[3], self.lsoi_k2) def test_bounding_boxes_k_is_list(self): aug = iaa.Rot90(_TwoValueParam(1, 2), keep_size=False) bbsoi = self.bbsoi bbsoi_aug = aug.augment_bounding_boxes([bbsoi] * 4) assert_cbaois_equal(bbsoi_aug[0], self.bbsoi_k1) assert_cbaois_equal(bbsoi_aug[1], self.bbsoi_k2) assert_cbaois_equal(bbsoi_aug[2], self.bbsoi_k1) assert_cbaois_equal(bbsoi_aug[3], self.bbsoi_k2) def test_empty_keypoints(self): aug = iaa.Rot90(k=1, keep_size=False) kpsoi = ia.KeypointsOnImage([], shape=(4, 8, 3)) kpsoi_aug = aug.augment_keypoints(kpsoi) expected = self.kpsoi_k1 expected.keypoints = [] assert_cbaois_equal(kpsoi_aug, expected) def test_empty_polygons(self): aug = iaa.Rot90(k=1, keep_size=False) psoi = ia.PolygonsOnImage([], shape=(4, 8, 3)) psoi_aug = aug.augment_polygons(psoi) expected = self.psoi_k1 expected.polygons = [] assert_cbaois_equal(psoi_aug, expected) def test_empty_line_strings(self): aug = iaa.Rot90(k=1, keep_size=False) lsoi = ia.LineStringsOnImage([], shape=(4, 8, 3)) lsoi_aug = aug.augment_line_strings(lsoi) expected = self.lsoi_k1 expected.line_strings = [] assert_cbaois_equal(lsoi_aug, expected) def test_empty_bounding_boxes(self): aug = iaa.Rot90(k=1, keep_size=False) bbsoi = ia.BoundingBoxesOnImage([], shape=(4, 8, 3)) bbsoi_aug = aug.augment_bounding_boxes(bbsoi) expected = self.bbsoi_k1 expected.bounding_boxes = [] assert_cbaois_equal(bbsoi_aug, expected) def test_unusual_channel_numbers(self): shapes = [ (1, 1, 4), (1, 1, 5), (1, 1, 512), (1, 1, 513) ] for shape in shapes: with self.subTest(shape=shape): image = np.zeros(shape, dtype=np.uint8) aug = iaa.Rot90(k=1) image_aug = aug(image=image) shape_expected = tuple([shape[1], shape[0]] + list(shape[2:])) assert np.all(image_aug == 0) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape_expected def test_zero_sized_axes_k_0_or_2(self): shapes = [ (0, 0), (0, 1), (1, 0), (0, 1, 0), (1, 0, 0), (0, 1, 1), (1, 0, 1) ] for shape in shapes: for keep_size in [False, True]: with self.subTest(shape=shape, keep_size=keep_size): for _ in sm.xrange(10): image = np.zeros(shape, dtype=np.uint8) aug = iaa.Rot90([0, 2], keep_size=keep_size) image_aug = aug(image=image) assert image_aug.shape == shape def test_zero_sized_axes_k_1_or_3_no_keep_size(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): for _ in sm.xrange(10): image = np.zeros(shape, dtype=np.uint8) aug = iaa.Rot90([1, 3], keep_size=False) image_aug = aug(image=image) shape_expected = tuple([shape[1], shape[0]] + list(shape[2:])) assert image_aug.shape == shape_expected def test_zero_sized_axes_k_1_or_3_keep_size(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): for _ in sm.xrange(10): image = np.zeros(shape, dtype=np.uint8) aug = iaa.Rot90([1, 3], keep_size=True) image_aug = aug(image=image) assert image_aug.shape == image.shape def test_get_parameters(self): aug = iaa.Rot90([1, 3], keep_size=False) assert aug.get_parameters()[0] == aug.k assert aug.get_parameters()[1] is False def test_other_dtypes_bool(self): aug = iaa.Rot90(2) image = np.zeros((3, 3), dtype=bool) image[0, 0] = True image_aug = aug.augment_image(image) assert image_aug.dtype.name == image.dtype.name assert np.all(image_aug[0, 0] == 0) assert np.all(image_aug[2, 2] == 1) def test_other_dtypes_uint_int(self): aug = iaa.Rot90(2) dtypes = ["uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64"] for dtype in dtypes: with self.subTest(dtype=dtype): min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) image = np.zeros((3, 3), dtype=dtype) image[0, 0] = max_value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert np.all(image_aug[0, 0] == 0) assert np.all(image_aug[2, 2] == max_value) def test_other_dtypes_float(self): aug = iaa.Rot90(2) try: high_res_dt = np.float128 dtypes = ["float16", "float32", "float64", "float128"] except AttributeError: high_res_dt = np.float64 dtypes = ["float16", "float32", "float64"] for dtype in dtypes: def _allclose(a, b): atol = 1e-4 if dtype == "float16" else 1e-8 return np.allclose(a, b, atol=atol, rtol=0) isize = np.dtype(dtype).itemsize values = [ 0, 1.0, 10.0, 100.0, high_res_dt(500 ** (isize-1)), high_res_dt(1000 ** (isize-1)) ] values = values + [(-1) * value for value in values] for value in values: with self.subTest(dtype=dtype, value=value): image = np.zeros((3, 3), dtype=dtype) image[0, 0] = value image_aug = aug.augment_image(image) assert image_aug.dtype.name == dtype assert _allclose(image_aug[0, 0], 0) assert _allclose(image_aug[2, 2], high_res_dt(value)) def test_pickleable(self): aug = iaa.Rot90([0, 1, 2, 3], seed=1) runtest_pickleable_uint8_img(aug, iterations=5) class TestWithPolarWarping(unittest.TestCase): def setUp(self): reseed() def test___init___single_augmenter_as_child(self): aug = iaa.WithPolarWarping(iaa.Noop()) assert isinstance(aug.children, iaa.Sequential) assert isinstance(aug.children[0], iaa.Noop) def test___init___list_of_augmenters_as_child(self): aug = iaa.WithPolarWarping([iaa.Noop(), iaa.Noop()]) assert isinstance(aug.children, iaa.Sequential) assert isinstance(aug.children[0], iaa.Noop) assert isinstance(aug.children[1], iaa.Noop) def test_images_no_change(self): image = np.mod(np.arange(10*20*3), 255).astype(np.uint8) image = image.reshape((10, 20, 3)) aug = iaa.WithPolarWarping(iaa.Noop()) image_aug = aug(image=image) avg_dist = np.average( np.abs( image_aug.astype(np.int32)[2:-2, 2:-2] - image.astype(np.int32)[2:-2, 2:-2] ) ) assert image_aug.shape == (10, 20, 3) assert avg_dist < 7.0 def test_heatmaps_no_change(self): hm = np.linspace(0, 1.0, 10*20, dtype=np.float32).reshape((10, 20, 1)) hm = ia.HeatmapsOnImage(hm, shape=(10, 20, 3)) aug = iaa.WithPolarWarping(iaa.Noop()) hm_aug = aug(heatmaps=hm) avg_dist = np.average( np.abs( hm_aug.get_arr()[2:-2, 2:-2] - hm.get_arr()[2:-2, 2:-2] ) ) assert hm_aug.shape == (10, 20, 3) assert avg_dist < 0.0125 def test_segmentation_maps_no_change(self): sm = np.zeros((10, 20, 1), dtype=np.int32) sm[1, 0:5] = 1 sm[3:3, 3:3] = 2 sm[7:9, :] = 3 sm = ia.SegmentationMapsOnImage(sm, shape=(10, 20, 3)) aug = iaa.WithPolarWarping(iaa.Noop()) sm_aug = aug(segmentation_maps=sm) p_same = np.average( sm_aug.get_arr()[2:-2, 2:-2] == sm.get_arr()[2:-2, 2:-2] ) assert sm_aug.shape == (10, 20, 3) assert p_same > 0.95 def test_keypoints_no_change(self): kps = [ia.Keypoint(x=1, y=2), ia.Keypoint(x=5, y=5), ia.Keypoint(x=5, y=9)] kpsoi = ia.KeypointsOnImage(kps, shape=(10, 20, 3)) aug = iaa.WithPolarWarping(iaa.Noop()) kpsoi_aug = aug(keypoints=kpsoi) assert kpsoi_aug.shape == (10, 20, 3) assert np.allclose(kpsoi_aug.to_xy_array(), kpsoi.to_xy_array(), atol=0.01) def test_bounding_boxes_no_change(self): bbs = [ ia.BoundingBox(x1=1, y1=2, x2=3, y2=4, label="foo"), ia.BoundingBox(x1=3, y1=5, x2=7, y2=10), ] bbsoi = ia.BoundingBoxesOnImage(bbs, shape=(10, 20, 3)) aug = iaa.WithPolarWarping(iaa.Noop()) bbsoi_aug = aug(bounding_boxes=bbsoi) assert bbsoi_aug.items[0].label == "foo" assert bbsoi_aug.items[1].label is None assert bbsoi_aug.shape == (10, 20, 3) assert np.allclose(bbsoi_aug.to_xy_array(), bbsoi.to_xy_array(), atol=0.01) def test_polygons_no_change(self): ps = [ ia.Polygon([(0, 2), (4, 2), (4, 4)], label="foo"), ia.Polygon([(0, 0), (5, 0), (5, 5), (0, 5)]) ] psoi = ia.PolygonsOnImage(ps, shape=(10, 20, 3)) aug = iaa.WithPolarWarping(iaa.Noop()) psoi_aug = aug(polygons=psoi) assert psoi_aug.items[0].label == "foo" assert psoi_aug.items[1].label is None assert psoi_aug.shape == (10, 20, 3) assert np.allclose(psoi_aug.to_xy_array(), psoi.to_xy_array(), atol=0.01) def test_line_strings_no_change(self): ls = [ ia.LineString([(0, 2), (4, 2), (4, 4)]), ia.LineString([(0, 0), (5, 0), (5, 5), (0, 5)]) ] lsoi = ia.LineStringsOnImage(ls, shape=(10, 20, 3)) aug = iaa.WithPolarWarping(iaa.Noop()) lsoi_aug = aug(line_strings=lsoi) assert lsoi_aug.shape == (10, 20, 3) assert np.allclose(lsoi_aug.to_xy_array(), lsoi.to_xy_array(), atol=0.01) def test_bounding_boxes_and_polygons_provided_no_change(self): bbs = [ ia.BoundingBox(x1=1, y1=2, x2=3, y2=4, label="foo"), ia.BoundingBox(x1=3, y1=5, x2=7, y2=10), ] bbsoi = ia.BoundingBoxesOnImage(bbs, shape=(10, 20, 3)) ps = [ ia.Polygon([(0, 2), (4, 2), (4, 4)], label="foo"), ia.Polygon([(0, 0), (5, 0), (5, 5), (0, 5)]) ] psoi = ia.PolygonsOnImage(ps, shape=(10, 20, 3)) aug = iaa.WithPolarWarping(iaa.Noop()) aug = aug.to_deterministic() bbsoi_aug = aug.augment_bounding_boxes(bbsoi) psoi_aug = aug.augment_polygons(psoi) assert bbsoi_aug.items[0].label == "foo" assert bbsoi_aug.items[1].label is None assert bbsoi_aug.shape == (10, 20, 3) assert np.allclose(bbsoi_aug.to_xy_array(), bbsoi.to_xy_array(), atol=0.01) assert psoi_aug.items[0].label == "foo" assert psoi_aug.items[1].label is None assert psoi_aug.shape == (10, 20, 3) assert np.allclose(psoi_aug.to_xy_array(), psoi.to_xy_array(), atol=0.01) def test_images_translation_x(self): image = np.zeros((50, 70, 3), dtype=np.uint8) image[20-1:20+1, 30-1:30+1, 0] = 255 image[30-1:30+1, 40-1:40+1, 1] = 255 aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 15})) image_aug = aug(image=image) x1 = np.argmax(np.max(image_aug[..., 0], axis=0)) y1 = np.argmax(np.max(image_aug[..., 0], axis=1)) x2 = np.argmax(np.max(image_aug[..., 1], axis=0)) y2 = np.argmax(np.max(image_aug[..., 1], axis=1)) # translation on x axis in polar representation should move all points # a bit away from the center min_diff = 4 assert image_aug.shape == (50, 70, 3) assert x1 < 30 - min_diff assert y1 < 20 - min_diff assert x2 > 40 + min_diff assert y2 > 30 + min_diff def test_heatmaps_translation_x(self): hm = np.zeros((50, 70, 2), dtype=np.float32) hm[20-1:20+1, 30-1:30+1, 0] = 1.0 hm[30-1:30+1, 40-1:40+1, 1] = 1.0 hm = ia.HeatmapsOnImage(hm, shape=(50, 70, 3)) aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 15})) hm_aug = aug(heatmaps=hm) hm_aug_arr = hm_aug.get_arr() x1 = np.argmax(np.max(hm_aug_arr[..., 0], axis=0)) y1 = np.argmax(np.max(hm_aug_arr[..., 0], axis=1)) x2 = np.argmax(np.max(hm_aug_arr[..., 1], axis=0)) y2 = np.argmax(np.max(hm_aug_arr[..., 1], axis=1)) # translation on x axis in polar representation should move all points # a bit away from the center min_diff = 4 assert hm_aug_arr.shape == (50, 70, 2) assert hm_aug.shape == (50, 70, 3) assert x1 < 30 - min_diff assert y1 < 20 - min_diff assert x2 > 40 + min_diff assert y2 > 30 + min_diff def test_segmentation_maps_translation_x(self): sm = np.zeros((50, 70, 2), dtype=np.int32) sm[20-1:20+1, 30-1:30+1, 0] = 1 sm[30-1:30+1, 40-1:40+1, 1] = 2 sm = ia.SegmentationMapsOnImage(sm, shape=(50, 70, 3)) aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 15})) sm_aug = aug(segmentation_maps=sm) sm_aug_arr = sm_aug.get_arr() x1 = np.argmax(np.max(sm_aug_arr[..., 0], axis=0)) y1 = np.argmax(np.max(sm_aug_arr[..., 0], axis=1)) x2 = np.argmax(np.max(sm_aug_arr[..., 1], axis=0)) y2 = np.argmax(np.max(sm_aug_arr[..., 1], axis=1)) # translation on x axis in polar representation should move all points # a bit away from the center min_diff = 4 assert sm_aug_arr.shape == (50, 70, 2) assert sm_aug.shape == (50, 70, 3) assert x1 < 30 - min_diff assert y1 < 20 - min_diff assert x2 > 40 + min_diff assert y2 > 30 + min_diff def test_keypoints_translation_x(self): cbas = [ia.Keypoint(y=20, x=30), ia.Keypoint(y=30, x=40)] cbaoi = ia.KeypointsOnImage(cbas, shape=(50, 70, 3)) aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 15})) cbaoi_aug = aug(keypoints=cbaoi) x1 = cbaoi_aug.items[0].x y1 = cbaoi_aug.items[0].y x2 = cbaoi_aug.items[1].x y2 = cbaoi_aug.items[1].y # translation on x axis in polar representation should move all points # a bit away from the center min_diff = 4 assert cbaoi_aug.shape == (50, 70, 3) assert x1 < 30 - min_diff assert y1 < 20 - min_diff assert x2 > 40 + min_diff assert y2 > 30 + min_diff def test_bounding_boxes_translation_x(self): cbas = [ia.BoundingBox(y1=20, x1=30, y2=20+2, x2=30+2), ia.BoundingBox(y1=30, x1=40, y2=30+2, x2=40+2)] cbaoi = ia.BoundingBoxesOnImage(cbas, shape=(50, 70, 3)) aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 15})) cbaoi_aug = aug(bounding_boxes=cbaoi) x1 = cbaoi_aug.items[0].x1 y1 = cbaoi_aug.items[0].y1 x2 = cbaoi_aug.items[1].x2 y2 = cbaoi_aug.items[1].y2 # translation on x axis in polar representation should move all points # a bit away from the center min_diff = 4 assert cbaoi_aug.shape == (50, 70, 3) assert x1 < 30 - min_diff assert y1 < 20 - min_diff assert x2 > 40 + min_diff assert y2 > 30 + min_diff def test_polygons_translation_x(self): cbas = [ia.Polygon([(30, 20), (30+2, 20), (30+2, 20+2)]), ia.Polygon([(40, 30), (40+2, 30), (40+2, 30+2)])] cbaoi = ia.PolygonsOnImage(cbas, shape=(50, 70, 3)) aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 15})) cbaoi_aug = aug(polygons=cbaoi) x1 = cbaoi_aug.items[0].coords[0][0] y1 = cbaoi_aug.items[0].coords[0][1] x2 = cbaoi_aug.items[1].coords[2][0] y2 = cbaoi_aug.items[1].coords[2][1] # translation on x axis in polar representation should move all points # a bit away from the center min_diff = 4 assert cbaoi_aug.shape == (50, 70, 3) assert x1 < 30 - min_diff assert y1 < 20 - min_diff assert x2 > 40 + min_diff assert y2 > 30 + min_diff def test_line_strings_translation_x(self): cbas = [ia.LineString([(30, 20), (30+2, 20), (30+2, 20+2)]), ia.LineString([(40, 30), (40+2, 30), (40+2, 30+2)])] cbaoi = ia.LineStringsOnImage(cbas, shape=(50, 70, 3)) aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 15})) cbaoi_aug = aug(line_strings=cbaoi) x1 = cbaoi_aug.items[0].coords[0][0] y1 = cbaoi_aug.items[0].coords[0][1] x2 = cbaoi_aug.items[1].coords[2][0] y2 = cbaoi_aug.items[1].coords[2][1] # translation on x axis in polar representation should move all points # a bit away from the center min_diff = 4 assert cbaoi_aug.shape == (50, 70, 3) assert x1 < 30 - min_diff assert y1 < 20 - min_diff assert x2 > 40 + min_diff assert y2 > 30 + min_diff def test_image_heatmap_alignment(self): image = np.zeros((80, 100, 3), dtype=np.uint8) image[40-10:40+10, 50-10:50+10, :] = 255 hm = np.zeros((40, 50, 1), dtype=np.float32) hm[20-5:20+5, 25-5:25+5, :] = 1.0 hm = ia.HeatmapsOnImage(hm, shape=image.shape) aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 10})) image_aug, hm_aug = aug(image=image, heatmaps=hm) hm_aug_arr = hm_aug.get_arr() hm_aug_arr_rs = ia.imresize_single_image(hm_aug_arr, (80, 100), interpolation="nearest") overlap = np.average( (image_aug[..., 0] > 200) == (hm_aug_arr_rs[..., 0] > 0.9) ) assert image_aug.shape == (80, 100, 3) assert hm_aug.shape == (80, 100, 3) assert hm_aug_arr.shape == (40, 50, 1) assert overlap > 0.96 def test_image_segmentation_map_alignment(self): image = np.zeros((80, 100, 3), dtype=np.uint8) image[40-10:40+10, 50-10:50+10, :] = 255 sm = np.zeros((40, 50, 1), dtype=np.int32) sm[20-5:20+5, 25-5:25+5, :] = 1 sm = ia.SegmentationMapsOnImage(sm, shape=image.shape) aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 10})) image_aug, sm_aug = aug(image=image, segmentation_maps=sm) sm_aug_arr = sm_aug.get_arr() sm_aug_arr_rs = ia.imresize_single_image(sm_aug_arr, (80, 100), interpolation="nearest") overlap = np.average( (image_aug[..., 0] > 200) == (sm_aug_arr_rs[..., 0] == 1) ) assert image_aug.shape == (80, 100, 3) assert sm_aug.shape == (80, 100, 3) assert sm_aug_arr.shape == (40, 50, 1) assert overlap > 0.96 def test_image_keypoint_alignment(self): image = np.zeros((80, 100, 3), dtype=np.uint8) image[40-10:40-10+3, 50-10:50-10+3, :] = 255 image[40+10:40+10+3, 50+10:50+10+3, :] = 255 kps = [ia.Keypoint(y=40-10+1.5, x=50-10+1.5), ia.Keypoint(y=40+10+1.5, x=50+10+1.5)] kpsoi = ia.KeypointsOnImage(kps, shape=image.shape) aug = iaa.WithPolarWarping(iaa.Affine(translate_px={"x": 10})) image_aug, kpsoi_aug = aug(image=image, keypoints=kpsoi) kp1 = kpsoi_aug.items[0] kp2 = kpsoi_aug.items[1] kp1_intensity = image_aug[int(kp1.y), int(kp1.x), 0] kp2_intensity = image_aug[int(kp2.y), int(kp2.x), 0] assert image_aug.shape == (80, 100, 3) assert kpsoi_aug.shape == (80, 100, 3) assert kp1_intensity > 200 assert kp2_intensity > 200 def test_image_is_noncontiguous(self): image = np.mod(np.arange(10*20*3), 255).astype(np.uint8) image = image.reshape((10, 20, 3)) image_cp = np.fliplr(np.copy(image)) image = np.fliplr(image) assert image.flags["C_CONTIGUOUS"] is False aug = iaa.WithPolarWarping(iaa.Noop()) image_aug = aug(image=image) avg_dist = np.average( np.abs( image_aug.astype(np.int32)[2:-2, 2:-2] - image_cp.astype(np.int32)[2:-2, 2:-2] ) ) assert image_aug.shape == (10, 20, 3) assert avg_dist < 7.0 def test_image_is_view(self): image = np.mod(np.arange(10*20*3), 255).astype(np.uint8) image = image.reshape((10, 20, 3)) image_cp = np.copy(image)[2:, 2:, :] image = image[2:, 2:, :] assert image.flags["OWNDATA"] is False aug = iaa.WithPolarWarping(iaa.Noop()) image_aug = aug(image=image) avg_dist = np.average( np.abs( image_aug.astype(np.int32)[2:-2, 2:-2] - image_cp.astype(np.int32)[2:-2, 2:-2] ) ) assert image_aug.shape == (8, 18, 3) assert avg_dist < 7.0 def test_propagation_hooks(self): image = np.mod(np.arange(30*30), 255).astype(np.uint8) image = image.reshape((30, 30)) aug = iaa.WithPolarWarping(iaa.Add(50)) def _propagator(images, augmenter, parents, default): return False if augmenter is aug else default hooks = ia.HooksImages(propagator=_propagator) observed1 = aug.augment_image(image) observed2 = aug.augment_image(image, hooks=hooks) image_plus50 = np.clip(image.astype(np.int32)+50, 0, 255) diff1 = np.abs(observed1[2:-2].astype(np.int32) - image_plus50[2:-2].astype(np.int32)) diff2 = np.abs(observed2[2:-2].astype(np.int32) - image_plus50[2:-2].astype(np.int32)) overlap_1_add = np.average(diff1 <= 1) overlap_2_add = np.average(diff2 <= 2) assert overlap_1_add >= 0.9 assert overlap_2_add < 0.01 def test_unusual_channel_numbers(self): with assertWarns(self, iaa.SuspiciousSingleImageShapeWarning): shapes = [ (5, 5, 4), (5, 5, 5), (5, 5, 512), (5, 5, 513) ] for shape in shapes: with self.subTest(shape=shape): image = np.zeros(shape, dtype=np.uint8) aug = iaa.WithPolarWarping(iaa.Noop()) image_aug = aug(image=image) shape_expected = tuple([shape[1], shape[0]] + list(shape[2:])) assert np.all(image_aug == 0) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape_expected 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) kpsoi = ia.KeypointsOnImage([ia.Keypoint(x=1, y=2)], shape=image.shape) sm_arr = np.zeros((3, 3), dtype=np.int32) sm_arr[1, 1] = 1 sm = ia.SegmentationMapsOnImage(sm_arr, shape=image.shape) aug = iaa.WithPolarWarping(iaa.Noop()) aug_det = aug.to_deterministic() image_aug = aug_det(image=image) kpsoi_aug = aug_det(keypoints=kpsoi) sm_aug = aug_det(segmentation_maps=sm) assert image_aug.dtype.name == "uint8" assert image_aug.shape == shape assert np.allclose(kpsoi_aug.to_xy_array(), kpsoi.to_xy_array()) assert kpsoi_aug.shape == shape assert np.array_equal(sm_aug.get_arr(), sm_arr) assert sm_aug.shape == shape def test_other_dtypes_bool(self): aug = iaa.WithPolarWarping(iaa.Noop()) arr = np.zeros((20, 20), dtype=bool) arr[10-3:10+3, 10-3:10+3] = True arr_aug = aug(image=arr) overlap = np.average(arr_aug == arr) assert arr_aug.shape == (20, 20) assert arr_aug.dtype.name == "bool" assert overlap > 0.95 def test_other_dtypes_uint_int(self): aug = iaa.WithPolarWarping(iaa.Noop()) dtypes = ["uint8", "uint16", "int8", "int16", "int32",] for dtype in dtypes: with self.subTest(dtype=dtype): min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) center_value = int(center_value) image = np.zeros((30, 10), dtype=dtype) image[0:10, :] = min_value image[10:20, :] = center_value image[20:30, :] = max_value image = iaa.pad(image, top=2, right=2, bottom=2, left=2, cval=0) image_aug = aug.augment_image(image) image_aug = image_aug[2:-2, 2:-2] overlap_min = np.average(image_aug[0:10] == min_value) overlap_cv = np.average(image_aug[10:20] == center_value) overlap_max = np.average(image_aug[20:30] == max_value) assert image_aug.dtype.name == dtype assert overlap_min > 0.9 assert overlap_cv > 0.9 assert overlap_max > 0.9 def test_other_dtypes_float(self): def _avg_close(arr_aug, expected_val): atol = 1e-8 return np.average(np.isclose(arr_aug, expected_val, rtol=0, atol=atol)) aug = iaa.WithPolarWarping(iaa.Noop()) dtypes = ["float16", "float32", "float64"] for dtype in dtypes: with self.subTest(dtype=dtype): min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) center_value = center_value image = np.zeros((70, 10), dtype=dtype) image[0:10, :] = min_value image[10:20, :] = center_value image[20:30, :] = max_value image[30:40, :] = -1.0 image[40:50, :] = 1.0 image[50:60, :] = -100.0 image[60:70, :] = 100.0 image = iaa.pad(image, top=2, right=2, bottom=2, left=2, cval=0) image_aug = aug.augment_image(image) image_aug = image_aug[2:-2, 2:-2] overlap1 = _avg_close(image_aug[0:10], min_value) overlap2 = _avg_close(image_aug[10:20], center_value) overlap3 = _avg_close(image_aug[20:30], max_value) overlap4 = _avg_close(image_aug[30:40], -1.0) overlap5 = _avg_close(image_aug[40:50], 1.0) overlap6 = _avg_close(image_aug[50:60], -100.0) overlap7 = _avg_close(image_aug[60:70], 100.0) assert image_aug.dtype.name == dtype assert overlap1 > 0.9 assert overlap2 > 0.9 assert overlap3 > 0.9 assert overlap4 > 0.9 assert overlap5 > 0.9 assert overlap6 > 0.9 assert overlap7 > 0.9 def test_get_parameters(self): aug = iaa.WithPolarWarping(iaa.Noop()) params = aug.get_parameters() assert len(params) == 0 def test_get_children_lists(self): children = iaa.Sequential([iaa.Noop()]) aug = iaa.WithPolarWarping(children) assert aug.get_children_lists() == [children] def test_to_deterministic(self): child = iaa.Identity() aug = iaa.WithPolarWarping([child]) aug_det = aug.to_deterministic() assert aug_det.deterministic assert aug_det.random_state is not aug.random_state assert aug_det.children.deterministic assert aug_det.children[0].deterministic def test___repr___and___str__(self): children = iaa.Sequential([iaa.Noop()]) aug = iaa.WithPolarWarping(children, name="WithPolarWarpingTest") expected = ( "WithPolarWarping(" "name=WithPolarWarpingTest, " "children=%s, " "deterministic=False" ")" % (str(children),)) assert aug.__repr__() == expected assert aug.__str__() == expected def test_pickleable(self): aug = iaa.WithPolarWarping( iaa.Affine(translate_px=(0, 10), seed=1), seed=2) runtest_pickleable_uint8_img(aug, iterations=5, shape=(25, 25, 1)) class Test_apply_jigsaw(unittest.TestCase): def test_no_movement(self): dtypes = [ "bool", "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "float16", "float32", "float64" ] try: dtypes.append(np.dtype("float128")) except TypeError: pass # float128 not known on system for dtype in dtypes: with self.subTest(dtype=dtype): arr = np.arange(20*20*1).reshape((20, 20, 1)) if dtype == "bool": mask = np.logical_or( arr % 4 == 0, arr % 7 == 0) arr[mask] = 1 arr[~mask] = 0 arr = arr.astype(dtype) min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) arr[0, 0] = min_value arr[0, 1] = max_value destinations = np.arange(5*5).reshape((5, 5)) observed = iaa.apply_jigsaw(arr, destinations) if arr.dtype.kind != "f": assert np.array_equal(observed, arr) else: atol = 1e-4 if dtype == "float16" else 1e-8 assert np.allclose(observed, arr, rtol=0, atol=atol) def test_no_movement_zero_sized_axes(self): sizes = [ (0, 1), (1, 0), (0, 0) ] dtype = "uint8" for size in sizes: with self.subTest(size=size): arr = np.zeros(size, dtype=dtype) destinations = np.arange(1*1).reshape((1, 1)) observed = iaa.apply_jigsaw(arr, destinations) assert np.array_equal(observed, arr) def _test_two_cells_moved__n_channels(self, nb_channels): dtypes = [ "bool", "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "float16", "float32", "float64" ] try: dtypes.append(np.dtype("float128").name) except TypeError: pass # float128 not known by user system for dtype in dtypes: with self.subTest(dtype=dtype): c = 1 if nb_channels is None else nb_channels arr = np.arange(20*20*c) if dtype == "bool": mask = np.logical_or( arr % 4 == 0, arr % 7 == 0) arr[mask] = 1 arr[~mask] = 0 if nb_channels is not None: arr = arr.reshape((20, 20, c)) else: arr = arr.reshape((20, 20)) arr = arr.astype(dtype) min_value, center_value, max_value = \ iadt.get_value_range_of_dtype(dtype) arr[0, 0] = min_value arr[0, 1] = max_value destinations = np.arange(5*5).reshape((5, 5)) destinations[0, 0] = 4 # cell 0 will be filled with 4 destinations[0, 4] = 0 # cell 4 will be filled with 0 destinations[0, 1] = 6 # cell 1 will be filled with 6 destinations[1, 1] = 1 # cell 6 will be filled with 1 observed = iaa.apply_jigsaw(arr, destinations) cell_0_obs = observed[0:4, 0:4] cell_0_exp = arr[0:4, 16:20] cell_4_obs = observed[0:4, 16:20] cell_4_exp = arr[0:4, 0:4] cell_1_obs = observed[0:4, 4:8] cell_1_exp = arr[4:8, 4:8] cell_6_obs = observed[4:8, 4:8] cell_6_exp = arr[0:4, 4:8] cell_2_obs = observed[0:4, 8:12] cell_2_exp = arr[0:4, 8:12] if arr.dtype.kind != "f": assert np.array_equal(cell_0_obs, cell_0_exp) assert np.array_equal(cell_4_obs, cell_4_exp) assert np.array_equal(cell_1_obs, cell_1_exp) assert np.array_equal(cell_6_obs, cell_6_exp) assert np.array_equal(cell_2_obs, cell_2_exp) else: atol = 1e-4 if dtype == "float16" else 1e-8 kwargs = {"rtol": 0, "atol": atol} assert np.allclose(cell_0_obs, cell_0_exp, **kwargs) assert np.allclose(cell_4_obs, cell_4_exp, **kwargs) assert np.allclose(cell_1_obs, cell_1_exp, **kwargs) assert np.allclose(cell_6_obs, cell_6_exp, **kwargs) assert np.allclose(cell_2_obs, cell_2_exp, **kwargs) assert observed.shape == arr.shape assert observed.dtype.name == dtype def test_two_cells_moved__no_channels(self): self._test_two_cells_moved__n_channels(None) def test_two_cells_moved__1_channel(self): self._test_two_cells_moved__n_channels(1) def test_two_cells_moved__3_channels(self): self._test_two_cells_moved__n_channels(3) class Test_apply_jigsaw_to_coords(unittest.TestCase): def test_no_movement(self): arr = np.float32([ (0.0, 0.0), (5.0, 5.0), (25.0, 50.5), (10.01, 21.0) ]) destinations = np.arange(10*10).reshape((10, 10)) observed = iaa.apply_jigsaw_to_coords(arr, destinations, (50, 100)) assert np.allclose(observed, arr) def test_with_movement(self): arr = np.float32([ (0.0, 0.0), # in cell (0,0) = idx 0 (5.0, 5.0), # in cell (0,0) = idx 0 (25.0, 50.5), # in cell (5,2) = idx 52 (10.01, 21.0) # in cell (2,1) = idx 12 ]) destinations = np.arange(10*10).reshape((10, 10)) destinations[0, 0] = 1 destinations[0, 1] = 0 destinations[5, 2] = 7 destinations[0, 7] = 52 observed = iaa.apply_jigsaw_to_coords(arr, destinations, (100, 100)) expected = np.float32([ (10.0, 0.0), (15.0, 5.0), (75.0, 0.5), (10.01, 21.0) ]) assert np.allclose(observed, expected) def test_with_movement_non_square_image(self): arr = np.float32([ (0.5, 0.6), # in cell (0,0) = idx 0 (180.7, 90.8), # in cell (9,9) = idx 99 ]) destinations = np.arange(10*10).reshape((10, 10)) destinations[0, 0] = 99 destinations[9, 9] = 0 observed = iaa.apply_jigsaw_to_coords(arr, destinations, (100, 200)) expected = np.float32([ (180+0.5, 90+0.6), (0+0.7, 0+0.8) ]) assert np.allclose(observed, expected) def test_empty_coords(self): arr = np.zeros((0, 2), dtype=np.float32) destinations = np.arange(10*10).reshape((10, 10)) observed = iaa.apply_jigsaw_to_coords(arr, destinations, (100, 100)) assert np.allclose(observed, arr) class Test_generate_jigsaw_destinations(unittest.TestCase): def test_max_steps_0(self): rng = iarandom.RNG(0) max_steps = 0 rows = 10 cols = 20 observed = iaa.generate_jigsaw_destinations(rows, cols, max_steps, rng, connectivity=8) assert np.array_equal( observed, np.arange(rows*cols).reshape((rows, cols))) def test_max_steps_1(self): rng = iarandom.RNG(0) max_steps = 1 rows = 10 cols = 20 observed = iaa.generate_jigsaw_destinations(rows, cols, max_steps, rng, connectivity=8) yy = (observed // cols).reshape((rows, cols)) xx = np.mod(observed, cols).reshape((rows, cols)) yy_expected = np.tile(np.arange(rows).reshape((rows, 1)), (1, cols)) xx_expected = np.tile(np.arange(cols).reshape((1, cols)), (rows, 1)) yy_diff = yy_expected - yy xx_diff = xx_expected - xx dist = np.sqrt(yy_diff ** 2 + xx_diff ** 2) assert np.min(dist) <= 0.01 assert np.any(dist >= np.sqrt(2) - 1e-4) assert np.max(dist) <= np.sqrt(2) + 1e-4 def test_max_steps_1_connectivity_4(self): rng = iarandom.RNG(0) max_steps = 1 rows = 10 cols = 20 observed = iaa.generate_jigsaw_destinations(rows, cols, max_steps, rng, connectivity=4) yy = (observed // cols).reshape((rows, cols)) xx = np.mod(observed, cols).reshape((rows, cols)) yy_expected = np.tile(np.arange(rows).reshape((rows, 1)), (1, cols)) xx_expected = np.tile(np.arange(cols).reshape((1, cols)), (rows, 1)) yy_diff = yy_expected - yy xx_diff = xx_expected - xx dist = np.sqrt(yy_diff ** 2 + xx_diff ** 2) assert np.min(dist) <= 0.01 assert np.any(dist >= 0.99) assert np.max(dist) <= 1.01 class TestJigsaw(unittest.TestCase): def setUp(self): reseed() def test___init___defaults(self): aug = iaa.Jigsaw(nb_rows=1, nb_cols=2) assert aug.nb_rows.value == 1 assert aug.nb_cols.value == 2 assert aug.max_steps.value == 1 assert aug.allow_pad is True def test___init___custom(self): aug = iaa.Jigsaw(nb_rows=1, nb_cols=2, max_steps=3, allow_pad=False) assert aug.nb_rows.value == 1 assert aug.nb_cols.value == 2 assert aug.max_steps.value == 3 assert aug.allow_pad is False def test__draw_samples(self): aug = iaa.Jigsaw(nb_rows=(1, 5), nb_cols=(1, 6), max_steps=(1, 3)) batch = mock.Mock() batch.nb_rows = 100 samples = aug._draw_samples(batch, iarandom.RNG(0)) assert len(np.unique(samples.nb_rows)) > 1 assert len(np.unique(samples.nb_cols)) > 1 assert len(np.unique(samples.max_steps)) > 1 assert np.all(samples.nb_rows >= 1) assert np.all(samples.nb_rows <= 5) assert np.all(samples.nb_cols >= 1) assert np.all(samples.nb_cols <= 6) assert np.all(samples.max_steps >= 1) assert np.all(samples.max_steps <= 3) all_same = True first = samples.destinations[0] for dest in samples.destinations: this_same = (dest.shape == first.shape and np.array_equal(dest, first)) all_same = all_same and this_same assert not all_same def test_images_without_shifts(self): aug = iaa.Jigsaw(nb_rows=2, nb_cols=2, max_steps=0) image = np.mod(np.arange(20*20*3), 255).astype(np.uint8) image = image.reshape((20, 20, 3)) image_aug = aug(image=image) assert image_aug.dtype.name == "uint8" assert image_aug.shape == (20, 20, 3) assert np.array_equal(image_aug, image) def test_heatmaps_without_shifts(self): aug = iaa.Jigsaw(nb_rows=2, nb_cols=2, max_steps=0) arr = np.linspace(0, 1.0, 20*20*1).astype(np.float32) arr = arr.reshape((20, 20, 1)) heatmap = ia.HeatmapsOnImage(arr, shape=(20, 20, 3)) heatmap_aug = aug(heatmaps=heatmap) assert heatmap_aug.shape == (20, 20, 3) assert np.allclose(heatmap_aug.arr_0to1, heatmap.arr_0to1) def test_segmaps_without_shifts(self): aug = iaa.Jigsaw(nb_rows=2, nb_cols=2, max_steps=0) arr = np.zeros((20, 20, 1), dtype=np.int32) arr[0:10, :] = 1 arr[10:20, 10:20] = 2 arr = arr.reshape((20, 20, 1)) segmap = ia.SegmentationMapsOnImage(arr, shape=(20, 20, 3)) segmap_aug = aug(segmentation_maps=segmap) assert segmap_aug.shape == (20, 20, 3) assert np.array_equal(segmap_aug.arr, segmap.arr) def test_keypoints_without_shifts(self): aug = iaa.Jigsaw(nb_rows=2, nb_cols=2, max_steps=0) kpsoi = ia.KeypointsOnImage.from_xy_array([ (0, 0), (5.5, 3.5), (12.1, 23.5) ], shape=(20, 20, 3)) kpsoi_aug = aug(keypoints=kpsoi) assert kpsoi_aug.shape == (20, 20, 3) assert np.allclose(kpsoi_aug.to_xy_array(), kpsoi.to_xy_array()) def test_images_with_shifts(self): # these rows/cols/max_steps parameters are mostly ignored due to the # mocked _draw_samples method below aug = iaa.Jigsaw(nb_rows=2, nb_cols=2, max_steps=1) image = np.mod(np.arange(19*19*3), 255).astype(np.uint8) image = image.reshape((19, 19, 3)) destinations = np.array([ [3, 1], [2, 0] ], dtype=np.int32) old_func = aug._draw_samples def _mocked_draw_samples(batch, random_state): samples = old_func(batch, random_state) return geometriclib._JigsawSamples( nb_rows=samples.nb_rows, nb_cols=samples.nb_cols, max_steps=samples.max_steps, destinations=[destinations]) aug._draw_samples = _mocked_draw_samples image_aug = aug(image=image) expected = iaa.pad(image, bottom=1, right=1, cval=0) expected = iaa.apply_jigsaw(expected, destinations) assert np.array_equal(image_aug, expected) def test_heatmaps_with_shifts(self): # these rows/cols/max_steps parameters are mostly ignored due to the # mocked _draw_samples method below aug = iaa.Jigsaw(nb_rows=2, nb_cols=2, max_steps=1) arr = np.linspace(0, 1.0, 18*18*1).astype(np.float32) arr = arr.reshape((18, 18, 1)) heatmap = ia.HeatmapsOnImage(arr, shape=(19, 19, 3)) destinations = np.array([ [3, 1], [2, 0] ], dtype=np.int32) old_func = aug._draw_samples def _mocked_draw_samples(batch, random_state): samples = old_func(batch, random_state) return geometriclib._JigsawSamples( nb_rows=samples.nb_rows, nb_cols=samples.nb_cols, max_steps=samples.max_steps, destinations=[destinations]) aug._draw_samples = _mocked_draw_samples heatmap_aug = aug(heatmaps=heatmap) expected = ia.imresize_single_image(arr, (19, 19), interpolation="cubic") expected = np.clip(expected, 0, 1.0) expected = iaa.pad(expected, bottom=1, right=1, cval=0.0) expected = iaa.apply_jigsaw(expected, destinations) expected = ia.imresize_single_image(expected, (18, 18), interpolation="cubic") expected = np.clip(expected, 0, 1.0) assert np.allclose(heatmap_aug.arr_0to1, expected) def test_segmaps_with_shifts(self): # these rows/cols/max_steps parameters are mostly ignored due to the # mocked _draw_samples method below aug = iaa.Jigsaw(nb_rows=2, nb_cols=2, max_steps=1) arr = np.zeros((18, 18, 1), dtype=np.int32) arr[0:10, :] = 1 arr[10:18, 10:18] = 2 arr = arr.reshape((18, 18, 1)) segmap = ia.SegmentationMapsOnImage(arr, shape=(19, 19, 3)) destinations = np.array([ [3, 1], [2, 0] ], dtype=np.int32) old_func = aug._draw_samples def _mocked_draw_samples(batch, random_state): samples = old_func(batch, random_state) return geometriclib._JigsawSamples( nb_rows=samples.nb_rows, nb_cols=samples.nb_cols, max_steps=samples.max_steps, destinations=[destinations]) aug._draw_samples = _mocked_draw_samples segmap_aug = aug(segmentation_maps=segmap) expected = ia.imresize_single_image(arr, (19, 19), interpolation="nearest") expected = iaa.pad(expected, bottom=1, right=1, cval=0) expected = iaa.apply_jigsaw(expected, destinations) expected = ia.imresize_single_image(expected, (18, 18), interpolation="nearest") assert np.array_equal(segmap_aug.arr, expected) def test_keypoints_with_shifts(self): # these rows/cols/max_steps parameters are mostly ignored due to the # mocked _draw_samples method below aug = iaa.Jigsaw(nb_rows=5, nb_cols=5, max_steps=1) kpsoi = ia.KeypointsOnImage.from_xy_array([ (0, 0), (5.5, 3.5), (4.0, 12.5), (11.1, 11.2), (12.1, 23.5) ], shape=(18, 18, 3)) destinations = np.array([ [3, 1], [2, 0] ], dtype=np.int32) old_func = aug._draw_samples def _mocked_draw_samples(batch, random_state): samples = old_func(batch, random_state) return geometriclib._JigsawSamples( nb_rows=samples.nb_rows, nb_cols=samples.nb_cols, max_steps=samples.max_steps, destinations=[destinations]) aug._draw_samples = _mocked_draw_samples kpsoi_aug = aug(keypoints=kpsoi) expected = kpsoi.deepcopy() expected.shape = (20, 20, 3) # (0.0, 0.0) to cell at bottom-right, 1px pad at top and left expected.keypoints[0].x = 10.0 + (0.0 - 0.0) + 1.0 expected.keypoints[0].y = 10.0 + (0.0 - 0.0) + 1.0 # (5.5, 3.5) to cell at bottom-right, 1px pad at top and left expected.keypoints[1].x = 10.0 + (5.5 - 0.0) + 1.0 expected.keypoints[1].y = 10.0 + (3.5 - 0.0) + 1.0 # (4.0, 12.5) not moved to other cell, but 1px pad at top and left expected.keypoints[2].x = 4.0 + 1.0 expected.keypoints[2].y = 12.5 + 1.0 # (11.0, 11.0) to cell at top-left, 1px pad at top and left expected.keypoints[3].x = 0.0 + (11.1 - 10.0) + 1.0 expected.keypoints[3].y = 0.0 + (11.2 - 10.0) + 1.0 # (12.1, 23.5) not moved to other cell, but 1px pad at top and left expected.keypoints[4].x = 12.1 + 1.0 expected.keypoints[4].y = 23.5 + 1.0 expected.shape = (20, 20, 3) assert kpsoi_aug.shape == (20, 20, 3) assert np.allclose(kpsoi_aug.to_xy_array(), expected.to_xy_array()) def test_images_and_heatmaps_aligned(self): nb_changed = 0 rs = iarandom.RNG(0) for _ in np.arange(10): aug = iaa.Jigsaw(nb_rows=(2, 5), nb_cols=(2, 5), max_steps=(0, 3)) image_small = rs.integers(0, 10, size=(10, 15)).astype(np.float32) image_small = image_small / 10.0 image = ia.imresize_single_image(image_small, (20, 30), interpolation="cubic") image = np.clip(image, 0, 1.0) hm = ia.HeatmapsOnImage(image_small, shape=(20, 30)) images_aug, hms_aug = aug(images=[image, image, image], heatmaps=[hm, hm, hm]) for image_aug, hm_aug in zip(images_aug, hms_aug): # TODO added squeeze here because get_arr() falsely returns # (H,W,1) for 2D inputs arr = np.squeeze(hm_aug.get_arr()) image_aug_rs = ia.imresize_single_image( image_aug.astype(np.float32), arr.shape[0:2], interpolation="cubic") image_aug_rs = np.clip(image_aug_rs, 0, 1.0) overlap = np.average(np.isclose(image_aug_rs, arr)) assert overlap > 0.99 if not np.array_equal(arr, hm.get_arr()): nb_changed += 1 assert nb_changed > 5 def test_images_and_segmaps_aligned(self): nb_changed = 0 rs = iarandom.RNG(0) for _ in np.arange(10): aug = iaa.Jigsaw(nb_rows=(2, 5), nb_cols=(2, 5), max_steps=(0, 3)) image_small = rs.integers(0, 10, size=(10, 15)) image = ia.imresize_single_image(image_small, (20, 30), interpolation="nearest") image = image.astype(np.uint8) segm = ia.SegmentationMapsOnImage(image_small, shape=(20, 30)) images_aug, sms_aug = aug(images=[image, image, image], segmentation_maps=[segm, segm, segm]) for image_aug, sm_aug in zip(images_aug, sms_aug): arr = sm_aug.get_arr() image_aug_rs = ia.imresize_single_image( image_aug, arr.shape[0:2], interpolation="nearest") overlap = np.average(image_aug_rs == arr) assert overlap > 0.99 if not np.array_equal(arr, segm.arr): nb_changed += 1 assert nb_changed > 5 def test_images_and_keypoints_aligned(self): for i in np.arange(20): aug = iaa.Jigsaw(nb_rows=(1, 3), nb_cols=(1, 3), max_steps=(2, 5), seed=i) # make sure that these coords are not exactly at a grid cell # border with any possibly sampled height/width in grid cells y = 17.5 x = 25.5 kpsoi = ia.KeypointsOnImage([ia.Keypoint(x=x, y=y)], shape=(20, 30)) image = np.zeros((20, 30), dtype=np.uint8) image[int(y), int(x)] = 255 images_aug, kpsois_aug = aug(images=[image, image, image], keypoints=[kpsoi, kpsoi, kpsoi]) for image_aug, kpsoi_aug in zip(images_aug, kpsois_aug): x_aug = kpsoi_aug.keypoints[0].x y_aug = kpsoi_aug.keypoints[0].y idx = np.argmax(image_aug) y_aug_img, x_aug_img = np.unravel_index(idx, image_aug.shape) dist = np.sqrt((x_aug - x_aug_img)**2 + (y_aug - y_aug_img)**2) # best possible distance is about 0.7 as KP coords are in cell # center and sampled coords are at cell top left assert dist < 0.8 def test_no_error_for_1x1_grids(self): aug = iaa.Jigsaw(nb_rows=1, nb_cols=1, max_steps=2) image = np.mod(np.arange(19*19*3), 255).astype(np.uint8) image = image.reshape((19, 19, 3)) kpsoi = ia.KeypointsOnImage.from_xy_array([ (0, 0), (5.5, 3.5), (4.0, 12.5), (11.1, 11.2), (12.1, 23.5) ], shape=(19, 19, 3)) image_aug, kpsoi_aug = aug(image=image, keypoints=kpsoi) assert np.array_equal(image_aug, image) assert np.allclose(kpsoi_aug.to_xy_array(), kpsoi.to_xy_array()) 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): for _ in sm.xrange(3): image = np.zeros(shape, dtype=np.uint8) aug = iaa.Jigsaw(nb_rows=2, nb_cols=2, max_steps=2) image_aug = aug(image=image) # (2, 2, [C]) here, because rows/cols are padded to be # multiple of nb_rows and nb_cols shape_exp = tuple([2, 2] + list(shape[2:])) assert image_aug.dtype.name == "uint8" assert np.array_equal(image_aug, np.zeros(shape_exp, dtype=np.uint8)) def test_get_parameters(self): aug = iaa.Jigsaw(nb_rows=1, nb_cols=2) params = aug.get_parameters() assert params[0] is aug.nb_rows assert params[1] is aug.nb_cols assert params[2] is aug.max_steps assert params[3] is True def test_pickleable(self): aug = iaa.Jigsaw(nb_rows=(1, 4), nb_cols=(1, 4), max_steps=(1, 3)) runtest_pickleable_uint8_img(aug, iterations=20, shape=(32, 32, 3))