0.3.0
0.3.0 - Summary Of Changes
Improved Segmentation Map Augmentation (#302)
The segmentation map augmentation was previously previously a wrapper
around heatmap augmentation. This patch introduces independent methods
for segmentation map augmentation. This makes the augmentation of such
inputs faster and more memory efficient. The internal representation (int
instead of floats) also becomes more intuitive.
This improvement leads to some breaking changes. To adapt to the new
version, the following steps should be sufficient for most users:
- Rename all calls of
SegmentationMapOnImagetoSegmentationMapsOnImage
(Map -> Maps). - Rename all calls of
SegmentationMapsOnImage.get_arr_int()to
SegmentationMapsOnImage.get_arr(). - Remove the argument
nb_classesfrom all calls ofSegmentationMapsOnImage. - Remove the argument
background_thresholdfrom all
calls as it is no longer supported. - Remove the argument
draw_foreground_maskfrom all calls of
SegmentationMapsOnImage.draw_on_image()as it is no longer supported. - Ensure that the input array to
SegmentationMapsOnImageis always an
int-like (int, uint or bool). Float arrays are now deprecated. - Adapt all calls
SegmentationMapsOnImage.draw()and
SegmentationMapsOnImage.draw_on_image(), as both of these now return a
list of drawn images instead of a single array. (For a segmentation map
array of shape(H,W,C)they returnCdrawn images. In most casesC=1,
so simply calldraw()[0]ordraw_on_image()[0].) - Ensure that if
SegmentationMapsOnImage.arris accessed anywhere, the
respective code can handle the newint32(H,W,#maps)array form.
Previously, it wasfloat32and the channel-axis had the same size as the
max class id (+1) that could appear in the map. - Ensure that calls of
<augmenter>.augment()or<augmenter>()that
provide segmentation maps as numpy arrays (i.e. bypassing
SegmentationMapsOnImage) use the shape(N,H,W,#maps)as
(N,H,W)is no longer supported.
New RNG System (#375, #408)
numpy 1.17 introduces a new API for random number generation. This patch
adapts imgaug to automatically use the new API if it is available and
fall back to the old one otherwise. To achieve that, the module
imgaug.random is introduced, containing the new standard random number
generator imgaug.random.RNG. You can create a new RNG using a seed value
via RNG(seed) and it will take care of the rest. It supports all sampling
functions that numpy.random.RandomState and numpy.random.Generator
support. This new random number generator is now supposed to be used
wherever previously numpy.random.RandomState would have been used.
(For most users, this shouldn't change anything. Integer seeds are
still supported. If you used RandomState anywhere, that is also still
supported.)
Breaking changes related to this patch:
- imgaug now uses a different seed at each run of the library. Previously,
a fixed seed was used for each run, leading to the same agumentations. That
confused some users as it differed from numpy's behaviour.
The new "dynamic" seed is derived from numpy's seed and hence seeding numpy
will also lead to imgaug being seeded. (It is not recommended to rely on
that behaviour as it might be changed in the future. Use
imgaug.random.seed()to set a custom seed.) - The constants
imgaug.SEED_MIN_VALUEandimgaug.SEED_MAX_VALUEwere
removed. They are now inimgaug.random. - The constant
imgaug.CURRENT_RANDOM_STATEwas removed.
Useimgaug.random.get_global_rng()instead.
Other Changes Related to numpy 1.17 (#302)
numpy 1.17 uses a new implementation of clip(), which turns int64 values
into float64 values. As a result, it is no longer safe to use int64 in
many augmenters and other functions/methods and hence these inputs are now
rejected. This affects at least ReplaceElementwise and thereby Dropout,
CoarseDropout, Salt, Pepper, SaltAndPepper, CoarseSalt,
CoarsePepper and CoarseSaltAndPepper. See the ReadTheDocs documentation
page about dtype support for more details.
In relation to this change, parameters in imgaug.parameters that previously
returned int64 were modified to now return int32 instead. Analogously,
float64 results were changed to float32.
New Augmenters
The following new augmenters were added to the library:
Canny edge detection (#316):
imgaug.augmenters.edges.Canny. Performs canny edge detection and colorizes
the resulting binary image in random ways.
Pooling (#317):
imgaug.augmenters.edges.AveragePooling. Performs average pooling using a
given kernel size. Very similar toAverageBlur.imgaug.augmenters.edges.MaxPooling. Performs maximum pooling using a
given kernel size.imgaug.augmenters.edges.MinPooling. Analogous.imgaug.augmenters.edges.MedianPooling. Analogous.
Hue and Saturation (#210, #319):
imgaug.augmenters.color.WithHueAndSaturation. Apply child augmenters to
images inHSVcolorspace. Automatically accounts for the hue being in
angular representation.imgaug.augmenters.color.AddToHue. Adds a defined value to the hue of each
pixel in input images.imgaug.augmenters.color.AddToSaturation. Adds a defined value to the
saturation of each pixel in input images.imgaug.augmenters.color.MultiplyHueAndSaturation. Multiplies the hue and/or
saturation of all pixels in input images.imgaug.augmenters.color.MultiplyHue. Analogous, affects always only the hue.imgaug.augmenters.color.MultiplySaturation. Analogous, affects always only
the saturation.
Color Quantization (#347):
imgaug.augmenters.color.UniformColorQuantization. Uniformly splits all
possible colors intoNdifferent ones, then finds for each pixel in an
image among theNcolors the most similar one and replaces that pixel's
color with the quantized color.imgaug.augmenters.color.KMeansColorQuantization. Groups all colors in an
each intoNdifferent ones using k-Means clustering. Then replaces each
pixel'S color, analogously toUniformColorQuantization.
Voronoi (#348):
imgaug.augmenters.segmentation.Voronoi. Queries a point sampler to
generate a large number of(x,y)coordinates on an image. Each such
coordinate becomes a voronoi cell. All pixels within the voronoi cell
are replaced by their average color. (Similar toSuperpixels, this
augmenter also supports to only replacep%of all cells with their
average color.)imgaug.augmenters.segmentation.UniformVoronoi. Shortcut to callVoronoi
with a uniform points sampler. That sampler placesNpoints on an image
using uniform distributions (i.e. they are randomly spread over the image.)imgaug.augmenters.segmentation.RegularGridVoronoi. Shortcut to call
Voronoiwith a regular grid points sampler. That points sampler generates
coordinate on a regular grid withHrows andWcols. Some of these points
can be randomly dropped to generate a less regular pattern.imgaug.augmenters.segmentation.RelativeRegularGridVoronoi. Same as
RegularGridVoronoi, but instead of using absolute numbers forHandW,
they are defined as relative amounts w.r.t. image shapes, leading to more
rows/cols on larger images.
New Augmentation Functions
One of the long term goals of the library is to move as much augmentation
logic as possible out of Augmenter instances and into functions. This
patch therefore adds several new augmentation functions:
imgaug.min_pool(). #369imgaug.median_pool(). #369augmenters.segmentation.segment_voronoi(). #348augmenters.flip.fliplr(). #385augmenters.flip.flipud(). #385augmenters.color.change_colorspace_(). #409augmenters.color.change_colorspace_batch_(). #409augmenters.arithmetic.add_scalar(). #411augmenters.arithmetic.add_elementwise(). #411augmenters.arithmetic.replace_elementwise_(). #411augmenters.arithmetic.compress_jpg(). #411
Colorspace Changes (#409)
The color space naming within the library had become rather messy in the
past as there were many colorspace-related augmenters, with some of them
not using constants for colorspace names/IDs and others defining their own
ones. This patch introduces a unified colorspace naming system for which the
following constants were added:
imgaug.CSPACE_RGBimgaug.CSPACE_BGRimgaug.CSPACE_GRAYimgaug.CSPACE_CIEimgaug.CSPACE_YCrCbimgaug.CSPACE_HSVimgaug.CSPACE_HLSimgaug.CSPACE_Labimgaug.CSPACE_Luvimgaug.CSPACE_YUVimgaug.CSPACE_ALL
All colorspace-related augmenters should now support these constants.
Additionally, support for rarely used colorspaces -- mainly CIE, YCrCb,
Luv and YUV -- was previously unverified or non-existent. These colorspaces
are now tested for the underlying transformation functions and should be
supported by most colorspace-related augmenters. (Some augmenters may still
define their own subset of actually sensible colorspaces and only accept
these.)
Setting limits on memory usage of background augmentation (#305, #417)
The methods imap_batches() and imap_batches_unordered() of
imgaug.multicore.Pool have now the new argument output_buffer_size.
The argument set the maximum number of batches that may be handled anywhere
in the augmentation pipeline at a given time (i.e. in the steps "loaded and
waiting", "in augmentation" or "augmented and waiting"). It denotes the
total number of batches over all processes. Setting this argument to
an integer value avoids situations where Pool eats up all the available
memory due to the data loading and augmentation running faster than the
training.
Augmenter.augment_batches() now uses a default value of 10*C
for output_buffer_size, where C is the number of available logical CPU
cores.
Performance Related Changes
The algorithms for Fliplr and Flipud were reworked to be as fast as
possible. In practice this should have no noticeable effects as both augmenters
were already very fast. (#385)
Furthermore, all assert statements within the library were changed from
do_assert() to standard assert statements. This is a bit less secure
(as assert statements can be optimized away), but should have a small
positive impact on the performance. (#387)
Large parts of the library were also refactored to reduce code duplication
and decrease the complexity of many functions. This should make future
improvements easier, but is expected to have a very small negative impact on
the performance due to an increased number of function calls.
It is also expected that numpy 1.17 can make some operations slower. This
is because (a) creating and copying random number generaters has become slower
and (b) clip() overall seems to be slower.
Improved Error Messages (#366, #367, #387)
imgaug uses quite many assert statements and other checks on input data
to fail early instead of late. This is supposed to improve usability, but that
goal was not always reached as many errors had no associated error
messages. This patch changes that. Now, all assert statements and other
checks have an associated error message. This should protect users from having
to wade through the library's code in order to understand the root cause of
errors.
(Almost) All Augmenters Are Now Classes (#396)
Some augmenters were previously defined as functions returning other
augmenters with appropriate settings. This could lead to confusing effects,
where seemingly instantiating an augmenters would lead to the instantiation
of a completely different augmenter. Hence, most of these augmenters were
switched from functions to classes. (The classes are now inheriting from the
previously returned augmenters, i.e. instanceof checks should still work.)
This affects: AdditiveGaussianNoise, AdditiveLaplaceNoise,
AdditivePoissonNoise, Dropout, CoarseDropout, ImpulseNoise,
SaltAndPepper, CoarseSaltAndPepper, Salt, CoarseSalt, Pepper,
CoarsePepper, SimplexNoiseAlpha, FrequencyNoiseAlpha, MotionBlur,
MultiplyHueAndSaturation, MultiplyHue, MultiplySaturation, AddToHue,
AddToSaturation, Grayscale, GammaContrast, SigmoidContrast,
LogContrast, LinearContrast, Sharpen, Emboss, EdgeDetect,
DirectedEdgeDetect, OneOf, AssertLambda, AssertShape, Pad, Crop,
Clouds, Fog and Snowflakes.
Not yet switched are: InColorspace (deprecated),
ContrastNormalization (deprecated), HorizontalFlip (pure alias
for Fliplr), VerticalFlip (pure alias for Flipud)
and Scale (deprecated).
Augmenters are now more robust towards unusual axis-sizes (#428, #433)
Feeding images with height and/or width of 0 or a channel axis of size 0
into augmenters would previously often result in crashes. This was also the
case for input arrays with more than 512 channels. Some of these errors
also included segmentation faults or endlessly hanging programs. Most
augmenters and helper functions were modified to be more robust towards
such unusual inputs and will no longer crash.
It is still good practice to avoid such inputs. Note e.g. that some helper
functions -- like drawing routines -- may still crash. The unittests
corresponding to this change also only cover image data. Using other inputs,
e.g. segmentation maps, might still induce problems.
Other New Functions
The following (public) functions were added to the library (not listing
functions that were already mentioned above):
- Added
imgaug.is_np_scalar(). #366 - Added
dtypes.normalize_dtypes(). #366 - Added
dtypes.normalize_dtype(). #366 - Added
dtypes.change_dtypes_(). #366 - Added
dtypes.change_dtype_(). #366 - Added
dtypes.increase_itemsize_of_dtype(). #366 - Added
imgaug.warn()function. #367 - Added
imgaug.compute_paddings_to_reach_multiples_of(). #369 - Added
imgaug.pad_to_multiples_of(). #369 - Added
augmentables.utils.copy_augmentables. #410 - Added
validation.convert_iterable_to_string_of_types(). #413 - Added
validation.is_iterable_of(). #413 - Added
validation.assert_is_iterable_of(). #413 - Added
random.supports_new_rng_style(). #375 - Added
random.get_global_rng(). #375 - Added
random.seed(). #375 - Added
random.normalize_generator(). #375 - Added
random.normalize_generator_(). #375 - Added
random.convert_seed_to_generator(). #375 - Added
random.convert_seed_sequence_to_generator(). #375 - Added
random.create_pseudo_random_generator_(). #375 - Added
random.create_fully_random_generator(). #375 - Added
random.generate_seed_(). #375 - Added
random.generate_seeds_(). #375 - Added
random.copy_generator(). #375 - Added
random.copy_generator_unless_global_generator(). #375 - Added
random.reset_generator_cache_(). #375 - Added
random.derive_generator_(). #375 - Added
random.derive_generators_(). #375 - Added
random.get_generator_state(). #375 - Added
random.set_generator_state_(). #375 - Added
random.is_generator_equal_to(). #375 - Added
random.advance_generator_(). #375 - Added
random.polyfill_integers(). #375 - Added
random.polyfill_random(). #375
Other New Classes and Interfaces
The following (public) classes were added (not listing classes that were
already mentioned above):
- Added
augmenters.edges.IBinaryImageColorizer. #316 - Added
augmenters.edges.RandomColorsBinaryImageColorizer. #316 - Added
augmenters.segmentation.IPointsSampler. #348 - Added
augmenters.segmentation.RegularGridPointsSampler. #348 - Added
augmenters.segmentation.RelativeRegularGridPointsSampler. #348 - Added
augmenters.segmentation.DropoutPointsSampler. #348 - Added
augmenters.segmentation.UniformPointsSampler. #348 - Added
augmenters.segmentation.SubsamplingPointsSampler. #348 - Added
testutils.ArgCopyingMagicMock. #413
The image colorization is used for Canny to turn binary images into color
images.
The points samplers are currently used within Voronoi.
Refactorings
Due to fast growth of the library in the past, a significant amount of messy
code had accumulated. To fix that, a lot of time was spend to refactor the code
throughout the whole library to reduce code duplication and improve the
general quality. This also included a rewrite of many outdated docstrings.
There is still quite some mess remaining, but the current state should make
it somewhat easier to add future improvements.
As part of the refactorings, a few humongously large unittests were also
split up into many smaller tests. The library has now around 3000
unique unittests (i.e. each unittest function is counted once, even it is
called many times with different parameters).
Related PRs:
- #302, #319, #328, #329, #330, #331, #332, #333, #334, #335, #336, #351,
#352, #353, #354, #355, #356, #359, #362, #366, #367, #368, #369, #389,
#397, #401, #402, #403, #407, #409, #410, #411, #413, #419
Deprecated
The following functions/classes/arguments are now deprecated:
- Function
imgaug.augmenters.meta.clip_augmented_image_.
Useimgaug.dtypes.clip_()ornumpy.clip()instead. #398 - Function
imgaug.augmenters.meta.clip_augmented_image.
Useimgaug.dtypes.clip_()ornumpy.clip()instead. #398 - Function
imgaug.augmenters.meta.clip_augmented_images_.
Useimgaug.dtypes.clip_()ornumpy.clip()instead. #398 - Function
imgaug.augmenters.meta.clip_augmented_images.
Useimgaug.dtypes.clip_()ornumpy.clip()instead. #398 - Function
imgaug.normalize_random_state.
Useimgaug.random.normalize_generatorinstead. #375 - Function
imgaug.current_random_state.
Useimgaug.random.get_global_rnginstead. #375 - Function
imgaug.new_random_state.
Use classimgaug.random.RNGinstead. #375 - Function
imgaug.dummy_random_state.
Useimgaug.random.RNG(1)instead. #375 - Function
imgaug.copy_random_state.
Useimgaug.random.copy_generatorinstead. - Function
imgaug.derive_random_state.
Useimgaug.random.derive_generator_instead. #375 - Function
imgaug.normalize_random_states.
Useimgaug.random.derive_generators_instead. #375 - Function
imgaug.forward_random_state.
Useimgaug.random.advance_generator_instead. #375 - Augmenter
imgaug.augmenters.arithmetic.ContrastNormalization.
Useimgaug.augmenters.contrast.LinearContrastinstead. #396 - Argument
Xinimgaug.augmentables.kps.compute_geometric_median().
Use argumentpointsinstead. #402 - Argument
cvalinimgaug.pool(),imgaug.avg_pool()and
imgaug.max_pool(). Usepad_cvalinstead. #369
Dependencies
The following changes were made to the dependencies of the library:
- Increased minimum version requirement for
scikit-imageto
0.14.2. #377, #399 - Changed dependency
opencv-pythontoopencv-python-headless.
This should improve support for some system without GUIs. #324 - Added dependency
pytest-subtestsfor the library's unittests. #366
conda-forge
The library was added to conda-forge so that it can now be installed via
conda install imgaug. (The conda-forge channel must be added first,
see installation docs or README.) #320 #339
Fixes
- Fixed an issue with
Polygon.clip_out_of_image(),
which would lead to exceptions if a polygon had overlap with an image,
but not a single one of its points was inside that image plane. - Fixed
multicoremethods falsely not accepting
augmentables.batches.UnnormalizedBatch. Rot90now uses subpixel-based coordinate remapping.
I.e. any coordinate(x, y)will be mapped to(H-y, x)for a rotation by
90deg.
Previously, an integer-based remapping to(H-y-1, x)was used.
Coordinates are e.g. used by keypoints, bounding boxes or polygons.augmenters.arithmetic.Invert- [rarely breaking] If
min_valueand/ormax_valuearguments were
set,uint64is no longer a valid input array dtype forInvert.
This is due to a conversion tofloat64resulting in loss of resolution. - Fixed
Invertin rare cases restoring dtypes improperly.
- [rarely breaking] If
- Fixed
dtypes.gate_dtypes()crashing if the input was one or more numpy
scalars instead of numpy arrays or dtypes. - Fixed
augmenters.geometric.PerspectiveTransformproducing invalid
polygons (more often with higherscalevalues). #338 - Fixed errors caused by
external/poly_point_isect_py2py3.pyrelated to
floating point inaccuracies (changed an epsilon from1e-10to1e-4,
rounded some floats). #338 - Fixed
Superpixelsbreaking when a sampledn_segmentswas<=0.
n_segmentsis now treated as1in these cases. - Fixed
ReplaceElementwiseboth allowing and disallowing dtypeint64. #346 - Fixed
BoundingBox.deepcopy()creating only shallow copies of labels. #356 - Fixed
dtypes.change_dtypes_()#366- Fixed argument
roundbeing ignored if input images were a list. - Fixed failure if input images were a list and dtypes a single numpy
dtype function.
- Fixed argument
- Fixed
dtypes.get_minimal_dtype()failing if argumentarrayscontained
not exactly two items. #366 - Fixed calls of
CloudLayer.get_parameters()resulting in errors. #309 - Fixed
SimplexNoiseAlphaandFrequencyNoiseAlphanot handling
sigmoidargument correctly. #343 - Fixed
SnowflakesLayercrashing for grayscale images. #345 - Fixed
Affineheatmap augmentation crashing for arrays with more than
four channels andorder!=0. #381 - Fixed an outdated error message in
Affine. #381 - Fixed
Polygon.clip_out_of_image()crashing if the intersection between
polygon and image plane was an edge or point. #382 - Fixed
Polygon.clip_out_of_image()potentially failing for polygons
containing two or fewer points. #382 - Fixed
Polygon.is_out_of_image()returning wrong values if the image plane
was fully contained inside the polygon with no intersection between the
image plane and the polygon edge. #382 - Fixed
FliplrandFlipudusing for coordinate-based inputs and image-like
inputs slightly different conditions for when to actually apply
augmentations. #385 - Fixed
Convolveusing an overly restrictive check when validating inputs
formatrixw.r.t. whether they are callables. The check should now also
support class methods (and possibly various other callables). #407 - Fixed
CropAndPad,PadandPadToFixedSizestill clippingcvalsamples
to theuint8. They now clip to the input array's dtype's value range. #407 - Fixed
WithColorspacenot propagating polygons to child augmenters. #409 - Fixed
WithHueAndSaturationnot propagating segmentation maps and polygons
to child augmenters. #409 - Fixed
AlphaElementwiseto blend coordinates (for keypoints, polygons,
line strings) on a point-by-point basis following the image's average
alpha value in the sampled alpha mask of the point's coordinate.
Previously, the average over the whole mask was used and then either all
points of the first branch or all of the second branch were used as the
augmentation output. This also affectsSimplexNoiseAlphaand
FrequencyNoiseAlpha. #410 - Fixed many augmenters and helper functions producing errors if the height,
width and/or channels of input arrays were exactly0or the channels
were>512. See further above for more details. #433 - Fixed
Rot90not supportingimgaug.ALL. #434 - Fixed
PiecewiseAffinepossibly generating samples for non-image data
when usingabsolute_scale=Truethat were not well aligned with the
corresponding images. #437