10187 lines
384 KiB
Python
10187 lines
384 KiB
Python
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))
|