From 882512cf95b36b55fb4260316b9d0e2bbe501850 Mon Sep 17 00:00:00 2001 From: Alexander Jung Date: Sat, 25 Jan 2020 14:45:52 +0100 Subject: [PATCH] Improve default values of augmenters (#582) **[breaking]** Most augmenters had previously default values that made them equivalent to identity functions. Users had to explicitly change the defaults to proper values in order to "activate" augmentations. To simplify the usage of the library, the default values of most augmenters are changed in this patch to medium-strength augmentations. E.g. `Sequential([Affine(), UniformVoronoi(), CoarseDropout()])` should now produce decent augmentations. A few augmenters are set to always-on, maximum-strength augmentations. This is the case for: * `Grayscale` (always fully grayscales images, use `Grayscale((0.0, 1.0))` for random strengths) * `RemoveSaturation` (same as `Grayscale`) * `Fliplr` (always flips images, use `Fliplr(0.5)` for 50% probability) * `Flipud` (same as `Fliplr`) * `TotalDropout` (always drops everything, use `TotalDropout(0.1)` to drop everything for 10% of all images) * `Invert` (always inverts images, use `Invert(0.1)` to invert 10% of all images) * `Rot90` (always rotates exactly once clockwise by 90 degrees, use `Rot90((0, 3))` for any rotation) These settings seem to better match user-expectations. Such maximum-strength settings however are not chosen for all augmenters where one might expect them. The defaults are set to varying strengths for, e.g. `Superpixels` (replaces only some superpixels with cellwise average colors), `UniformVoronoi` (also only replaces some cells), `Sharpen` (alpha-blends with variable strength, the same is the case for `Emboss`, `EdgeDetect` and `DirectedEdgeDetect`) and `CLAHE` (variable clip limits). *Note*: Some of the new default values will cause issues with non-`uint8` inputs. *Note*: The defaults for `per_channel` and `keep_size` are not adjusted. It is currently still the default behaviour of all augmenters to affect all channels in the same way and to resize their outputs back to the input sizes. The exact changes to default values are listed below. **imgaug.arithmetic** * `Add` * `value`: `0` -> `(-20, 20)` * `AddElementwise` * `value`: `0` -> `(-20, 20)` * `AdditiveGaussianNoise` * `scale`: `0` -> `(0, 15)` * `AdditiveLaplaceNoise` * `scale`: `0` -> `(0, 15)` * `AdditivePoissonNoise` * `scale`: `0` -> `(0, 15)` * `Multiply` * `mul`: `1.0` -> `(0.8, 1.2)` * `MultiplyElementwise`: * `mul`: `1.0` -> `(0.8, 1.2)` * `Dropout`: * `p`: `0.0` -> `(0.0, 0.05)` * `CoarseDropout`: * `p`: `0.0` -> `(0.02, 0.1)` * `size_px`: `None` -> `(3, 8)` * `min_size`: `4` -> `3` * Default for `size_px` is only used if neither `size_percent` nor `size_px` is provided by the user. * `CoarseSaltAndPepper`: * `p`: `0.0` -> `(0.02, 0.1)` * `size_px`: `None` -> `(3, 8)` * `min_size`: `4` -> `3` * Default for `size_px` is only used if neither `size_percent` nor `size_px` is provided by the user. * `CoarseSalt`: * `p`: `0.0` -> `(0.02, 0.1)` * `size_px`: `None` -> `(3, 8)` * `min_size`: `4` -> `3` * Default for `size_px` is only used if neither `size_percent` nor `size_px` is provided by the user. * `CoarsePepper`: * `p`: `0.0` -> `(0.02, 0.1)` * `size_px`: `None` -> `(3, 8)` * `min_size`: `4` -> `3` * Default for `size_px` is only used if neither `size_percent` nor `size_px` is provided by the user. * `SaltAndPepper`: * `p`: `0.0` -> `(0.0, 0.03)` * `Salt`: * `p`: `0.0` -> `(0.0, 0.03)` * `Pepper`: * `p`: `0.0` -> `(0.0, 0.05)` * `ImpulseNoise`: * `p`: `0.0` -> `(0.0, 0.03)` * `Invert`: * `p`: `0` -> `1` * `JpegCompression`: * `compression`: `50` -> `(0, 100)` **imgaug.blend** * `BlendAlpha` * `factor`: `0` -> `(0.0, 1.0)` * `BlendAlphaElementwise` * `factor`: `0` -> `(0.0, 1.0)` **imgaug.blur** * `GaussianBlur`: * `sigma`: `0` -> `(0.0, 3.0)` * `AverageBlur`: * `k`: `1` -> `(1, 7)` * `MedianBlur`: * `k`: `1` -> `(1, 7)` * `BilateralBlur`: * `d`: `1` -> `(1, 9)` * `MotionBlur`: * `k`: `5` -> `(3, 7)` **imgaug.color** * `MultiplyHueAndSaturation`: * `mul_hue`: `None` -> `(0.5, 1.5)` * `mul_saturation`: `None` -> `(0.0, 1.7)` * These defaults are only used if the user provided neither `mul` nor `mul_hue` nor `mul_saturation`. * `MultiplyHue`: * `mul`: `(-1.0, 1.0)` -> `(-3.0, 3.0)` * `AddToHueAndSaturation`: * `value_hue`: `None` -> `(-40, 40)` * `value_saturation`: `None` -> `(-40, 40)` * These defaults are only used if the user provided neither `value` nor `value_hue` nor `value_saturation`. * `Grayscale`: * `alpha`: `0` -> `1` **imgaug.contrast** * `GammaContrast`: * `gamma`: `1` -> `(0.7, 1.7)` * `SigmoidContrast`: * `gain`: `10` -> `(5, 6)` * `cutoff`: `0.5` -> `(0.3, 0.6)` * `LogContrast`: * `gain`: `1` -> `(0.4, 1.6)` * `LinearContrast`: * `alpha`: `1` -> `(0.6, 1.4)` * `AllChannelsCLAHE`: * `clip_limit`: `40` -> `(0.1, 8)` * `tile_grid_size_px`: `8` -> `(3, 12)` * `CLAHE`: * `clip_limit`: `40` -> `(0.1, 8)` * `tile_grid_size_px`: `8` -> `(3, 12)` **convolutional** * `Sharpen`: * `alpha`: `0` -> `(0.0, 0.2)` * `lightness`: `1` -> `(0.8, 1.2)` * `Emboss`: * `alpha`: `0` -> `(0.0, 1.0)` * `strength`: `1` -> `(0.25, 1.0)` * `EdgeDetect`: * `alpha`: `0` -> `(0.0, 0.75)` * `DirectedEdgeDetect`: * `alpha`: `0` -> `(0.0, 0.75)` **imgaug.flip** * `Fliplr`: * `p`: `0` -> `1` * `Flipud`: * `p`: `0` -> `1` **imgaug.geometric** * `Affine`: * `scale`: `1` -> `{"x": (0.9, 1.1), "y": (0.9, 1.1)}` * `translate_percent`: None -> `{"x": (-0.1, 0.1), "y": (-0.1, 0.1)}` * `rotate`: `0` -> `(-15, 15)` * `shear`: `0` -> `shear={"x": (-10, 10), "y": (-10, 10)}` * These defaults are only used if no affine transformation parameter was set by the user. Otherwise the not-set parameters default again towards the identity function. * `PiecewiseAffine`: * `scale`: `0` -> `(0.0, 0.04)` * `nb_rows`: `4` -> `(2, 4)` * `nb_cols`: `4` -> `(2, 4)` * `PerspectiveTransform`: * `scale`: `0` -> `(0.0, 0.06)` * `ElasticTransformation`: * `alpha`: `0` -> `(0.0, 40.0)` * `sigma`: `0` -> `(4.0, 8.0)` * `Rot90`: * `k`: `(no default)` -> `k=1` **imgaug.pooling** * `AveragePooling`: * `k`: `(no default)` -> `(1, 5)` * `MaxPooling`: * `k`: `(no default)` -> `(1, 5)` * `MinPooling`: * `k`: `(no default)` -> `(1, 5)` * `MedianPooling`: * `k`: `(no default)` -> `(1, 5)` **imgaug.segmentation** * `Superpixels`: * `p_replace`: `0.0` -> `(0.5, 1.0)` * `n_segments`: `100` -> `(50, 120)` * `UniformVoronoi`: * `n_points`: `(no default)` -> `(50, 500)` * `p_replace`: `1.0` -> `(0.5, 1.0)`. * `RegularGridVoronoi`: * `n_rows`: `(no default)` -> `(10, 30)` * `n_cols`: `(no default)` -> `(10, 30)` * `p_drop_points`: `0.4` -> `(0.0, 0.5)` * `p_replace`: `1.0` -> `(0.5, 1.0)` * `RelativeRegularGridVoronoi`: Changed defaults from * `n_rows_frac`: `(no default)` -> `(0.05, 0.15)` * `n_cols_frac`: `(no default)` -> `(0.05, 0.15)` * `p_drop_points`: `0.4` -> `(0.0, 0.5)` * `p_replace`: `1.0` -> `(0.5, 1.0)` **imgaug.size** * `CropAndPad`: * `percent`: `None` -> `(-0.1, 0.1)` * This default is only used if the user has provided neither `px` nor `percent`. * `Pad`: * `percent`: `None` -> `(0.0, 0.1)` * This default is only used if the user has provided neither `px` nor `percent`. * `Crop`: * `percent`: `None` -> `(0.0, 0.1)` * This default is only used if the user has provided neither `px` nor `percent`. --- .../changed/20200115_changed_defaults.md | 242 ++++++++++++++++++ imgaug/augmenters/arithmetic.py | 80 +++--- imgaug/augmenters/blend.py | 4 +- imgaug/augmenters/blur.py | 10 +- imgaug/augmenters/color.py | 15 +- imgaug/augmenters/contrast.py | 15 +- imgaug/augmenters/convolutional.py | 8 +- imgaug/augmenters/flip.py | 4 +- imgaug/augmenters/geometric.py | 62 +++-- imgaug/augmenters/imgcorruptlike.py | 38 +-- imgaug/augmenters/pooling.py | 8 +- imgaug/augmenters/segmentation.py | 18 +- imgaug/augmenters/size.py | 9 + test/augmenters/test_arithmetic.py | 45 ++-- test/augmenters/test_color.py | 7 +- test/augmenters/test_geometric.py | 14 +- test/augmenters/test_segmentation.py | 2 - 17 files changed, 424 insertions(+), 157 deletions(-) create mode 100644 changelogs/master/changed/20200115_changed_defaults.md diff --git a/changelogs/master/changed/20200115_changed_defaults.md b/changelogs/master/changed/20200115_changed_defaults.md new file mode 100644 index 000000000..bf4c8df4d --- /dev/null +++ b/changelogs/master/changed/20200115_changed_defaults.md @@ -0,0 +1,242 @@ +# Better default values #582 + +**[breaking]** Most augmenters had previously default values that +made them equivalent to identity functions. Users had to explicitly +change the defaults to proper values in order to "activate" +augmentations. To simplify the usage of the library, the default +values of most augmenters were changed to medium-strength +augmentations. E.g. +`Sequential([Affine(), UniformVoronoi(), CoarseDropout()])` +should now produce decent augmentations. + +A few augmenters were set to always-on, maximum-strength +augmentations. This is the case for: + +* `Grayscale` (always fully grayscales images, use + `Grayscale((0.0, 1.0))` for random strengths) +* `RemoveSaturation` (same as `Grayscale`) +* `Fliplr` (always flips images, use `Fliplr(0.5)` for 50% + probability) +* `Flipud` (same as `Fliplr`) +* `TotalDropout` (always drops everything, use + `TotalDropout(0.1)` to drop everything for 10% of all images) +* `Invert` (always inverts images, use `Invert(0.1)` to invert + 10% of all images) +* `Rot90` (always rotates exactly once clockwise by 90 degrees, + use `Rot90((0, 3))` for any rotation) + +These settings seemed to better match user-expectations. +Such maximum-strength settings however were not chosen for all +augmenters where one might expect them. The defaults are set to +varying strengths for, e.g. `Superpixels` (replaces only some +superpixels with cellwise average colors), `UniformVoronoi` (also +only replaces some cells), `Sharpen` (alpha-blends with variable +strength, the same is the case for `Emboss`, `EdgeDetect` and +`DirectedEdgeDetect`) and `CLAHE` (variable clip limits). + +*Note*: Some of the new default values will cause issues with +non-`uint8` inputs. + +*Note*: The defaults for `per_channel` and `keep_size` were not +adjusted. It is currently still the default behaviour of all +augmenters to affect all channels in the same way and to resize +their outputs back to the input sizes. + +The exact changes to default values are listed below. + +**imgaug.arithmetic** + + * `Add` + * `value`: `0` -> `(-20, 20)` + * `AddElementwise` + * `value`: `0` -> `(-20, 20)` + * `AdditiveGaussianNoise` + * `scale`: `0` -> `(0, 15)` + * `AdditiveLaplaceNoise` + * `scale`: `0` -> `(0, 15)` + * `AdditivePoissonNoise` + * `scale`: `0` -> `(0, 15)` + * `Multiply` + * `mul`: `1.0` -> `(0.8, 1.2)` + * `MultiplyElementwise`: + * `mul`: `1.0` -> `(0.8, 1.2)` + * `Dropout`: + * `p`: `0.0` -> `(0.0, 0.05)` + * `CoarseDropout`: + * `p`: `0.0` -> `(0.02, 0.1)` + * `size_px`: `None` -> `(3, 8)` + * `min_size`: `4` -> `3` + * Default for `size_px` is only used if neither `size_percent` + nor `size_px` is provided by the user. + * `CoarseSaltAndPepper`: + * `p`: `0.0` -> `(0.02, 0.1)` + * `size_px`: `None` -> `(3, 8)` + * `min_size`: `4` -> `3` + * Default for `size_px` is only used if neither `size_percent` + nor `size_px` is provided by the user. + * `CoarseSalt`: + * `p`: `0.0` -> `(0.02, 0.1)` + * `size_px`: `None` -> `(3, 8)` + * `min_size`: `4` -> `3` + * Default for `size_px` is only used if neither `size_percent` + nor `size_px` is provided by the user. + * `CoarsePepper`: + * `p`: `0.0` -> `(0.02, 0.1)` + * `size_px`: `None` -> `(3, 8)` + * `min_size`: `4` -> `3` + * Default for `size_px` is only used if neither `size_percent` + nor `size_px` is provided by the user. + * `SaltAndPepper`: + * `p`: `0.0` -> `(0.0, 0.03)` + * `Salt`: + * `p`: `0.0` -> `(0.0, 0.03)` + * `Pepper`: + * `p`: `0.0` -> `(0.0, 0.05)` + * `ImpulseNoise`: + * `p`: `0.0` -> `(0.0, 0.03)` + * `Invert`: + * `p`: `0` -> `1` + * `JpegCompression`: + * `compression`: `50` -> `(0, 100)` + +**imgaug.blend** + + * `BlendAlpha` + * `factor`: `0` -> `(0.0, 1.0)` + * `BlendAlphaElementwise` + * `factor`: `0` -> `(0.0, 1.0)` + +**imgaug.blur** + + * `GaussianBlur`: + * `sigma`: `0` -> `(0.0, 3.0)` + * `AverageBlur`: + * `k`: `1` -> `(1, 7)` + * `MedianBlur`: + * `k`: `1` -> `(1, 7)` + * `BilateralBlur`: + * `d`: `1` -> `(1, 9)` + * `MotionBlur`: + * `k`: `5` -> `(3, 7)` + +**imgaug.color** + + * `MultiplyHueAndSaturation`: + * `mul_hue`: `None` -> `(0.5, 1.5)` + * `mul_saturation`: `None` -> `(0.0, 1.7)` + * These defaults are only used if the user provided neither + `mul` nor `mul_hue` nor `mul_saturation`. + * `MultiplyHue`: + * `mul`: `(-1.0, 1.0)` -> `(-3.0, 3.0)` + * `AddToHueAndSaturation`: + * `value_hue`: `None` -> `(-40, 40)` + * `value_saturation`: `None` -> `(-40, 40)` + * These defaults are only used if the user provided neither + `value` nor `value_hue` nor `value_saturation`. + * `Grayscale`: + * `alpha`: `0` -> `1` + +**imgaug.contrast** + + * `GammaContrast`: + * `gamma`: `1` -> `(0.7, 1.7)` + * `SigmoidContrast`: + * `gain`: `10` -> `(5, 6)` + * `cutoff`: `0.5` -> `(0.3, 0.6)` + * `LogContrast`: + * `gain`: `1` -> `(0.4, 1.6)` + * `LinearContrast`: + * `alpha`: `1` -> `(0.6, 1.4)` + * `AllChannelsCLAHE`: + * `clip_limit`: `40` -> `(0.1, 8)` + * `tile_grid_size_px`: `8` -> `(3, 12)` + * `CLAHE`: + * `clip_limit`: `40` -> `(0.1, 8)` + * `tile_grid_size_px`: `8` -> `(3, 12)` + +**convolutional** + + * `Sharpen`: + * `alpha`: `0` -> `(0.0, 0.2)` + * `lightness`: `1` -> `(0.8, 1.2)` + * `Emboss`: + * `alpha`: `0` -> `(0.0, 1.0)` + * `strength`: `1` -> `(0.25, 1.0)` + * `EdgeDetect`: + * `alpha`: `0` -> `(0.0, 0.75)` + * `DirectedEdgeDetect`: + * `alpha`: `0` -> `(0.0, 0.75)` + +**imgaug.flip** + + * `Fliplr`: + * `p`: `0` -> `1` + * `Flipud`: + * `p`: `0` -> `1` + +**imgaug.geometric** + + * `Affine`: + * `scale`: `1` -> `{"x": (0.9, 1.1), "y": (0.9, 1.1)}` + * `translate_percent`: None -> `{"x": (-0.1, 0.1), "y": (-0.1, 0.1)}` + * `rotate`: `0` -> `(-15, 15)` + * `shear`: `0` -> `shear={"x": (-10, 10), "y": (-10, 10)}` + * These defaults are only used if no affine transformation + parameter was set by the user. Otherwise the not-set + parameters default again towards the identity function. + * `PiecewiseAffine`: + * `scale`: `0` -> `(0.0, 0.04)` + * `nb_rows`: `4` -> `(2, 4)` + * `nb_cols`: `4` -> `(2, 4)` + * `PerspectiveTransform`: + * `scale`: `0` -> `(0.0, 0.06)` + * `ElasticTransformation`: + * `alpha`: `0` -> `(0.0, 40.0)` + * `sigma`: `0` -> `(4.0, 8.0)` + * `Rot90`: + * `k`: `(no default)` -> `k=1` + +**imgaug.pooling** + + * `AveragePooling`: + * `k`: `(no default)` -> `(1, 5)` + * `MaxPooling`: + * `k`: `(no default)` -> `(1, 5)` + * `MinPooling`: + * `k`: `(no default)` -> `(1, 5)` + * `MedianPooling`: + * `k`: `(no default)` -> `(1, 5)` + +**imgaug.segmentation** + + * `Superpixels`: + * `p_replace`: `0.0` -> `(0.5, 1.0)` + * `n_segments`: `100` -> `(50, 120)` + * `UniformVoronoi`: + * `n_points`: `(no default)` -> `(50, 500)` + * `p_replace`: `1.0` -> `(0.5, 1.0)`. + * `RegularGridVoronoi`: + * `n_rows`: `(no default)` -> `(10, 30)` + * `n_cols`: `(no default)` -> `(10, 30)` + * `p_drop_points`: `0.4` -> `(0.0, 0.5)` + * `p_replace`: `1.0` -> `(0.5, 1.0)` + * `RelativeRegularGridVoronoi`: Changed defaults from + * `n_rows_frac`: `(no default)` -> `(0.05, 0.15)` + * `n_cols_frac`: `(no default)` -> `(0.05, 0.15)` + * `p_drop_points`: `0.4` -> `(0.0, 0.5)` + * `p_replace`: `1.0` -> `(0.5, 1.0)` + +**imgaug.size** + + * `CropAndPad`: + * `percent`: `None` -> `(-0.1, 0.1)` + * This default is only used if the user has provided + neither `px` nor `percent`. + * `Pad`: + * `percent`: `None` -> `(0.0, 0.1)` + * This default is only used if the user has provided + neither `px` nor `percent`. + * `Crop`: + * `percent`: `None` -> `(0.0, 0.1)` + * This default is only used if the user has provided + neither `px` nor `percent`. diff --git a/imgaug/augmenters/arithmetic.py b/imgaug/augmenters/arithmetic.py index e4c1b19a5..f3469f956 100644 --- a/imgaug/augmenters/arithmetic.py +++ b/imgaug/augmenters/arithmetic.py @@ -1536,7 +1536,7 @@ class Add(meta.Augmenter): """ - def __init__(self, value=0, per_channel=False, + def __init__(self, value=(-20, 20), per_channel=False, seed=None, name=None, **old_kwargs): super(Add, self).__init__(seed=seed, name=name, **old_kwargs) @@ -1671,7 +1671,7 @@ class AddElementwise(meta.Augmenter): """ - def __init__(self, value=0, per_channel=False, + def __init__(self, value=(-20, 20), per_channel=False, seed=None, name=None, **old_kwargs): super(AddElementwise, self).__init__( seed=seed, name=name, **old_kwargs) @@ -1799,7 +1799,7 @@ class AdditiveGaussianNoise(AddElementwise): active for 50 percent of all images. """ - def __init__(self, loc=0, scale=0, per_channel=False, + def __init__(self, loc=0, scale=(0, 15), per_channel=False, seed=None, name=None, **old_kwargs): loc2 = iap.handle_continuous_param( loc, "loc", value_range=None, tuple_to_uniform=True, @@ -1815,6 +1815,7 @@ def __init__(self, loc=0, scale=0, per_channel=False, seed=seed, name=name, **old_kwargs) +# TODO add tests # TODO rename to AddLaplaceNoise? class AdditiveLaplaceNoise(AddElementwise): """ @@ -1912,7 +1913,7 @@ class AdditiveLaplaceNoise(AddElementwise): active for 50 percent of all images. """ - def __init__(self, loc=0, scale=0, per_channel=False, + def __init__(self, loc=0, scale=(0, 15), per_channel=False, seed=None, name=None, **old_kwargs): loc2 = iap.handle_continuous_param( loc, "loc", value_range=None, tuple_to_uniform=True, @@ -1929,6 +1930,7 @@ def __init__(self, loc=0, scale=0, per_channel=False, seed=seed, name=name, **old_kwargs) +# TODO add tests # TODO rename to AddPoissonNoise? class AdditivePoissonNoise(AddElementwise): """ @@ -1995,10 +1997,10 @@ class AdditivePoissonNoise(AddElementwise): parameter of ``5.0`` to images. The samples are drawn per image and pixel. - >>> aug = iaa.AdditivePoissonNoise(lam=(0.0, 10.0)) + >>> aug = iaa.AdditivePoissonNoise(lam=(0.0, 15.0)) Adds poisson noise sampled from ``Poisson(x)`` to images, where ``x`` is - randomly sampled per image from the interval ``[0.0, 10.0]``. + randomly sampled per image from the interval ``[0.0, 15.0]``. >>> aug = iaa.AdditivePoissonNoise(lam=5.0, per_channel=True) @@ -2006,19 +2008,19 @@ class AdditivePoissonNoise(AddElementwise): where the values are different per image and pixel *and* channel (e.g. a different one for red, green and blue channels for the same pixel). - >>> aug = iaa.AdditivePoissonNoise(lam=(0.0, 10.0), per_channel=True) + >>> aug = iaa.AdditivePoissonNoise(lam=(0.0, 15.0), per_channel=True) Adds poisson noise sampled from ``Poisson(x)`` to images, - with ``x`` being sampled from ``uniform(0.0, 10.0)`` per image and + with ``x`` being sampled from ``uniform(0.0, 15.0)`` per image and channel. This is the *recommended* configuration. - >>> aug = iaa.AdditivePoissonNoise(lam=(0.0, 10.0), per_channel=0.5) + >>> aug = iaa.AdditivePoissonNoise(lam=(0.0, 15.0), per_channel=0.5) Identical to the previous example, but the `per_channel` feature is only active for 50 percent of all images. """ - def __init__(self, lam=0, per_channel=False, + def __init__(self, lam=(0.0, 15.0), per_channel=False, seed=None, name=None, **old_kwargs): lam2 = iap.handle_continuous_param( lam, "lam", @@ -2101,7 +2103,7 @@ class Multiply(meta.Augmenter): """ - def __init__(self, mul=1.0, per_channel=False, + def __init__(self, mul=(0.8, 1.2), per_channel=False, seed=None, name=None, **old_kwargs): super(Multiply, self).__init__( seed=seed, name=name, **old_kwargs) @@ -2235,7 +2237,7 @@ class MultiplyElementwise(meta.Augmenter): """ - def __init__(self, mul=1.0, per_channel=False, + def __init__(self, mul=(0.8, 1.2), per_channel=False, seed=None, name=None, **old_kwargs): super(MultiplyElementwise, self).__init__( seed=seed, name=name, **old_kwargs) @@ -2695,7 +2697,7 @@ class Dropout(MultiplyElementwise): active for ``50`` percent of all images. """ - def __init__(self, p=0, per_channel=False, + def __init__(self, p=(0.0, 0.05), per_channel=False, seed=None, name=None, **old_kwargs): p_param = _handle_dropout_probability_param(p, "p") @@ -2740,8 +2742,7 @@ def _handle_dropout_probability_param(p, name): return p_param -# TODO add similar cutout augmenter -# TODO invert size_p and size_percent so that larger values denote larger +# TODO invert size_px and size_percent so that larger values denote larger # areas being dropped instead of the opposite way around class CoarseDropout(MultiplyElementwise): """ @@ -2886,8 +2887,8 @@ class CoarseDropout(MultiplyElementwise): for ``50`` percent of all images. """ - def __init__(self, p=0, size_px=None, size_percent=None, per_channel=False, - min_size=4, + def __init__(self, p=(0.02, 0.1), size_px=None, size_percent=None, + per_channel=False, min_size=3, seed=None, name=None, **old_kwargs): p_param = _handle_dropout_probability_param(p, "p") @@ -2900,7 +2901,11 @@ def __init__(self, p=0, size_px=None, size_percent=None, per_channel=False, size_percent=size_percent, min_size=min_size) else: - raise Exception("Either size_px or size_percent must be set.") + # default if neither size_px nor size_percent is provided + # is size_px=(3, 8) + p_param = iap.FromLowerResolution(other_param=p_param, + size_px=(3, 8), + min_size=min_size) super(CoarseDropout, self).__init__( p_param, @@ -2991,7 +2996,7 @@ class Dropout2d(meta.Augmenter): """ - def __init__(self, p, nb_keep_channels=1, + def __init__(self, p=0.1, nb_keep_channels=1, seed=None, name=None, **old_kwargs): super(Dropout2d, self).__init__( seed=seed, name=name, **old_kwargs) @@ -3164,7 +3169,7 @@ class TotalDropout(meta.Augmenter): """ - def __init__(self, p, seed=None, name=None, **old_kwargs): + def __init__(self, p=1, seed=None, name=None, **old_kwargs): super(TotalDropout, self).__init__( seed=seed, name=name, **old_kwargs) self.p = _handle_dropout_probability_param(p, "p") @@ -3451,7 +3456,7 @@ class SaltAndPepper(ReplaceElementwise): noise. """ - def __init__(self, p=0, per_channel=False, + def __init__(self, p=(0.0, 0.03), per_channel=False, seed=None, name=None, **old_kwargs): super(SaltAndPepper, self).__init__( mask=p, @@ -3505,7 +3510,7 @@ class ImpulseNoise(SaltAndPepper): Replace ``10%`` of all pixels with impulse noise. """ - def __init__(self, p=0, seed=None, name=None, **old_kwargs): + def __init__(self, p=(0.0, 0.03), seed=None, name=None, **old_kwargs): super(ImpulseNoise, self).__init__( p=p, per_channel=True, @@ -3634,8 +3639,8 @@ class CoarseSaltAndPepper(ReplaceElementwise): independently per image channel. """ - def __init__(self, p=0, size_px=None, size_percent=None, - per_channel=False, min_size=4, + def __init__(self, p=(0.02, 0.1), size_px=None, size_percent=None, + per_channel=False, min_size=3, seed=None, name=None, **old_kwargs): mask = iap.handle_probability_param( p, "p", tuple_to_uniform=True, list_to_choice=True) @@ -3647,7 +3652,8 @@ def __init__(self, p=0, size_px=None, size_percent=None, mask_low = iap.FromLowerResolution( other_param=mask, size_percent=size_percent, min_size=min_size) else: - raise Exception("Either size_px or size_percent must be set.") + mask_low = iap.FromLowerResolution( + other_param=mask, size_px=(3, 8), min_size=min_size) replacement = iap.Beta(0.5, 0.5) * 255 @@ -3715,7 +3721,7 @@ class Salt(ReplaceElementwise): """ - def __init__(self, p=0, per_channel=False, + def __init__(self, p=(0.0, 0.03), per_channel=False, seed=None, name=None, **old_kwargs): replacement01 = iap.ForceSign( iap.Beta(0.5, 0.5) - 0.5, @@ -3835,8 +3841,8 @@ class CoarseSalt(ReplaceElementwise): """ - def __init__(self, p=0, size_px=None, size_percent=None, per_channel=False, - min_size=4, + def __init__(self, p=(0.02, 0.1), size_px=None, size_percent=None, + per_channel=False, min_size=3, seed=None, name=None, **old_kwargs): mask = iap.handle_probability_param( p, "p", tuple_to_uniform=True, list_to_choice=True) @@ -3848,7 +3854,8 @@ def __init__(self, p=0, size_px=None, size_percent=None, per_channel=False, mask_low = iap.FromLowerResolution( other_param=mask, size_percent=size_percent, min_size=min_size) else: - raise Exception("Either size_px or size_percent must be set.") + mask_low = iap.FromLowerResolution( + other_param=mask, size_px=(3, 8), min_size=min_size) replacement01 = iap.ForceSign( iap.Beta(0.5, 0.5) - 0.5, @@ -3923,7 +3930,7 @@ class Pepper(ReplaceElementwise): """ - def __init__(self, p=0, per_channel=False, + def __init__(self, p=(0.0, 0.05), per_channel=False, seed=None, name=None, **old_kwargs): replacement01 = iap.ForceSign( iap.Beta(0.5, 0.5) - 0.5, @@ -4041,8 +4048,8 @@ class CoarsePepper(ReplaceElementwise): """ - def __init__(self, p=0, size_px=None, size_percent=None, per_channel=False, - min_size=4, + def __init__(self, p=(0.02, 0.1), size_px=None, size_percent=None, + per_channel=False, min_size=3, seed=None, name=None, **old_kwargs): mask = iap.handle_probability_param( p, "p", tuple_to_uniform=True, list_to_choice=True) @@ -4054,7 +4061,8 @@ def __init__(self, p=0, size_px=None, size_percent=None, per_channel=False, mask_low = iap.FromLowerResolution( other_param=mask, size_percent=size_percent, min_size=min_size) else: - raise Exception("Either size_px or size_percent must be set.") + mask_low = iap.FromLowerResolution( + other_param=mask, size_px=(3, 8), min_size=min_size) replacement01 = iap.ForceSign( iap.Beta(0.5, 0.5) - 0.5, @@ -4187,7 +4195,7 @@ class Invert(meta.Augmenter): ] ] - def __init__(self, p=0, per_channel=False, min_value=None, max_value=None, + def __init__(self, p=1, per_channel=False, min_value=None, max_value=None, threshold=None, invert_above_threshold=0.5, seed=None, name=None, **old_kwargs): super(Invert, self).__init__( @@ -4337,7 +4345,7 @@ class Solarize(Invert): per image. The thresholding operation happens per channel. """ - def __init__(self, p, per_channel=False, min_value=None, max_value=None, + def __init__(self, p=1, per_channel=False, min_value=None, max_value=None, threshold=(128-64, 128+64), invert_above_threshold=True, seed=None, name=None, **old_kwargs): super(Solarize, self).__init__( @@ -4479,7 +4487,7 @@ class JpegCompression(meta.Augmenter): setting of ``1`` to ``30``. """ - def __init__(self, compression=50, + def __init__(self, compression=(0, 100), seed=None, name=None, **old_kwargs): super(JpegCompression, self).__init__( seed=seed, name=name, **old_kwargs) diff --git a/imgaug/augmenters/blend.py b/imgaug/augmenters/blend.py index 324e47839..8cad13e03 100644 --- a/imgaug/augmenters/blend.py +++ b/imgaug/augmenters/blend.py @@ -385,7 +385,7 @@ class BlendAlpha(meta.Augmenter): """ - def __init__(self, factor=0, foreground=None, background=None, + def __init__(self, factor=(0.0, 1.0), foreground=None, background=None, per_channel=False, seed=None, name=None, **old_kwargs): super(BlendAlpha, self).__init__( @@ -889,7 +889,7 @@ class BlendAlphaElementwise(BlendAlphaMask): """ - def __init__(self, factor=0, foreground=None, background=None, + def __init__(self, factor=(0.0, 1.0), foreground=None, background=None, per_channel=False, seed=None, name=None, **old_kwargs): factor = iap.handle_continuous_param( diff --git a/imgaug/augmenters/blur.py b/imgaug/augmenters/blur.py index f0f713960..12f90f11d 100644 --- a/imgaug/augmenters/blur.py +++ b/imgaug/augmenters/blur.py @@ -433,7 +433,7 @@ class GaussianBlur(meta.Augmenter): """ - def __init__(self, sigma=0, + def __init__(self, sigma=(0.0, 3.0), seed=None, name=None, **old_kwargs): super(GaussianBlur, self).__init__( seed=seed, name=name, **old_kwargs) @@ -547,7 +547,7 @@ class AverageBlur(meta.Augmenter): """ - def __init__(self, k=1, seed=None, name=None, **old_kwargs): + def __init__(self, k=(1, 7), seed=None, name=None, **old_kwargs): super(AverageBlur, self).__init__( seed=seed, name=name, **old_kwargs) @@ -734,7 +734,7 @@ class MedianBlur(meta.Augmenter): """ - def __init__(self, k=1, seed=None, name=None, **old_kwargs): + def __init__(self, k=(1, 7), seed=None, name=None, **old_kwargs): super(MedianBlur, self).__init__( seed=seed, name=name, **old_kwargs) @@ -886,7 +886,7 @@ class BilateralBlur(meta.Augmenter): """ - def __init__(self, d=1, sigma_color=(10, 250), sigma_space=(10, 250), + def __init__(self, d=(1, 9), sigma_color=(10, 250), sigma_space=(10, 250), seed=None, name=None, **old_kwargs): # pylint: disable=invalid-name super(BilateralBlur, self).__init__( @@ -1019,7 +1019,7 @@ class MotionBlur(iaa_convolutional.Convolve): """ - def __init__(self, k=5, angle=(0, 360), direction=(-1.0, 1.0), order=1, + def __init__(self, k=(3, 7), angle=(0, 360), direction=(-1.0, 1.0), order=1, seed=None, name=None, **old_kwargs): # TODO allow (1, None) and set to identity matrix if k == 1 k_param = iap.handle_discrete_param( diff --git a/imgaug/augmenters/color.py b/imgaug/augmenters/color.py index 9192e1160..4aa0be997 100644 --- a/imgaug/augmenters/color.py +++ b/imgaug/augmenters/color.py @@ -1791,6 +1791,10 @@ class MultiplyHueAndSaturation(WithHueAndSaturation): def __init__(self, mul=None, mul_hue=None, mul_saturation=None, per_channel=False, from_colorspace="RGB", seed=None, name=None, **old_kwargs): + if mul is None and mul_hue is None and mul_saturation is None: + mul_hue = (0.5, 1.5) + mul_saturation = (0.0, 1.7) + if mul is not None: assert mul_hue is None, ( "`mul_hue` may not be set if `mul` is set. " @@ -1929,7 +1933,7 @@ class MultiplyHue(MultiplyHueAndSaturation): """ - def __init__(self, mul=(-1.0, 1.0), from_colorspace="RGB", + def __init__(self, mul=(-3.0, 3.0), from_colorspace="RGB", seed=None, name=None, **old_kwargs): super(MultiplyHue, self).__init__( mul_hue=mul, @@ -2040,7 +2044,7 @@ class RemoveSaturation(MultiplySaturation): Examples -------- >>> import imgaug.augmenters as iaa - >>> aug = iaa.RemoveSaturation() + >>> aug = iaa.RemoveSaturation((0.0, 1.0)) Create an augmenter that decreases saturation by varying degrees. @@ -2056,7 +2060,7 @@ class RemoveSaturation(MultiplySaturation): """ - def __init__(self, mul=(0.0, 1.0), from_colorspace=CSPACE_RGB, + def __init__(self, mul=1, from_colorspace=CSPACE_RGB, seed=None, name=None, **old_kwargs): mul = iap.Subtract( 1.0, @@ -2235,6 +2239,9 @@ def __init__(self, value=None, value_hue=None, value_saturation=None, seed=None, name=None, **old_kwargs): super(AddToHueAndSaturation, self).__init__( seed=seed, name=name, **old_kwargs) + if value is None and value_hue is None and value_saturation is None: + value_hue = (-40, 40) + value_saturation = (-40, 40) self.value = self._handle_value_arg(value, value_hue, value_saturation) self.value_hue = self._handle_value_hue_arg(value_hue) @@ -2831,7 +2838,7 @@ class Grayscale(ChangeColorspace): """ - def __init__(self, alpha=0, from_colorspace=CSPACE_RGB, + def __init__(self, alpha=1, from_colorspace=CSPACE_RGB, seed=None, name=None, **old_kwargs): super(Grayscale, self).__init__( to_colorspace=CSPACE_GRAY, diff --git a/imgaug/augmenters/contrast.py b/imgaug/augmenters/contrast.py index 4e3989b50..9ca3db0db 100644 --- a/imgaug/augmenters/contrast.py +++ b/imgaug/augmenters/contrast.py @@ -477,7 +477,7 @@ class GammaContrast(_ContrastFuncWrapper): """ - def __init__(self, gamma=1, per_channel=False, + def __init__(self, gamma=(0.7, 1.7), per_channel=False, seed=None, name=None, **old_kwargs): params1d = [iap.handle_continuous_param( gamma, "gamma", value_range=None, tuple_to_uniform=True, @@ -499,6 +499,9 @@ class SigmoidContrast(_ContrastFuncWrapper): Values in the range ``gain=(5, 20)`` and ``cutoff=(0.25, 0.75)`` seem to be sensible. + A combination of ``gain=5.5`` and ``cutof=0.45`` is fairly close to + the identity function. + Supported dtypes ---------------- @@ -564,7 +567,7 @@ class SigmoidContrast(_ContrastFuncWrapper): sampled once per image *and* channel. """ - def __init__(self, gain=10, cutoff=0.5, per_channel=False, + def __init__(self, gain=(5, 6), cutoff=(0.3, 0.6), per_channel=False, seed=None, name=None, **old_kwargs): # TODO add inv parameter? params1d = [ @@ -642,7 +645,7 @@ class LogContrast(_ContrastFuncWrapper): *and* channel. """ - def __init__(self, gain=1, per_channel=False, + def __init__(self, gain=(0.4, 1.6), per_channel=False, seed=None, name=None, **old_kwargs): # TODO add inv parameter? params1d = [iap.handle_continuous_param( @@ -712,7 +715,7 @@ class LinearContrast(_ContrastFuncWrapper): *and* channel. """ - def __init__(self, alpha=1, per_channel=False, + def __init__(self, alpha=(0.6, 1.4), per_channel=False, seed=None, name=None, **old_kwargs): params1d = [ iap.handle_continuous_param( @@ -949,7 +952,7 @@ class AllChannelsCLAHE(meta.Augmenter): """ - def __init__(self, clip_limit=40, tile_grid_size_px=8, + def __init__(self, clip_limit=(0.1, 8), tile_grid_size_px=(3, 12), tile_grid_size_px_min=3, per_channel=False, seed=None, name=None, **old_kwargs): super(AllChannelsCLAHE, self).__init__( @@ -1201,7 +1204,7 @@ class CLAHE(meta.Augmenter): HLS = color_lib.CSPACE_HLS Lab = color_lib.CSPACE_Lab - def __init__(self, clip_limit=40, tile_grid_size_px=8, + def __init__(self, clip_limit=(0.1, 8), tile_grid_size_px=(3, 12), tile_grid_size_px_min=3, from_colorspace=color_lib.CSPACE_RGB, to_colorspace=color_lib.CSPACE_Lab, diff --git a/imgaug/augmenters/convolutional.py b/imgaug/augmenters/convolutional.py index a1bde4d84..f401f43d8 100644 --- a/imgaug/augmenters/convolutional.py +++ b/imgaug/augmenters/convolutional.py @@ -290,7 +290,7 @@ class Sharpen(Convolve): (as in the above example). """ - def __init__(self, alpha=0, lightness=1, + def __init__(self, alpha=(0.0, 0.2), lightness=(0.8, 1.2), seed=None, name=None, **old_kwargs): alpha_param = iap.handle_continuous_param( alpha, "alpha", @@ -392,7 +392,7 @@ class Emboss(Convolve): using a random blending factor between ``0%`` and ``100%``. """ - def __init__(self, alpha=0, strength=1, + def __init__(self, alpha=(0.0, 1.0), strength=(0.25, 1.0), seed=None, name=None, **old_kwargs): alpha_param = iap.handle_continuous_param( alpha, "alpha", @@ -480,7 +480,7 @@ class EdgeDetect(Convolve): blending factor between ``0%`` and ``100%``. """ - def __init__(self, alpha=0, + def __init__(self, alpha=(0.0, 0.75), seed=None, name=None, **old_kwargs): alpha_param = iap.handle_continuous_param( alpha, "alpha", @@ -604,7 +604,7 @@ class DirectedEdgeDetect(Convolve): and ``30%``. """ - def __init__(self, alpha=0, direction=(0.0, 1.0), + def __init__(self, alpha=(0.0, 0.75), direction=(0.0, 1.0), seed=None, name=None, **old_kwargs): alpha_param = iap.handle_continuous_param( alpha, "alpha", diff --git a/imgaug/augmenters/flip.py b/imgaug/augmenters/flip.py index 1a91c80f5..c8764095e 100644 --- a/imgaug/augmenters/flip.py +++ b/imgaug/augmenters/flip.py @@ -861,7 +861,7 @@ class Fliplr(meta.Augmenter): """ - def __init__(self, p=0, seed=None, name=None, **old_kwargs): + def __init__(self, p=1, seed=None, name=None, **old_kwargs): super(Fliplr, self).__init__( seed=seed, name=name, **old_kwargs) self.p = iap.handle_probability_param(p, "p") @@ -962,7 +962,7 @@ class Flipud(meta.Augmenter): """ - def __init__(self, p=0, seed=None, name=None, **old_kwargs): + def __init__(self, p=1, seed=None, name=None, **old_kwargs): super(Flipud, self).__init__( seed=seed, name=name, **old_kwargs) self.p = iap.handle_probability_param(p, "p") diff --git a/imgaug/augmenters/geometric.py b/imgaug/augmenters/geometric.py index d52a111e7..ef11c8ad6 100644 --- a/imgaug/augmenters/geometric.py +++ b/imgaug/augmenters/geometric.py @@ -1149,13 +1149,24 @@ class Affine(meta.Augmenter): """ - def __init__(self, scale=1.0, translate_percent=None, translate_px=None, - rotate=0.0, shear=0.0, order=1, cval=0, mode="constant", + def __init__(self, scale=None, translate_percent=None, translate_px=None, + rotate=None, shear=None, order=1, cval=0, mode="constant", fit_output=False, backend="auto", seed=None, name=None, **old_kwargs): super(Affine, self).__init__( seed=seed, name=name, **old_kwargs) + params = [scale, translate_percent, translate_px, rotate, shear] + if all([p is None for p in params]): + scale = {"x": (0.9, 1.1), "y": (0.9, 1.1)} + translate_percent = {"x": (-0.1, 0.1), "y": (-0.1, 0.1)} + rotate = (-15, 15) + shear = {"x": (-10, 10), "y": (-10, 10)} + else: + scale = scale if scale is not None else 1.0 + rotate = rotate if rotate is not None else 0.0 + shear = shear if shear is not None else 0.0 + assert backend in ["auto", "skimage", "cv2"], ( "Expected 'backend' to be \"auto\", \"skimage\" or \"cv2\", " "got %s." % (backend,)) @@ -1559,7 +1570,7 @@ class ScaleX(Affine): """ - def __init__(self, scale, order=1, cval=0, mode="constant", + def __init__(self, scale=(0.5, 1.5), order=1, cval=0, mode="constant", fit_output=False, backend="auto", seed=None, name=None, **old_kwargs): super(ScaleX, self).__init__( @@ -1624,7 +1635,7 @@ class ScaleY(Affine): """ - def __init__(self, scale, order=1, cval=0, mode="constant", + def __init__(self, scale=(0.5, 1.5), order=1, cval=0, mode="constant", fit_output=False, backend="auto", seed=None, name=None, **old_kwargs): super(ScaleY, self).__init__( @@ -1702,11 +1713,9 @@ class TranslateX(Affine): def __init__(self, percent=None, px=None, order=1, cval=0, mode="constant", fit_output=False, backend="auto", seed=None, name=None, **old_kwargs): - # we don't test here if both are not-None at the same time, because - # that is already checked in Affine - assert percent is not None or px is not None, ( - "Expected either `percent` to be not-None or " - "`px` to be not-None, but both were None.") + if percent is None and px is None: + percent = (-0.25, 0.25) + super(TranslateX, self).__init__( translate_percent=({"x": percent} if percent is not None else None), translate_px=({"x": px} if px is not None else None), @@ -1783,11 +1792,9 @@ class TranslateY(Affine): def __init__(self, percent=None, px=None, order=1, cval=0, mode="constant", fit_output=False, backend="auto", seed=None, name=None, **old_kwargs): - # we don't test here if both are not-None at the same time, because - # that is already checked in Affine - assert percent is not None or px is not None, ( - "Expected either `percent` to be not-None or " - "`px` to be not-None, but both were None.") + if percent is None and px is None: + percent = (-0.25, 0.25) + super(TranslateY, self).__init__( translate_percent=({"y": percent} if percent is not None else None), translate_px=({"y": px} if px is not None else None), @@ -1849,7 +1856,7 @@ class Rotate(Affine): """ - def __init__(self, rotate, order=1, cval=0, mode="constant", + def __init__(self, rotate=(-30, 30), order=1, cval=0, mode="constant", fit_output=False, backend="auto", seed=None, name=None, **old_kwargs): super(Rotate, self).__init__( @@ -1904,7 +1911,7 @@ class ShearX(Affine): """ - def __init__(self, shear, order=1, cval=0, mode="constant", + def __init__(self, shear=(-30, 30), order=1, cval=0, mode="constant", fit_output=False, backend="auto", seed=None, name=None, **old_kwargs): super(ShearX, self).__init__( @@ -1959,7 +1966,7 @@ class ShearY(Affine): """ - def __init__(self, shear, order=1, cval=0, mode="constant", + def __init__(self, shear=(-30, 30), order=1, cval=0, mode="constant", fit_output=False, backend="auto", seed=None, name=None, **old_kwargs): super(ShearY, self).__init__( @@ -2856,8 +2863,9 @@ class PiecewiseAffine(meta.Augmenter): """ - def __init__(self, scale=0, nb_rows=4, nb_cols=4, order=1, cval=0, - mode="constant", absolute_scale=False, polygon_recoverer=None, + def __init__(self, scale=(0.0, 0.04), nb_rows=(2, 4), nb_cols=(2, 4), + order=1, cval=0, mode="constant", absolute_scale=False, + polygon_recoverer=None, seed=None, name=None, **old_kwargs): super(PiecewiseAffine, self).__init__( seed=seed, name=name, **old_kwargs) @@ -3383,8 +3391,8 @@ class PerspectiveTransform(meta.Augmenter): "constant": cv2.BORDER_CONSTANT } - def __init__(self, scale=0, cval=0, mode="constant", keep_size=True, - fit_output=False, polygon_recoverer="auto", + def __init__(self, scale=(0.0, 0.06), cval=0, mode="constant", + keep_size=True, fit_output=False, polygon_recoverer="auto", seed=None, name=None, **old_kwargs): super(PerspectiveTransform, self).__init__( seed=seed, name=name, **old_kwargs) @@ -4055,7 +4063,8 @@ class ElasticTransformation(meta.Augmenter): 5: cv2.INTER_CUBIC } - def __init__(self, alpha=0, sigma=0, order=3, cval=0, mode="constant", + def __init__(self, alpha=(0.0, 40.0), sigma=(4.0, 8.0), order=3, cval=0, + mode="constant", polygon_recoverer="auto", seed=None, name=None, **old_kwargs): super(ElasticTransformation, self).__init__( @@ -4703,7 +4712,7 @@ class Rot90(meta.Augmenter): """ - def __init__(self, k, keep_size=True, + def __init__(self, k=1, keep_size=True, seed=None, name=None, **old_kwargs): super(Rot90, self).__init__( seed=seed, name=name, **old_kwargs) @@ -5525,7 +5534,7 @@ class Jigsaw(meta.Augmenter): Parameters ---------- - nb_rows : int or list of int or tuple of int or imgaug.parameters.StochasticParameter + nb_rows : int or list of int or tuple of int or imgaug.parameters.StochasticParameter, optional How many rows the jigsaw pattern should have. * If a single ``int``, then that value will be used for all images. @@ -5536,7 +5545,7 @@ class Jigsaw(meta.Augmenter): * If ``StochasticParameter``, then that parameter is queried per image to sample the value to use. - nb_cols : int or list of int or tuple of int or imgaug.parameters.StochasticParameter + nb_cols : int or list of int or tuple of int or imgaug.parameters.StochasticParameter, optional How many cols the jigsaw pattern should have. * If a single ``int``, then that value will be used for all images. @@ -5592,7 +5601,8 @@ class Jigsaw(meta.Augmenter): """ - def __init__(self, nb_rows, nb_cols, max_steps=2, allow_pad=True, + def __init__(self, nb_rows=(3, 10), nb_cols=(3, 10), max_steps=1, + allow_pad=True, seed=None, name=None, **old_kwargs): super(Jigsaw, self).__init__( seed=seed, name=name, **old_kwargs) diff --git a/imgaug/augmenters/imgcorruptlike.py b/imgaug/augmenters/imgcorruptlike.py index 0d9219dba..d95c071b3 100644 --- a/imgaug/augmenters/imgcorruptlike.py +++ b/imgaug/augmenters/imgcorruptlike.py @@ -1050,7 +1050,7 @@ class GaussianNoise(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(GaussianNoise, self).__init__( apply_gaussian_noise, severity, @@ -1096,7 +1096,7 @@ class ShotNoise(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(ShotNoise, self).__init__( apply_shot_noise, severity, @@ -1142,7 +1142,7 @@ class ImpulseNoise(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(ImpulseNoise, self).__init__( apply_impulse_noise, severity, @@ -1188,7 +1188,7 @@ class SpeckleNoise(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(SpeckleNoise, self).__init__( apply_speckle_noise, severity, @@ -1234,7 +1234,7 @@ class GaussianBlur(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(GaussianBlur, self).__init__( apply_gaussian_blur, severity, @@ -1280,7 +1280,7 @@ class GlassBlur(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(GlassBlur, self).__init__( apply_glass_blur, severity, @@ -1326,7 +1326,7 @@ class DefocusBlur(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(DefocusBlur, self).__init__( apply_defocus_blur, severity, @@ -1372,7 +1372,7 @@ class MotionBlur(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(MotionBlur, self).__init__( apply_motion_blur, severity, @@ -1418,7 +1418,7 @@ class ZoomBlur(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(ZoomBlur, self).__init__( apply_zoom_blur, severity, @@ -1464,7 +1464,7 @@ class Fog(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(Fog, self).__init__( apply_fog, severity, @@ -1510,7 +1510,7 @@ class Frost(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(Frost, self).__init__( apply_frost, severity, @@ -1556,7 +1556,7 @@ class Snow(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(Snow, self).__init__( apply_snow, severity, @@ -1602,7 +1602,7 @@ class Spatter(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(Spatter, self).__init__( apply_spatter, severity, @@ -1648,7 +1648,7 @@ class Contrast(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(Contrast, self).__init__( apply_contrast, severity, @@ -1694,7 +1694,7 @@ class Brightness(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(Brightness, self).__init__( apply_brightness, severity, @@ -1740,7 +1740,7 @@ class Saturate(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(Saturate, self).__init__( apply_saturate, severity, @@ -1786,7 +1786,7 @@ class JpegCompression(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(JpegCompression, self).__init__( apply_jpeg_compression, severity, @@ -1832,7 +1832,7 @@ class Pixelate(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(Pixelate, self).__init__( apply_pixelate, severity, @@ -1882,7 +1882,7 @@ class ElasticTransform(_ImgcorruptAugmenterBase): """ - def __init__(self, severity=1, + def __init__(self, severity=(1, 5), seed=None, name=None, **old_kwargs): super(ElasticTransform, self).__init__( apply_elastic_transform, severity, diff --git a/imgaug/augmenters/pooling.py b/imgaug/augmenters/pooling.py index 58766d894..c497b5092 100644 --- a/imgaug/augmenters/pooling.py +++ b/imgaug/augmenters/pooling.py @@ -288,7 +288,7 @@ class AveragePooling(_AbstractPoolingBase): # TODO add floats as ksize denoting fractions of image sizes # (note possible overlap with fractional kernel sizes here) - def __init__(self, kernel_size, keep_size=True, + def __init__(self, kernel_size=(1, 5), keep_size=True, seed=None, name=None, **old_kwargs): super(AveragePooling, self).__init__( kernel_size=kernel_size, keep_size=keep_size, @@ -400,7 +400,7 @@ class MaxPooling(_AbstractPoolingBase): # TODO add floats as ksize denoting fractions of image sizes # (note possible overlap with fractional kernel sizes here) - def __init__(self, kernel_size, keep_size=True, + def __init__(self, kernel_size=(1, 5), keep_size=True, seed=None, name=None, **old_kwargs): super(MaxPooling, self).__init__( kernel_size=kernel_size, keep_size=keep_size, @@ -514,7 +514,7 @@ class MinPooling(_AbstractPoolingBase): # TODO add floats as ksize denoting fractions of image sizes # (note possible overlap with fractional kernel sizes here) - def __init__(self, kernel_size, keep_size=True, + def __init__(self, kernel_size=(1, 5), keep_size=True, seed=None, name=None, **old_kwargs): super(MinPooling, self).__init__( kernel_size=kernel_size, keep_size=keep_size, @@ -628,7 +628,7 @@ class MedianPooling(_AbstractPoolingBase): # TODO add floats as ksize denoting fractions of image sizes # (note possible overlap with fractional kernel sizes here) - def __init__(self, kernel_size, keep_size=True, + def __init__(self, kernel_size=(1, 5), keep_size=True, seed=None, name=None, **old_kwargs): super(MedianPooling, self).__init__( kernel_size=kernel_size, keep_size=keep_size, diff --git a/imgaug/augmenters/segmentation.py b/imgaug/augmenters/segmentation.py index 5b826ee65..d36207822 100644 --- a/imgaug/augmenters/segmentation.py +++ b/imgaug/augmenters/segmentation.py @@ -199,8 +199,8 @@ class Superpixels(meta.Augmenter): """ - def __init__(self, p_replace=0, n_segments=100, max_size=128, - interpolation="linear", + def __init__(self, p_replace=(0.5, 1.0), n_segments=(50, 120), + max_size=128, interpolation="linear", seed=None, name=None, **old_kwargs): super(Superpixels, self).__init__( seed=seed, name=name, **old_kwargs) @@ -743,7 +743,7 @@ class UniformVoronoi(Voronoi): """ - def __init__(self, n_points, p_replace=1.0, max_size=128, + def __init__(self, n_points=(50, 500), p_replace=(0.5, 1.0), max_size=128, interpolation="linear", seed=None, name=None, **old_kwargs): super(UniformVoronoi, self).__init__( @@ -897,7 +897,8 @@ class RegularGridVoronoi(Voronoi): """ - def __init__(self, n_rows, n_cols, p_drop_points=0.4, p_replace=1.0, + def __init__(self, n_rows=(10, 30), n_cols=(10, 30), + p_drop_points=(0.0, 0.5), p_replace=(0.5, 1.0), max_size=128, interpolation="linear", seed=None, name=None, **old_kwargs): super(RegularGridVoronoi, self).__init__( @@ -928,8 +929,8 @@ class RelativeRegularGridVoronoi(Voronoi): In contrast to the other voronoi augmenters, this one uses ``None`` as the default value for `max_size`, i.e. the color averaging is always performed at full resolution. This enables the augmenter to - make most use of the added points for larger images. It does however - slow down the augmentation process. + make use of the additional points on larger images. It does + however slow down the augmentation process. Supported dtypes ---------------- @@ -1069,8 +1070,9 @@ class RelativeRegularGridVoronoi(Voronoi): """ - def __init__(self, n_rows_frac, n_cols_frac, p_drop_points=0.4, - p_replace=1.0, max_size=None, interpolation="linear", + def __init__(self, n_rows_frac=(0.05, 0.15), n_cols_frac=(0.05, 0.15), + p_drop_points=(0.0, 0.5), p_replace=(0.5, 1.0), + max_size=None, interpolation="linear", seed=None, name=None, **old_kwargs): super(RelativeRegularGridVoronoi, self).__init__( points_sampler=DropoutPointsSampler( diff --git a/imgaug/augmenters/size.py b/imgaug/augmenters/size.py index 2e11c7402..286c75fe9 100644 --- a/imgaug/augmenters/size.py +++ b/imgaug/augmenters/size.py @@ -1764,6 +1764,9 @@ def __init__(self, px=None, percent=None, pad_mode="constant", pad_cval=0, super(CropAndPad, self).__init__( seed=seed, name=name, **old_kwargs) + if px is None and percent is None: + percent = (-0.1, 0.1) + self.mode, self.all_sides, self.top, self.right, self.bottom, \ self.left = self._handle_px_and_percent_args(px, percent) @@ -2334,6 +2337,9 @@ def recursive_validate(value): "Expected None or int or float or StochasticParameter or " "list or tuple, got %s." % (type(value),)) + if px is None and percent is None: + percent = (0.0, 0.1) + px = recursive_validate(px) percent = recursive_validate(percent) @@ -2508,6 +2514,9 @@ def recursive_negate(value): "Expected None or int or float or StochasticParameter or " "list or tuple, got %s." % (type(value),)) + if px is None and percent is None: + percent = (0.0, 0.1) + px = recursive_negate(px) percent = recursive_negate(percent) diff --git a/test/augmenters/test_arithmetic.py b/test/augmenters/test_arithmetic.py index 16213a8ad..41e957724 100644 --- a/test/augmenters/test_arithmetic.py +++ b/test/augmenters/test_arithmetic.py @@ -2450,12 +2450,9 @@ def test___init___bad_datatypes(self): assert got_exception def test___init___size_px_and_size_percent_both_none(self): - got_exception = False - try: - _ = iaa.CoarseDropout(p=0.5, size_px=None, size_percent=None) - except Exception: - got_exception = True - assert got_exception + aug = iaa.CoarseDropout(p=0.5, size_px=None, size_percent=None) + assert np.isclose(aug.mul.size_px.a.value, 3) + assert np.isclose(aug.mul.size_px.b.value, 8) def test_heatmaps_dont_change(self): # test heatmaps (not affected by augmenter) @@ -2475,9 +2472,9 @@ def setUp(self): reseed() def test___init___defaults(self): - aug = iaa.Dropout2d(p=0) + aug = iaa.Dropout2d() assert isinstance(aug.p, iap.Binomial) - assert np.isclose(aug.p.p.value, 1.0) + assert np.isclose(aug.p.p.value, 1-0.1) assert aug.nb_keep_channels == 1 def test___init___p_is_float(self): @@ -4590,12 +4587,10 @@ def test___init___bad_datatypes(self): got_exception = True assert got_exception - got_exception = False - try: - _ = iaa.CoarseSaltAndPepper(p=0.5, size_px=None, size_percent=None) - except Exception: - got_exception = True - assert got_exception + def test___init___size_px_and_size_percent_both_none(self): + aug = iaa.CoarseSaltAndPepper(p=0.5, size_px=None, size_percent=None) + assert np.isclose(aug.mask.size_px.a.value, 3) + assert np.isclose(aug.mask.size_px.b.value, 8) def test_heatmaps_dont_change(self): # test heatmaps (not affected by augmenter) @@ -4710,13 +4705,10 @@ def test___init___bad_datatypes(self): got_exception = True assert got_exception - def test_size_px_or_size_percent_not_none(self): - got_exception = False - try: - _ = iaa.CoarseSalt(p=0.5, size_px=None, size_percent=None) - except Exception: - got_exception = True - assert got_exception + def test___init___size_px_and_size_percent_both_none(self): + aug = iaa.CoarseSalt(p=0.5, size_px=None, size_percent=None) + assert np.isclose(aug.mask.size_px.a.value, 3) + assert np.isclose(aug.mask.size_px.b.value, 8) def test_heatmaps_dont_change(self): # test heatmaps (not affected by augmenter) @@ -4830,13 +4822,10 @@ def test___init___bad_datatypes(self): got_exception = True assert got_exception - def test_size_px_or_size_percent_not_none(self): - got_exception = False - try: - _ = iaa.CoarsePepper(p=0.5, size_px=None, size_percent=None) - except Exception: - got_exception = True - assert got_exception + def test___init___size_px_and_size_percent_both_none(self): + aug = iaa.CoarsePepper(p=0.5, size_px=None, size_percent=None) + assert np.isclose(aug.mask.size_px.a.value, 3) + assert np.isclose(aug.mask.size_px.b.value, 8) def test_heatmaps_dont_change(self): # test heatmaps (not affected by augmenter) diff --git a/test/augmenters/test_color.py b/test/augmenters/test_color.py index 33fed2683..762b5b28c 100644 --- a/test/augmenters/test_color.py +++ b/test/augmenters/test_color.py @@ -1335,8 +1335,7 @@ def test___init___defaults(self): multiply = aug.children[0].children[0] assert isinstance(multiply.mul, iap.Subtract) assert np.isclose(multiply.mul.other_param.value, 1.0) - assert np.isclose(multiply.mul.val.a.value, 0.0) - assert np.isclose(multiply.mul.val.b.value, 1.0) + assert np.isclose(multiply.mul.val.value, 1.0) assert aug.from_colorspace == iaa.CSPACE_RGB def test___init___custom(self): @@ -1462,8 +1461,8 @@ def test___init___value_none(self): def test___init___per_channel(self): aug = iaa.AddToHueAndSaturation(per_channel=0.5) assert aug.value is None - assert aug.value_hue is None - assert aug.value_saturation is None + assert aug.value_hue is not None + assert aug.value_saturation is not None assert isinstance(aug.per_channel, iap.Binomial) assert np.isclose(aug.per_channel.p.value, 0.5) diff --git a/test/augmenters/test_geometric.py b/test/augmenters/test_geometric.py index 7cfa3328d..1cad113a9 100644 --- a/test/augmenters/test_geometric.py +++ b/test/augmenters/test_geometric.py @@ -3122,9 +3122,9 @@ def test___init___translate_px(self): assert aug.fit_output is False def test___init___both_none(self): - with self.assertRaises(AssertionError) as ctx: - _aug = iaa.TranslateX() - assert "but both were None" in str(ctx.exception) + 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) @@ -3172,9 +3172,9 @@ def test___init___translate_px(self): assert aug.fit_output is False def test___init___both_none(self): - with self.assertRaises(AssertionError) as ctx: - _aug = iaa.TranslateY() - assert "but both were None" in str(ctx.exception) + 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) @@ -9736,7 +9736,7 @@ 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 == 2 + assert aug.max_steps.value == 1 assert aug.allow_pad is True def test___init___custom(self): diff --git a/test/augmenters/test_segmentation.py b/test/augmenters/test_segmentation.py index f0d5e7369..e47a1aa21 100644 --- a/test/augmenters/test_segmentation.py +++ b/test/augmenters/test_segmentation.py @@ -866,7 +866,6 @@ def test___init___integrationtest(self): seed=rs, name=None ) - assert np.isclose(aug.points_sampler.p_drop.p.value, 1-0.4) assert aug.points_sampler.other_points_sampler.n_rows.value == 10 assert isinstance(aug.points_sampler.other_points_sampler.n_cols, iap.DiscreteUniform) @@ -931,7 +930,6 @@ def test___init___integrationtest(self): ) ps = aug.points_sampler - assert np.isclose(aug.points_sampler.p_drop.p.value, 1-0.4) assert np.isclose(ps.other_points_sampler.n_rows_frac.value, 0.1) assert isinstance(ps.other_points_sampler.n_cols_frac, iap.Uniform) assert np.isclose(ps.other_points_sampler.n_cols_frac.a.value, 0.1)