Frequently Asked Questions

On this page

This FAQ covers common questions about Albumentations, from basic setup to advanced usage. You'll find information about:

  • Installation troubleshooting and configuration
  • Working with different data formats (images, video, volumetric data)
  • Advanced usage patterns and best practices
  • Integration with other tools and switching from other libraries

If you don't find an answer to your question, please check the GitHub Issues for Albumentations, or join our Discord community.

Installation

I am receiving an error message Failed building wheel for imagecodecs when I am trying to install Albumentations. How can I fix the problem?

Try to update pip by running the following command:

python -m pip install --upgrade pip

How to make Albumentations use one CPU core?

Albumentations do not use multithreading by default, but libraries it depends on (like opencv) may use multithreading. To make Albumentations use one CPU core, you can set the following environment variables:

import os

os.environ["OMP_NUM_THREADS"] = "1"
os.environ["OPENBLAS_NUM_THREADS"] = "1"
os.environ["MKL_NUM_THREADS"] = "1"
os.environ["VECLIB_MAXIMUM_THREADS"] = "1"
os.environ["NUMEXPR_NUM_THREADS"] = "1"

# Disable OpenCV multithreading and OpenCL
import cv2
cv2.setNumThreads(0)
cv2.ocl.setUseOpenCL(False)

This should be done at the beginning of your script or before creating the DataLoader. Note that this solution may not be necessary for all users, and you should only apply it if you're experiencing performance problems with your specific setup.

Experiencing slow performance with PyTorch DataLoader multi-processing?

Some users have reported performance issues when using Albumentations with PyTorch's DataLoader in a multi-processing setup. This can occur on certain hardware/software configurations because OpenCV (cv2), which Albumentations uses under the hood, may spawn multiple threads within each DataLoader worker process. These threads can potentially interfere with each other, leading to CPU blocking and slower data loading.

If you encounter this issue, you can try disabling OpenCV's internal multithreading and OpenCL acceleration by calling:

import cv2
cv2.setNumThreads(0)
cv2.ocl.setUseOpenCL(False)

This should be done at the beginning of your script or before creating the DataLoader. Note that this solution may not be necessary for all users, and you should only apply it if you're experiencing performance problems with your specific setup.

How do I disable telemetry in Albumentations?

Usage telemetry helps improve the library and is enabled by default. Set ALBUMENTATIONS_NO_TELEMETRY=1 before importing albumentations to disable it globally, or use A.Compose(..., telemetry=False) for an individual pipeline. Restart an existing process or notebook kernel after changing its environment.

See the library telemetry notice for collected fields and configuration details.

Albumentations and Licensing

What does a commercial license give my company?

A commercial agreement with Albumentations LLC can grant rights to use, modify, integrate, host, or distribute AlbumentationsX in proprietary software without AGPL source-sharing requirements for the use covered by that agreement. The offer names the teams, legal entities, products, deployments, term, and any distribution rights. Third-party licenses still apply; support and other services are included only when expressly agreed.

For a quote for your team or product, use the form or email [email protected]. You can also compare the license options.

Which package and license am I using?

The maintained package is albumentationsx, with the Python import namespace albumentations. It is available under AGPL-3.0-only from version 2.3.2, or under a commercial agreement. The legacy albumentations package remains under MIT; its last release was 2.0.8. Earlier releases keep the permissions that accompanied them, including the AGPL-3.0-or-later metadata of AlbumentationsX 2.1.3 through 2.3.1. See the License Guide for the history and practical differences.

Do I need a commercial license because my code is proprietary or used by a company?

No, those facts alone do not require a purchase. Companies can use AlbumentationsX at no charge under AGPL when they comply with its applicable conditions. A commercial agreement offers alternative rights for your covered software.

Does the AGPL require my entire project to use the same license?

AGPL's whole-work conditions concern the covered work, not automatically every file in a company or repository. Whether integrated components form one covered work or remain independent depends on the architecture, communication, and what is delivered. A Python import or an unchanged library file does not resolve the boundary by itself. See the License Guide for examples.

Does internal use require source disclosure?

Internal training alone does not require a purchase or automatic disclosure of your training code. Section 2 permits private execution and covered works that are not conveyed, subject to its terms. Separately check whether users interact with a modified version over a network or copies reach another legal entity.

Does every web or API service need to publish its source?

No. Section 13 concerns remote interaction with a modified version that supports that interaction. It requires an offer of that version's Corresponding Source to those users. This can include an internal network. The scope of a modified or combined work depends on how the software is integrated.

Are model weights or predictions automatically AGPL because AlbumentationsX was used for training?

No. Using AlbumentationsX for augmentation does not, by itself, make ordinary weights or predictions AGPL. Section 2 covers output only when the output itself constitutes a covered work. Check separately whether you also deliver library code, an SDK, a container, or a combined application.

Can I evaluate AlbumentationsX before signing commercial terms?

Yes. You can evaluate the public version under AGPL, subject to the same applicable conditions as other uses. Private execution of the unmodified Program is expressly permitted by section 2. There is no general AGPL trial expiry or automatic payment trigger when evaluation ends.

The License Guide explains these scenarios and links to the controlling license text.

Data Formats and Basic Usage

Supported Image Types

Compose accepts NumPy arrays and plain CPU Tensors with image dtypes uint8, float16 (FP16), or float32. Use [0, 255] for bytes and [0, 1] for floating images before ordinary image augmentations. Scale raw floating intensities explicitly; Compose does not universally clip inputs. Normalization can intentionally produce values outside [0, 1].

FP16-preserving transforms, Normalize, and ToFloat retain FP16 input. Bbox/keypoint Tensor inputs remain float32. See the dtype and layout tables.

How should I read an RGB image with OpenCV?

Use the explicit RGB read flag with the supported OpenCV 5.x runtime:

import cv2

image = cv2.imread("image.jpg", cv2.IMREAD_COLOR_RGB)
if image is None:
    raise FileNotFoundError("image.jpg")

How to have reproducible augmentations?

Set the seed parameter in your transform pipeline. Albumentations uses its own internal random state (independent from np.random.seed() or random.seed()). Two Compose instances with the same seed produce identical augmentation sequences.

transform = A.Compose([
    A.RandomCrop(height=256, width=256),
    A.HorizontalFlip(p=0.5),
    A.RandomBrightnessContrast(p=0.2),
], seed=137)

For a comprehensive guide on reproducibility, including advanced use cases and best practices, see the Reproducibility Guide.

How does Albumentations handle grayscale images?

Compose accepts a NumPy grayscale image as (H, W) or (H, W, 1), and a CPU Tensor as (H, W) or (1, H, W). It adds a missing channel axis for processing, then removes it if the result still has one channel. A transform that creates RGB output keeps the resulting channel axis.

import albumentations as A
import numpy as np

transform = A.Compose([A.CenterCrop(224, 224)], seed=137)
grayscale = np.zeros((256, 256), dtype=np.uint8)
assert transform(image=grayscale)["image"].shape == (224, 224)
assert transform(image=grayscale[..., None])["image"].shape == (224, 224, 1)

Direct NumPy transforms such as HorizontalFlip also accept (H, W). Use Compose for common layout handling across a policy. See Grayscale Image Handling.

What data formats does Albumentations accept?

Use NumPy arrays or supported plain CPU torch.Tensor values for dense images, masks, videos, and volumes. NumPy uses channel-last layouts; Tensor images and volumes use channel-first layouts. Container choice is independent for each target.

Bbox and keypoint processors accept numeric NumPy arrays, float32 CPU Tensors, or Python coordinate sequences. Label fields accept arrays or sequences. Structured instances, bbox_labels, and keypoint_labels keep their documented per-object containers.

For accepted shapes and dtypes, Tensor device constraints, and the NumPy-to-Tensor converter rule, see Working with Targets.

Working with Different Data Types

How to process video data with Albumentations?

Albumentations can process video data by treating it as a sequence of frames in numpy array format:

  • (N, H, W) - Grayscale video (N frames)
  • (N, H, W, C) - Color video (N frames)

When you pass a video array, Albumentations will apply the same transform with identical parameters to each frame, ensuring temporal consistency.

video = np.random.default_rng(137).random((32, 256, 256, 3), dtype=np.float32)

transform = A.Compose([
  A.RandomCrop(height=224, width=224),
  A.HorizontalFlip(p=0.5)
], seed=137)

transformed = transform(images=video)['images']

See Working with Video Data for more info.

How to process volumetric data with Albumentations?

Albumentations can process volumetric data by treating it as a sequence of 2D slices. When you pass a volumetric data as a numpy array, Albumentations will apply the same transform with identical parameters to each slice, ensuring temporal consistency.

See Working with Volumetric Data (3D) for more info.

Which transforms work with my data type?

Different transforms support different combinations of targets (images, masks, bboxes, keypoints, volumes). Before building your pipeline, check the Supported Targets by Transform reference to ensure your chosen transforms are compatible with your data types.

This reference is particularly useful when:

  • Working with multiple targets simultaneously (e.g., images + masks + bboxes)
  • Planning volumetric (3D) augmentation pipelines
  • Debugging "unsupported target" errors
  • Choosing transforms for specific computer vision tasks

My computer vision pipeline works with a sequence of images. I want to apply the same augmentations with the same parameters to each image in the sequence. Can Albumentations do it?

Yes. You can define additional images, masks, bounding boxes, or keypoints through the additional_targets argument to Compose. You can then pass those additional targets to the augmentation pipeline, and Albumentations will augment them in the same way. See this example for more info.

For a sequence of images, use the plural images target: NumPy (N, H, W, C) or grayscale (N, H, W), or a CPU Tensor (N, C, H, W). Pass a stacked array or Tensor rather than a list of frames.

Advanced Usage

How can I find which augmentations were applied to the input data and which parameters they used?

Pass save_applied_params=True to Compose to record which transforms ran and their JSON-compatible applied constructor configurations. Access the records through applied_transforms.

transform = A.Compose([
    A.RandomCrop(256, 256),
    A.HorizontalFlip(p=0.5),
    A.RandomBrightnessContrast(p=0.5),
    A.RandomGamma(p=0.5),
    A.Normalize(),
], save_applied_params=True, seed=137)

result = transform(image=image)

transformed = result["image"]
print(result["applied_transforms"])

The records may contain sampled constructor-level values, but they do not contain every runtime-only detail such as crop coordinates or dropout masks. For runtime inspection, exact replay, and training-time logging, see Replay and Applied-Parameter Debugging.

How to apply CutOut augmentation?

Albumentations provides the CoarseDropout transform, which is a generalization of the CutOut and Random Erasing augmentation techniques. If you are looking for CutOut or Random Erasing, you should use CoarseDropout.

CoarseDropout generalizes these techniques by allowing:

  • Variable number of holes: num_holes_range samples how many holes to draw (integer counts — not pixels and not fractions of the image).
  • Variable hole size: Holes can be rectangular, with ranges for height (hole_height_range) and width (hole_width_range). Prefer fractions of H/W (values in (0, 1]); integer tuples are interpreted as pixel sizes.
  • Flexible fill values: You can fill the holes with a constant value (int/float), per-channel values (tuple), random noise per pixel ('random'), a single random color per hole ('random_uniform'), or using OpenCV inpainting methods ('inpaint_telea', 'inpaint_ns').
  • Optional mask filling: You can specify a separate fill_mask value to fill corresponding areas in the mask, or leave the mask unchanged (None).

Example using random uniform fill:

import albumentations as A
import numpy as np

image = np.random.randint(0, 256, size=(256, 256, 3), dtype=np.uint8)

# Apply CoarseDropout with 3-6 holes; hole height/width are fractions of H/W (0.04-0.08 ≈ 4-8% of the side).
# filled with a random uniform color.
transform = A.CoarseDropout(
    num_holes_range=(3, 6),
    hole_height_range=(0.04, 0.08),
    hole_width_range=(0.04, 0.08),
    fill="random_uniform",
    p=1.0
)

augmented_image = transform(image=image)['image']

This transform randomly removes rectangular regions from an image, similar to CutOut, but with more configuration options.

To specifically mimic the original CutOut behavior, you can configure CoarseDropout as follows:

  • Set num_holes_range=(1, 1) to always create exactly one hole.
  • Set hole_height_range and hole_width_range to the same fixed fractional span (e.g., (0.0625, 0.0625) for a square ~6.25% of the image side, or (0.1, 0.1) for 10%). Prefer fractions so the policy scales across resolutions; integer tuples mean pixel sizes.
  • Set fill=0 to fill the hole with black.

Example mimicking CutOut with a fixed relative hole size (~1/16 of H and W):

cutout_transform = A.CoarseDropout(
    num_holes_range=(1, 1),
    hole_height_range=(0.0625, 0.0625),
    hole_width_range=(0.0625, 0.0625),
    fill=0,
    p=1.0 # Apply always, or adjust probability as needed
)

How to perform balanced scaling?

The default scaling logic in RandomScale, ShiftScaleRotate, and Affine transformations is biased towards upscaling.

For example, with A.Affine(scale=(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.Affine(scale=(0.5, 2), balanced_scale=True)

or use OneOf transform as follows:

balanced_scale_transform = A.OneOf([
  A.Affine(scale=(0.5, 1), p=0.5),
  A.Affine(scale=(1, 2), p=0.5)])

These policies give upscaling and downscaling equal probability; a finite sample need not split exactly in half.

How do I know which transforms support my combination of targets?

When working with multiple targets (images + masks + bboxes + keypoints), you need to ensure all transforms in your pipeline support your specific combination. The Supported Targets by Transform reference shows exactly which transforms work with which target types.

This is especially important when:

  • Building pipelines with bounding boxes or keypoints
  • Working with volumetric (3D) data
  • Debugging "unsupported target" errors
  • Migrating from other libraries

For example, if you're working with images and bounding boxes, use spatial transforms that declare bbox support. You can combine them with pixel transforms, which leave boxes unchanged.

Augmentations have a parameter named p that sets the probability of applying that augmentation. How does p work in nested containers?

The p parameter sets the probability of applying a specific augmentation. When augmentations are nested within a top-level container like Compose, the effective probability of each augmentation is the product of the container's probability and the augmentation's probability.

Let's look at an example when a container Compose contains one augmentation Resize:

transform = A.Compose([
    A.Resize(height=256, width=256, p=1.0),
], p=0.9)

In this case, Resize has a 90% chance to be applied. This is because there is a 90% chance for Compose to be applied (p=0.9). If Compose is applied, then Resize is applied with 100% probability (p=1.0).

To visualize:

  • Probability of Compose being applied: 0.9
  • Probability of Resize being applied given Compose is applied: 1.0
  • Effective probability of Resize being applied: 0.9 * 1.0 = 0.9 (or 90%)

This means that the effective probability of Resize being applied is the product of the probabilities of Compose and Resize, which is 0.9 * 1.0 = 0.9 or 90%. This principle applies to other transformations as well, where the overall probability is the product of the individual probabilities within the transformation pipeline.

Here's another example:

transform = A.Compose([
    A.Resize(height=256, width=256, p=0.5),
], p=0.9)

In this example, Resize has an effective probability of being applied as 0.9 * 0.5 = 0.45 or 45%. This is because Compose is applied 90% of the time, and within that 90%, Resize is applied 50% of the time.

I created annotations for bounding boxes using labeling service or labeling software. How can I use those annotations in Albumentations?

You need to convert those annotations to one of the formats, supported by Albumentations. For the list of formats, please refer to this article.

Note: Not all transforms support bounding boxes. Check the Supported Targets by Transform reference to see which transforms work with your specific combination of data types.

Consult the documentation of the labeling service to see how you can export annotations in those formats.

Integration

How to save and load augmentation transforms to HuggingFace Hub?

import albumentations as A
import numpy as np

transform = A.Compose([
    A.RandomCrop(256, 256),
    A.HorizontalFlip(),
    A.RandomBrightnessContrast(),
    A.RGBShift(),
    A.Normalize(),
])

transform.save_pretrained("qubvel-hf/albu", key="train")
# The 'key' parameter specifies the context or purpose of the saved transform,
# allowing for organized and context-specific retrieval.
# ^ 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")
# Use `save_pretrained` to save the transform locally and optionally push to the Hub.
# Use `push_to_hub` to directly push the transform to the Hub without saving it locally.
# ^ 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"

See this example for more info.

How do I switch from other augmentation libraries to Albumentations?

If you're switching from other libraries like torchvision or Kornia, you can refer to our Library Comparison guide. This guide provides:

  1. Mapping tables showing equivalent transforms between libraries
  2. Performance benchmarks demonstrating Albumentations's speed advantages
  3. Code examples for common switching scenarios
  4. Key differences in implementation and parameter handling

For a quick visual comparison of different augmentations, you can also use our interactive tool at Albumentations Explore to see how transforms affect images before implementing them.

For specific examples, see: