0.2.9
This update mainly covers the following topics:
- Moved classes/methods related to augmentable data to their own modules.
- Added polygon augmentation methods.
- Added line strings and line string augmentation methods.
- Added easier augmentation interface.
New 'augmentables' Modules
For the Polygon and Line String augmentation, new classes and methods had to be added. The previous file for that was imgaug/imgaug.py, which however was already fairly large. Therefore, all classes and methods related to augmentable data were split off and moved to imgaug/augmentables/<type>.py. The new modules and their main contents are:
imgaug.augmentables.batches: ContainsBatch,UnnormalizedBatch.imgaug.augmentables.utils: Contains utility functions.imgaug.augmentables.bbs: ContainsBoundingBox,BoundingBoxesOnImage.imgaug.augmentables.kps: ContainsKeypoint,KeypointsOnImage.imgaug.augmentables.polys: ContainsPolygon,PolygonsOnImage.imgaug.augmentables.lines: ContainsLineString,LineStringsOnImage.imgaug.augmentables.heatmaps: ContainsHeatmapsOnImage.imgaug.augmentables.segmaps: ContainsSegmentationMapOnImage.
Currently, all augmentable classes can still be created via imgaug.<type>, e.g. imgaug.BoundingBox still works.
Changes related to the new modules:
- Moved
Keypoint,KeypointsOnImageandimgaug.imgaug.compute_geometric_mediantoaugmentables/kps.py. - Moved
BoundingBox,BoundingBoxesOnImagetoaugmentables/bbs.py. - Moved
Polygon,PolygonsOnImageand related classes/functions toaugmentables/polys.py. - Moved
HeatmapsOnImagetoaugmentables/heatmaps.py. - Moved
SegmentationMapOnImagetoaugmentables/segmaps.py. - Moved
Batchtoaugmentables/batches.py. - Added module
imgaug.augmentables.utils.- Added function
normalize_shape(). - Added function
project_coords().
- Added function
- Moved line interpolation functions
_interpolate_points(),_interpolate_point_pair()and_interpolate_points_by_max_distance()toimgaug.augmentables.utilsand made them public functions. - Refactored
__init__()ofPolygonsOnImage,BoundingBoxesOnImage,KeypointsOnImageto make use ofimgaug.augmentables.utils.normalize_shape(). - Refactored
KeypointsOnImage.on()to useimgaug.augmentables.utils.normalize_shape(). - Refactored
Keypoint.project()to useimgaug.augmentables.utils.project_coords().
Polygon Augmentation
Polygons were already part of imgaug for quite a while, but couldn't be augmented yet. This version adds methods to perform such augmentations. It also makes some changes to the Polygon class, see the list of changes below.
Example for polygon augmentation:
import imgaug as ia
import imgaug.augmenters as iaa
from imgaug.augmentables.polys import Polygon, PolygonsOnImage
image = ia.quokka(size=0.2)
psoi = PolygonsOnImage([
Polygon([(0, 0), (20, 0), (20, 20)])
], shape=image.shape)
image_aug, psoi_aug = iaa.Affine(rotate=45).augment(
images=[image],
polygons=[psoi]
)See imgaug-doc/notebooks for a jupyter notebook with many more examples.
Changes related to polygon augmentation:
- Added
_ConcavePolygonRecoverertoimgaug.augmentables.polys. - Added
PolygonsOnImagetoimgaug.augmentables.polys. - Added polygon augmentation methods:
- Added
augment_polygons()toAugmenter. - Added
_augment_polygons()toAugmenter. - Added
_augment_polygons_as_keypoints()toAugmenter. - Added argument
polygonstoimgaug.augmentables.batches.Batch. - Added attributes
polygons_augandpolygons_unaugtoimgaug.augmentables.batches.Batch. - Added polygon handling to
Augmenter.augment_batches().
- Added
- Added property
Polygon.height. - Added property
Polygon.width. - Added method
Polygon.to_keypoints(). - Added optional drawing of corner points to
Polygon.draw_on_image()andPolygonsOnImage.draw_on_image(). - Added argument
raise_if_too_far_away=TruetoPolygon.change_first_point_by_coords(). - Added
imgaug.quokka_polygons()function to generate example polygon data. - [rarely breaking]
Polygon.draw_on_image(),PolygonsOnImage.draw_on_image()- Refactored to make partial use
LineStringmethods. - Added arguments
sizeandsize_perimeterto control polygon line thickness. - Renamed arguments
alpha_perimetertoalpha_line,color_perimetertocolor_lineto align withLineStrings. - Renamed arguments
alpha_filltoalpha_faceandcolor_filltocolor_face.
- Refactored to make partial use
- [rarely breaking] Changed the output of
Polygon.clip_out_of_image()fromMultiPolygontolistofPolygon.
This breaks for anybody who has already usedPolygon.clip_out_of_image(). - Changed
Polygon.exterior_almost_equals()to accept lists of tuples as argumentother_polygon. - Changed arguments
colorandalphainPolygon.draw_on_image()andPolygonsOnImage.draw_on_image()to represent
the general color and alpha of the polygon. The colors/alphas of the inner area, perimeter and points are derived from
colorandalpha(unlesscolor_inner,color_perimeterorcolor_pointsare set (analogous for alpha)). - Refactored
Polygon.project()to useLineString.project(). - Refactored
Polygon.shift()to useLineString.shift(). - [rarely breaking]
Polygon.exterior_almost_equals(),Polygon.almost_equals()- Refactored to make use of
LineString.coords_almost_equals(). - Renamed argument
interpolatetopoints_per_edge. - Renamed argument
other_polygontoother.
- Refactored to make use of
- Renamed
color_linetocolor_lines,alpha_linetoalpha_linesinPolygon.draw_on_image()andPolygonsOnImage.draw_on_image(). - Fixed
Polygon.clip_out_of_image(image)not handlingimagebeing a tuple. - Fixed
Polygon.is_out_of_image()falsely only checking the corner points of the polygon.
LineString Augmentation
This version adds Line String augmentation. Line Strings are simply lines made up of consecutive corner points that are connected by straight lines. Line strings have similarity with polygons, but do not have a filled inner area and are not closed (i.e. first and last coordinate differ).
Similar to other augmentables, line string are represented with the classes LineString(<iterable of xy-coords>) and LineStringsOnImage(<iterable of LineString>, <shape of image>). They are augmented e.g. via Augmenter.augment_line_strings(<iterable of LineStringsOnImage>) or Augmenter.augment(images=..., line_strings=...).
Example:
import imgaug as ia
import imgaug.augmenters as iaa
from imgaug.augmentables.lines import LineString, LineStringsOnImage
image = ia.quokka(size=0.2)
lsoi = LineStringsOnImage([
LineString([(0, 0), (20, 0), (20, 20)])
], shape=image.shape)
image_aug, lsoi_aug = iaa.Affine(rotate=45).augment(
images=[image],
line_strings=[lsoi]
)See imgaug-doc/notebooks for a jupyter notebook with many more examples.
Simplified Augmentation Interface
Augmentation of different data corresponding to the same image(s) has been a bit convoluted in the past, as each data type had to be augmented on its own. E.g. to augment an image and its bounding boxes, one had to first switch the augmenters to deterministic mode, then augment the images, then the bounding boxes. This version adds methods that perform these steps in one call. Specifically, Augmenter.augment(...) is used for that, which has the alias Augmenter.__call__(...). One argument can be used for each augmentable, e.g. bounding_boxes=<bounding box data>.
Example:
import imgaug as ia
import imgaug.augmenters as iaa
from imgaug.augmentables.kps import Keypoint, KeypointsOnImage
image = ia.quokka(size=0.2)
kpsoi = KeypointsOnImage([Keypoint(x=0, y=10), Keypoint(x=10, y=5)],
shape=image.shape)
image_aug, kpsoi_aug = iaa.Affine(rotate=(-45, 45)).augment(
image=image,
keypoints=kpsoi
)This will automatically make sure that image and keypoints are rotated by corresponding amounts.
Normalization methods have been added to that class, which allow it to process many more different inputs than just variations of *OnImage.
Example:
import imgaug as ia
import imgaug.augmenters as iaa
image = ia.quokka(size=0.2)
kps = [(0, 10), (10, 5)]
image_aug, kps_aug = iaa.Affine(rotate=(-45, 45)).augment(
image=image, keypoints=kps)Examples for other inputs that are automatically handled by augment():
- Integer arrays as segmentation maps.
- Float arrays for heatmaps.
list([N,4] ndarray)for bounding boxes. (One list for images,
thenNbounding boxes in(x1,y1,x2,y2)form.)list(list(list(tuple)))for line strings. (One list for images,
one list for line strings on the image, one list for coordinates within
the line string. Each tuple must contain two values for xy-coordinates.)list(list(imgaug.augmentables.polys.Polygon))for polygons.
Note that this "skips"imgaug.augmentables.polys.PolygonsOnImage.
In python <3.6, augment() is limited to a maximum of two inputs/outputs and if two inputs/outputs are used, then one of them must be image data and such (augmented) image data will always be returned first,
independent of the argument's order. E.g. augment(line_strings=<data>, polygons=<data>) would be invalid due to not containing image data. augment(polygons=<data>, images=<data>) would still return the images first, even though they are the second argument.
In python >=3.6, augment() may be called with more than two arguments and will respect their order.
Example:
import numpy as np
import imgaug as ia
import imgaug.augmenters as iaa
image = ia.quokka(size=0.2)
kps = [(0, 10), (10, 5)]
heatmap = np.zeros((image.shape[0], image.shape[1]), dtype=np.float32)
rotate = iaa.Affine(rotate=(-45, 45))
heatmaps_aug, images_aug, kps_aug = rotate(
heatmaps=[heatmap],
images=[image],
keypoints=[kps]
)To use more than two inputs/outputs in python <3.6, add the argument return_batch=True, which will return an instance of imgaug.augmentables.batches.UnnormalizedBatch.
Changes related to the augmentation interface:
- Added
Augmenter.augment()method. - Added
Augmenter.augment_batch()method.- This method is now called by
Augmenter.augment_batches()and multicore routines.
- This method is now called by
- Added
imgaug.augmentables.batches.UnnormalizedBatch. - Added module
imgaug.augmentables.normalizationfor data normalization routines. - Changed
augment_batches():- Accepts now
UnnormalizedBatchas input. It is automatically normalized before augmentation and unnormalized afterwards.
This allows to useBatchinstances with non-standard datatypes. - Accepts now single instances of
Batch(andUnnormalizedBatch). - The input may now also be a generator.
- The input may now be any iterable instead of just list (arrays or strings are not allowed).
- Accepts now
- Marked support for non-
Batch(and non-UnnormalizedBatch) inputs toaugment_batches()as deprecated. - Refactored
Batch.deepcopy()- Does no longer verify attribute datatypes.
- Allows now to directly change attributes of created copies, e.g. via
batch.deepcopy(images_aug=...).
Other Additions, Changes and Refactorings
Keypoint augmentation
- Added method
Keypoint.draw_on_image(). - [mildly breaking] Added an
alphaargument toKeypointsOnImage.draw_on_image(). This can break code that relied on the order of arguments of the method (though will usually only have visual consequences). KeypointsOnImageandKeypointcopying:- Added optional arguments
keypointsandshapetoKeypointsOnImage.deepcopy(). - Added optional arguments
keypointsandshapetoKeypointsOnImage.copy(). - Added method
Keypoint.copy(). - Added method
Keypoint.deepcopy().- Refactored methods in
Keypointto usedeepcopy()to create copies of itself (instead of instantiating new instances viaKeypoint(...)).
- Refactored methods in
KeypointsOnImage.deepcopy()now usesKeypoint.deepcopy()to create Keypoint copies, making it more flexible.- Refactored
KeypointsOnImageto useKeypointsOnImage.deepcopy()in as many methods as possible to create copies of itself. - Refactored
Affine,AffineCv2,PiecewiseAffine,PerspectiveTransform,ElasticTransformation,Rot90to useKeypointsOnImage.deepcopy()andKeypoint.deepcopy()during keypoint augmentation.
- Added optional arguments
- Changed
Keypoint.draw_on_image()to draw a rectangle for the keypoint so long as any part of that rectangle is within the image plane. (Previously, the rectangle was only drawn if the integer xy-coordinate of the point was inside the image plane.) - Changed
KeypointsOnImage.draw_on_image()to raise an error if an input image has shape(H,W). - Changed
KeypointsOnImage.draw_on_image()to handle single-number inputs forcolor. KeypointsOnImage.from_coords_array()- Marked as deprecated.
- Renamed to
from_xy_array(). - Renamed arg
coordstoxy. - Changed the method from
staticmethodtoclassmethod. - Refactored to make code simpler.
KeypointsOnImage.get_coords_array()- Marked as deprecated.
- Renamed to
to_xy_array().
- Refactored
KeypointsOnImage.draw_on_image()to useKeypoint.draw_on_image().
Heatmap augmentation
- Changed
Affine,PiecewiseAffine,ElasticTransformationto always useorder=3for heatmap augmentation. - Changed check in
HeatmapsOnImagethat validates whether the input array is within the desired value range[min_value, max_value]from a hard exception to a soft warning (with clipping). Also improved the error message a bit.
Deprecation warnings:
- Added
imgaug.imgaug.DeprecationWarning. The builtin pythonDeprecationWarningis silent since 2.7, which is why now a separate deprecation warning is used. - Added
imgaug.imgaug.warn_deprecated().- Refactored deprecation warnings to use this function.
- Added
imgaug.imgaug.deprecateddecorator.- Refactored deprecation warnings to use this decorator.
Bounding Boxes:
- Added to
BoundingBox.extract_from_image()the argumentspadandpad_max. - Changed
BoundingBox.contains()to also acceptKeypoint. - Changed
BoundingBox.project(from, to)to also accept images instead of shapes. - Renamed argument
thicknessinBoundingBox.draw_on_image()tosizein order to match the name used for keypoints, polygons and line strings. The argumentthicknesswill still be accepted, but raises a deprecation warning. - Renamed argument
thicknessinBoundingBoxesOnImage.draw_on_image()tosizein order to match the name used for keypoints, polygons and line strings. The argumentthicknesswill still be accepted, but raises a deprecation warning. - Refactored
BoundingBoxto reduce code repetition. - Refactored
BoundingBox.extract_from_image(). Improved some code fragments that looked wrong. - Refactored
BoundingBoxesOnImage.draw_on_image()to improve efficiency by evading unnecessary array copies.
Other:
- [rarely breaking] Added arguments
cvalandmodetoPerspectiveTransform(PR #301). This breaks code that relied on the order of the arguments and usedkeep_size,name,deterministicorrandom_stateas positional arguments. - Added
dtypes.clip_()function. - Added function
imgaug.imgaug.flatten()that flattens nested lists/tuples. - Changed
PerspectiveTransformto ensure minimum height and width of output images (by default2x2). This prevents errors in polygon augmentation (possibly also in keypoint augmentation). - Refactored
imgaug.augmenters.blend.blend_alpha()to no longer enforce a channel axis for foreground and background image. - Refactored
imgaug/parameters.pyto reorder classes within the file. - Re-allowed numpy 1.16 in
requirements.txt.
Fixes
- Fixed possible crash in
blend.blend_alpha()if dtype numpy.float128 does not exist. - Fixed a crash in
ChangeColorspacewhencv2.COLOR_Lab2RGBwas actually calledcv2.COLOR_LAB2RGBin the local OpenCV installation (analogous for BGR). (PR #263) - Fixed
ReplaceElementwisealways sampling replacement per channel. - Fixed an error in
draw_text()due to arrays that could not be set to writeable after drawing the text via PIL. - Fixed errors in docstring of
parameters.Subtract. - Fixed a division by zero bug in
angle_between_vectors(). - Augmentation of empty
KeypointsOnImageinstances- Fixed
Rot90not changingKeypointsOnImage.shapeif.keypointswas empty. - Fixed
Affinenot changingKeypointsOnImage.shapeif.keypointswas empty. - Fixed
PerspectiveTransformnot changingKeypointsOnImage.shapeif.keypointswas empty. - Fixed
Resizenot changingKeypointsOnImage.shapeif.keypointswas empty. - Fixed
CropAndPadnot changingKeypointsOnImage.shapeif.keypointswas empty. (Same forCrop,Pad.) - Fixed
PadToFixedSizenot changingKeypointsOnImage.shapeif.keypointswas empty. - Fixed
CropToFixedSizenot changingKeypointsOnImage.shapeif.keypointswas empty. - Fixed
KeepSizeByResizenot changingKeypointsOnImage.shapeif.keypointswas empty.
- Fixed
- Fixed
Affineheatmap augmentation producing arrays with values outside the range[0.0, 1.0]whenorderwas set to3. - Fixed
PiecewiseAffineheatmap augmentation producing arrays with values outside the range[0.0, 1.0]whenorderwas set to3. - Fixed assert in
SegmentationMapOnImagefalsely checking if max class index is<= nb_classesinstead of< nb_classes. - Fixed an issue in
dtypes.clip_to_value_range_()anddtypes.restore_dtypes_()causing errors when clip value range exceeded array dtype's value range. - Fixed an issue in
dtypes.clip_to_value_range_()anddtypes.restore_dtypes_()when the input array was scalar, i.e. had shape(). - Fixed a Permission Denied error when using
JpegCompressionon windows (possibly also affected other systems). #297