Releases: albumentations-team/albumentations
Albumentations 1.4.17 Release Notes
- Support Our Work
- Transforms
- Core
Support Our Work
- Love the library? You can contribute to its development by becoming a sponsor for the library. Your support is invaluable, and every contribution makes a difference.
- Haven't starred our repo yet? Show your support with a ⭐! It's just only one mouse click away.
- Got ideas or facing issues? We'd love to hear from you. Share your thoughts in our issues or join the conversation on our Discord server
Transforms
CoarseDropout
- Added Bounding Box support
remove_invisible=False
keeps keypoints
by @ternaus
ElasticTransform
Added support for keypoints
by @ternaus
Core
Added RandomOrder Compose
Select N transforms to apply. Selected transforms will be called in random order with force_apply=True.
Transforms probabilities will be normalized to one 1, so in this case transforms probabilities works as weights.
This transform is like SomeOf, but transforms are called with random order.
It will not replay random order in ReplayCompose.
Albumentations 1.4.16 Release Notes
- Support Our Work
- UI Tool
- Transforms
- Improvements and Bug Fixes
Support Our Work
- Love the library? You can contribute to its development by becoming a sponsor for the library. Your support is invaluable, and every contribution makes a difference.
- Haven't starred our repo yet? Show your support with a ⭐! It's just only one mouse click away.
- Got ideas or facing issues? We'd love to hear from you. Share your thoughts in our issues or join the conversation on our Discord server
UI Tool
For visual debug wrote a tool that allows visually inspect effects of augmentations on the image.
You can find it at https://explore.albumentations.ai/
- Works for all ImageOnly transforms
- Authorized users can upload their own images
it is work in progress. It is not stable and polished yet, but if you have feedback or proposals - just write in the Discord Server mentioned above.
Transforms
- Updated and extended docstrings in all ImageOnly transforms.
- All ImageOnly transforms support both
uint8
andfloat32
inputs
RandomSnow
Added texture
method to RandomSnow
RandomSunflare
Added physics_based
method to RandomSunFlare
Bugfixes and improvements
- Bugfix in albucore dependency. Now every
Albumnetations
version is tailored to a specificalbucore
version. Added pre-commit hook to automatically check it on every commit. - BugFix in TextImage transform, after rewriting bbox processing in a vectorized form, transform was failing.
- As a part of the work to remove scikit-image dependency @momincks rewrote bbox_affine in a plain numpy
- Bugfix. It was unexpected, but people use bounding bboxes that are less than 1 pixel. Removed constrant on a minimum bounding box being 1x1
- Bugfix in bounding box filtering. Now if all bounding boxes were filtered return not empty array, but empty array of shape (0, 4)
Albumentations 1.4.15 Release Notes
- Support Our Work
- UI Tool
- Core
- Transforms
- Improvements and Bug Fixes
Support Our Work
- Love the library? You can contribute to its development by becoming a sponsor for the library. Your support is invaluable, and every contribution makes a difference.
- Haven't starred our repo yet? Show your support with a ⭐! It's just only one mouse click away.
- Got ideas or facing issues? We'd love to hear from you. Share your thoughts in our issues or join the conversation on our Discord server
UI Tool
For visual debug wrote a tool that allows visually inspect effects of augmentations on the image.
You can find it at https://explore.albumentations.ai/
RIght now supports only ImageOnly transforms, and not all but a subset of them.
it is work in progress. It is not stable and polished yet, but if you have feedback or proposals - just write in the Discord Server mentioned above.
Core
Bounding box and keypoint processing was vectorized
- You can pass numpy array to compose and not only list of lists.
- Presumably transforms will work faster, but did not benchmark.
Transforms
Affine
- Reflection padding correctly works In
Affine
andShiftScaleRotate
CLAHE
- Added support for float32 images
Equalize
- Added support for float32 images
FancyPCA
- Added support for float32 images
- Added support for any number of channels
PixelDistributionAdaptation
- Added support for float32
- Added support for anyu number of channels
Flip
Still works, but deprecated. It was a very strange transform, I cannot find use case, where you needed to use it.
It was equivalent to:
OneOf([Transpose, VerticalFlip, HorizontalFlip])
Most likely if you needed transform that does not create artifacts, you should look at:
- Natural images =>
HorizontalFlip
(Symmetry group has 2 elements, meaning will effectively increase your dataset 2x) - Images that look natural when you vertically flip them =>
VerticalFlip
(Symmetry group has 2 elements, meaning will effectively increase your dataset 2x) - Images that need to preserve parity, for example texts, but we may expect rotated documents =>
RandomRotate90
(Symmetry group has 2 elements, meaning will effectively increase your dataset 4x) - Images that you can flip and rotate as you wish =>
D4
(Symmetry group has 8 elements, meaning will effectively increase your dataset 8x)
ToGray
Now you can define the number of output channels in the resulting gray image. All channels will be the same.
Extended ways one can get grayscale image. Most of them can work with any number of channels as input
weighted_average
: Uses a weighted sum of RGB channels(0.299R + 0.587G + 0.114B)
Works only with 3-channel images. Provides realistic results based on human perception.from_lab
: Extracts the L channel from the LAB color space.
Works only with 3-channel images. Gives perceptually uniform results.desaturation
: Averages the maximum and minimum values across channels.
Works with any number of channels. Fast but may not preserve perceived brightness well.average
: Simple average of all channels.
Works with any number of channels. Fast but may not give realistic results.max
: Takes the maximum value across all channels.
Works with any number of channels. Tends to produce brighter results.pca
: Applies Principal Component Analysis to reduce channels.
Works with any number of channels. Can preserve more information but is computationally intensive.
SafeRotate
Now uses Affine under the hood.
Improvements and Bug Fixes
- Bugfix in
GridElasticDeform
by @4pygmalion - Speedups in
to_float
andfrom_float
- Bugfix in PadIfNeeded. Did not work when empty bounding boxes were passed.
Albumentations 1.4.14 Release Notes
- Support Our Work
- Transforms
- Improvements and Bug Fixes
Support Our Work
- Love the library? You can contribute to its development by becoming a sponsor for the library. Your support is invaluable, and every contribution makes a difference.
- Haven't starred our repo yet? Show your support with a ⭐! It's just only one mouse click away.
- Got ideas or facing issues? We'd love to hear from you. Share your thoughts in our issues or join the conversation on our Discord server
Transforms
Added GridElasticDeform
transform
Grid-based Elastic deformation Albumentation implementation
This class applies elastic transformations using a grid-based approach.
The granularity and intensity of the distortions can be controlled using
the dimensions of the overlaying distortion grid and the magnitude parameter.
Larger grid sizes result in finer, less severe distortions.
Args:
num_grid_xy (tuple[int, int]): Number of grid cells along the width and height.
Specified as (grid_width, grid_height). Each value must be greater than 1.
magnitude (int): Maximum pixel-wise displacement for distortion. Must be greater than 0.
interpolation (int): Interpolation method to be used for the image transformation.
Default: cv2.INTER_LINEAR
mask_interpolation (int): Interpolation method to be used for mask transformation.
Default: cv2.INTER_NEAREST
p (float): Probability of applying the transform. Default: 1.0.
Targets:
image, mask
Image types:
uint8, float32
Example:
>>> transform = GridElasticDeform(num_grid_xy=(4, 4), magnitude=10, p=1.0)
>>> result = transform(image=image, mask=mask)
>>> transformed_image, transformed_mask = result['image'], result['mask']
Note:
This transformation is particularly useful for data augmentation in medical imaging
and other domains where elastic deformations can simulate realistic variations.
by @4pygmalion
PadIfNeeded
Now reflection padding correctly with bounding boxes and keypoints
by @ternaus
RandomShadow
- Works with any number of channels
- Intensity of the shadow is not hardcoded constant anymore but could be sampled
Simulates shadows for the image by reducing the brightness of the image in shadow regions.
Args:
shadow_roi (tuple): region of the image where shadows
will appear (x_min, y_min, x_max, y_max). All values should be in range [0, 1].
num_shadows_limit (tuple): Lower and upper limits for the possible number of shadows.
Default: (1, 2).
shadow_dimension (int): number of edges in the shadow polygons. Default: 5.
shadow_intensity_range (tuple): Range for the shadow intensity.
Should be two float values between 0 and 1. Default: (0.5, 0.5).
p (float): probability of applying the transform. Default: 0.5.
Targets:
image
Image types:
uint8, float32
Reference:
https://github.com/UjjwalSaxena/Automold--Road-Augmentation-Library
by @JonasKlotz
Improvements and Bug Fixes
- BugFix in
Affine
. Nowfit_output=True
works correctly with bounding boxes. by @ternaus - BugFix in
ColorJitter
. By @maremun - Speedup in
CoarseDropout
. By @thomaoc1 - Check for updates does not use
logger
anymore. by @ternaus - Bugfix in
HistorgramMatching
. Before it output array of ones. Now works as expected. by @ternaus
1.4.13
Albumentations 1.4.12 Release Notes
- Support Our Work
- Transforms
- Core Functionality
- Deprecations
- Improvements and Bug Fixes
Support Our Work
- Love the library? You can contribute to its development by becoming a sponsor for the library. Your support is invaluable, and every contribution makes a difference.
- Haven't starred our repo yet? Show your support with a ⭐! It's just only one mouse click away.
- Got ideas or facing issues? We'd love to hear from you. Share your thoughts in our issues or join the conversation on our Discord server
Transforms
Added TextImage transform
Allows adding text on top of images. Works with np,unit8
and np.float32
images with any number of channels.
Additional functionalities:
- Insert random stopwords
- Delete random words
- Swap word order
Core functionality
Added images
target
You can now apply the same transform to a list of images of the same shape, not just one image.
Use cases:
- Video: Split video into frames and apply the transform.
- Slices of 3D volumes: For example, in medical imaging.
import albumentations as A
transform = A.Compose([A.Affine(p=1)])
transformed = transform(images=<list of images>)
transformed_images = transformed["images"]
Note:
You can apply the same transform to any number of images, masks, bounding boxes, and sets of keypoints using the additional_targets functionality notebook with examples
Contributors @ternaus, @ayasyrev
get_params_dependent_on data
Relevant for those who build custom transforms.
Old way
@property
def targets_as_params(self) -> list[str]:
return <list of targets>
def get_params_dependent_on_targets(self, params: dict[str, Any]) -> dict[str, np.ndarray]:
image = params["image"]
....
New way
def get_params_dependent_on_data(self, params: dict[str, Any], data: dict[str, Any]) -> dict[str, np.ndarray]:
image = data["image"]
Contributor @ayasyrev
Added shape
to params
Old way:
def get_params_dependent_on_targets(self, params: dict[str, Any]) -> dict[str, np.ndarray]:
image = params["image"]
shape = image.shape
New way:
def get_params_dependent_on_data(self, params: dict[str, Any], data: dict[str, Any]) -> dict[str, np.ndarray]:
shape = params["shape"]
Contributor @ayasyrev
Deprecations
Elastic Transform
Deprecated parameter alpha_affine
in ElasticTransform
. To have Affine effects on your image, use the Affine
transform.
Contributor @ternaus
Improvements and Bug Fixes
Albumentations 1.4.11 Release Notes
- Support our work
- Transforms
- Core functionality
- Deprecations
- Improvements and bug fixes
Support Our Work
- Love the library? You can contribute to its development by becoming a sponsor for the library. Your support is invaluable, and every contribution makes a difference.
- Haven't starred our repo yet? Show your support with a ⭐! It's just only one mouse click.
- Got ideas or facing issues? We'd love to hear from you. Share your thoughts in our issues or join the conversation on our Discord server for Albumentations
Transforms
Added OverlayElements transform
Allows to paste set of images + corresponding masks to the image.
It is not entirely CopyAndPaste
as "masks", "bounding boxes" and "keypoints" are not supported, but step in that direction.
Affine
Added balanced sampling for scale_limit
From FAQ:
The default scaling logic in RandomScale
, ShiftScaleRotate
, and Affine
transformations is biased towards upscaling.
For example, if scale_limit = (0.5, 2)
, a user might expect that the image will be scaled down in half of the cases and scaled up in the other half. However, in reality, the image will be scaled up in 75% of the cases and scaled down in only 25% of the cases. This is because the default behavior samples uniformly from the interval [0.5, 2]
, and the interval [0.5, 1]
is three times smaller than [1, 2]
.
To achieve balanced scaling, you can use Affine with balanced_scale=True, which ensures that the probability of scaling up and scaling down is equal.
balanced_scale_transform = A.Compose([A.Affine(scale=(0.5, 2), balanced_scale=True)])
by @ternaus
RandomSizedBBoxSafeCrop
Added support for keypoints
by @ternaus
BBoxSafeRandomCrop
Added support for keypoints
by @ternaus
RandomToneCurve
- Now can sample noise per channel
- Works with any number of channels
- Now works not just with uint8, but with float32 images as well
by @zakajd
ISONoise
- BugFix
- Now works not just with uint8, but with float32 images as well
by @ternaus
Core
Added strict
parameter to Compose
If strict=True
only targets that are expected could be passed.
If strict = False
, user can pass data with extra keys. Such data would not be affected by transforms.
Request came from users that use pipelines in the form:
transform = A.Compose([....])
data = A.Compose(**data)
by @ayasyrev
Refactoring
Crop module was heavily refactored, all tests and checks pass, but we will see.
Deprecations
Grid Dropout
Old way:
GridDropout(
holes_number_x=XXX,
holes_numver_y=YYY,
unit_size_min=ZZZ,
unit_size_max=PPP
)
New way:
GridDropout(
holes_number_xy = (XXX, YYY),
unit_size_range = (ZZZ, PPP)
)
by @ternaus
RandomSunFlare
Old way:
RandomSunFlare(
num_flare_circles_lower = XXX,
num_flare_circles_upper = YYY
)
new way:
RandomSunFlare(num_flare_circles_range = (XXX, YYY))
Bugfixes
- Bugfix in
ISONoise
, as it returned zeros. by @ternaus - BugFix in
Affine
as during rotation image, mask, keypoints have one center point for rotation and bounding box another => we need to create two separate affine matrices. by @ternaus - Small fix in Error Message by @philipp-fischer
- Bugfix that affected many transforms, where users specified probability as number and not as
p=number
. Say forVerticalFlip(0.5)
you could expect 50% chance, but 0.5 was attributed not top
but toalways_apply
which meant that the transform was always applied. by @ayasyrev
Hotfix release with fixes for RandomGauss
Hotfix release that addresses issues introduced in 1.4.9
There were two issues in GaussNoise that this release addresses:
- Default value of 0.5 for
noise_scale_factor
, which is different from the behavior before version 1.4.9. Now default value = 1, which means random noise is created for every point independently - Noise was truncated before adding to the image, so that
gauss >=0
. Fixed.
Albumentations 1.4.9 Release Notes
- Support our work
- New transforms
- Integrations
- Speedups
- Deprecations
- Improvements and bug fixes
Support Our Work
- Love the library? You can contribute to its development by becoming a sponsor for the library. Your support is invaluable, and every contribution makes a difference.
- Haven't starred our repo yet? Show your support with a ⭐! It's just only one mouse click.
- Got ideas or facing issues? We'd love to hear from you. Share your thoughts in our issues or join the conversation on our Discord server for Albumentations
Transforms
PlanckianJitter
New transform, based on
Statements from the paper on why PlanckianJitter is superior to ColorJitter:
-
Realistic Color Variations: PlanckianJitter applies physically realistic illuminant variations based on Planck’s Law for black-body radiation. This leads to more natural and realistic variations in chromaticity compared to the arbitrary changes in hue, saturation, brightness, and contrast applied by ColorJitter.
-
Improved Representation for Color-Sensitive Tasks: The transformations in PlanckianJitter maintain the ability to discriminate image content based on color information, making it particularly beneficial for tasks where color is a crucial feature, such as classifying natural objects like birds or flowers. ColorJitter, on the other hand, can significantly alter colors, potentially degrading the quality of learned color features.
-
Robustness to Illumination Changes: PlanckianJitter produces models that are robust to illumination changes commonly observed in real-world images. This robustness is advantageous for applications where lighting conditions can vary widely.
-
Enhanced Color Sensitivity: Models trained with PlanckianJitter show a higher number of color-sensitive neurons, indicating that these models retain more color information compared to those trained with ColorJitter, which tends to induce color invariance.
by @zakajd
GaussNoise
Added option to approximate GaussNoise.
Generation of random Noise for large images is slow.
Added scaling factor for noise generation. Value should be in the range (0, 1]
. When set to 1, noise is sampled for each pixel independently. If less, noise is sampled for a smaller size and resized to fit the shape of the image. Smaller values make the transform much faster. Default: 0.5
Integrations
Added integration wit HFHub. Now you can load and save augmentation pipeline to HuggingFace and reuse it in the future or share with others.
import albumentations as A
import numpy as np
transform = A.Compose([
A.RandomCrop(256, 256),
A.HorizontalFlip(),
A.RandomBrightnessContrast(),
A.RGBShift(),
A.Normalize(),
])
evaluation_transform = A.Compose([
A.PadIfNeeded(256, 256),
A.Normalize(),
])
transform.save_pretrained("qubvel-hf/albu", key="train")
# ^ this will save the transform to a directory "qubvel-hf/albu" with filename "albumentations_config_train.json"
transform.save_pretrained("qubvel-hf/albu", key="train", push_to_hub=True)
# ^ this will save the transform to a directory "qubvel-hf/albu" with filename "albumentations_config_train.json"
# + push the transform to the Hub to the repository "qubvel-hf/albu"
transform.push_to_hub("qubvel-hf/albu", key="train")
# ^ this will push the transform to the Hub to the repository "qubvel-hf/albu" (without saving it locally)
loaded_transform = A.Compose.from_pretrained("qubvel-hf/albu", key="train")
# ^ this will load the transform from local folder if exist or from the Hub repository "qubvel-hf/albu"
evaluation_transform.save_pretrained("qubvel-hf/albu", key="eval", push_to_hub=True)
# ^ this will save the transform to a directory "qubvel-hf/albu" with filename "albumentations_config_eval.json"
loaded_evaluation_transform = A.Compose.from_pretrained("qubvel-hf/albu", key="eval")
# ^ this will load the transform from the Hub repository "qubvel-hf/albu"
by @qubvel
Speedups
These transforms should be faster for all types of images. But measured only for three channel uint8
- RGBShift: 2X (+106%)
- GaussNoise: 3.3X (+ 236%)
Deprecations
Deprecated always_apply
For years we had two parameters in constructors - probability
and always_apply
. The interplay between them is not always obvious and intuitively always_apply=True
should be equivalent to p=1
.
always_apply
is deprecated now. always_apply=True
still works, but it will be deprecated in the future. Use p=1
instead
by @ayasyrev
RandomFog
Updated interface for RandomFog
Old way:
RandomFog(fog_coef_lower=0.3, fog_coef_upper=1)
New way:
RandomFog(fog_coef_range=(0.3, 1))
by @ternaus
Improvements and bugfixes
Disable check for updates
When one imports Albumentations library, there is a check that it is the latest version installed.
To disable this check you can set up environmental variable: NO_ALBUMENTATIONS_UPDATE
to 1
by @lerignoux
Fix for deprecation warnings
For a set of transforms we were throwing deprecation warnings, even when modern version of the interface was used. Fixed. by @ternaus
Albucore
We moved low level operations like add, multiply, normalize, etc to a separate library: https://github.com/albumentations-team/albucore
There are numerous ways to perform such operations in opencv and numpy. And there is no clear winner. Results depend on image type.
Separate library gives us confidence that we picked the fastest version that works on any image type.
by @ternaus
Bugfixes
Various bugfixes by @ayasyrev @immortalCO
Albumentations 1.4.8 Release Notes
- Support our work
- Documentation
- Deprecations
- Improvements and bug fixes
Support Our Work
- Love the library? You can contribute to its development by becoming a sponsor for the library. Your support is invaluable, and every contribution makes a difference.
- Haven't starred our repo yet? Show your support with a ⭐! It's just only one mouse click.
- Got ideas or facing issues? We'd love to hear from you. Share your thoughts in our issues or join the conversation on our Discord server for Albumentations
Documentation
Added to the documentation links to the UI on HuggingFace to explore hyperparameters visually.
Deprecations
RandomSnow
Updated interface:
Old way:
transform = A.Compose([A.RandomSnow(
snow_point_lower=0.1,
snow_point_upper=0.3,
p=0.5
)])
New way:
transform = A.Compose([A.RandomSnow(
snow_point_range=(0.1, 0.3),
p=0.5
)])
RandomRain
Old way
transform = A.Compose([A.RandomSnow(
slant_lower=-10,
slant_upper=10,
p=0.5
)])
New way:
transform = A.Compose([A.RandomRain(
slant_range=(-10, 10),
p=0.5
)])
Improvements
Created library with core functions albucore. Moved a few helper functions there.
We need this library to be sure that transforms are:
- At least as fast as
numpy
andopencv
. For some functions it is possible to be faster than both of them. - Easier to debug.
- Could be used in other projects, not related to Albumentations.
Bugfixes
- Bugfix in
check_for_updates
. Now the pipeline does not throw an error regardless of why we cannot check for update. - Bugfix in
RandomShadow
. Does not create unexpected purple color on bright white regions with shadow overlay anymore. - BugFix in
Compose
. NowCompose([])
does not throw an error, but just works asNoOp
by @ayasyrev - Bugfix in
min_max
normalization. Now return 0 and not NaN on constant images. by @ternaus - Bugfix in
CropAndPad
. Now we can sample pad/crop values for all sides with interface like((-0.1, -0.2), (-0.2, -0.3), (0.3, 0.4), (0.4, 0.5))
by @christian-steinmeyer - Small refactoring to decrease tech debt by @ternaus and @ayasyrev