Core API¶
Compose is the main public entry point. It accepts a list of recognized backend transform objects and builds a segmented torch.nn.Module around the supported (B, C, H, W) tensor contract.
Compose and FusedCompose refer to the same class. AugmentationSequential is another naming alias; these aliases do not imply complete behavioral compatibility with every native container option.
Choose a construction style¶
import torch
import torchvision.transforms.v2 as transforms
from fuse_augmentations import Compose
pipe = Compose(
[
transforms.RandomRotation(15),
transforms.RandomHorizontalFlip(p=0.5),
transforms.RandomAffine(degrees=0, scale=(0.9, 1.1)),
]
)
image = torch.rand(8, 3, 224, 224)
output = pipe(image)
print(pipe.fusion_plan)
Fusion plan for the native TorchVision pipeline
Use Compose.from_params for an augmentation-backend-free pipeline and Compose.from_config for declarative backend-specific construction. Both are documented in Configuration API.
Input and output forms¶
The standard call accepts a BCHW tensor. Set data_keys when positional auxiliary targets are present:
Use only explicitly supported spatial transforms with auxiliary targets
The runtime refusal policy is a finite class-name list. An unknown crop,
resize, or custom spatial transform can modify the image while leaving
masks, boxes, or keypoints stale. Treat every
`Unknown ... SPATIAL_KERNEL barrier` warning as unsafe with `data_keys`.
Read [Auxiliary targets](../guides/auxiliary-targets.md) before using this
path for training data.
import torch
import torchvision.transforms.v2 as transforms
from fuse_augmentations import Compose
safe_transforms = [
transforms.RandomRotation(15),
transforms.RandomHorizontalFlip(p=0.5),
]
pipe = Compose(
safe_transforms,
data_keys=["input", "mask", "bbox_xyxy", "keypoints"],
)
image = torch.rand(2, 3, 64, 64)
mask = torch.zeros(2, 1, 64, 64, dtype=torch.long)
boxes = torch.tensor([[[8.0, 8.0, 32.0, 32.0]]] * 2)
keypoints = torch.tensor([[[16.0, 16.0]]] * 2)
image_out, mask_out, boxes_out, keypoints_out = pipe(
image,
mask,
boxes,
keypoints,
)
output_backend="numpy" converts images and masks to channel-last NumPy arrays. Coordinate outputs remain tensors.
An image-only Albumentations pipeline additionally accepts pipe(image=hwc_array) and returns an Albumentations-style dictionary. Auxiliary keyword keys are not supported on that native NumPy path; use tensor inputs and data_keys instead.
Inspect a pipeline¶
for descriptor in pipe.fusion_plan_descriptors:
print(descriptor.kind, descriptor.transforms, descriptor.n_warps_saved)
output, last_matrix = pipe(image, return_matrix=True)
Segment descriptor and saved warp count for the pipeline
fusion_plan, fusion_plan_descriptors, and n_warps_saved describe the constructed plan. transform_matrix and return_matrix=True report only the most recent call's last matrix-producing segment, not a whole-pipeline composition.
Constructor options that change semantics¶
| Option | Effect |
|---|---|
reorder |
Preserves order by default; POINTWISE may move color operations to extend geometric runs |
randomness |
Preserves backend sampling by default; per_sample requests independent draws where supported |
execution |
Selects cv2 or torch execution for fused Albumentations geometry only |
interpolation, padding_mode |
Segment-level sampling choices for fused geometry |
clip_policy |
Controls boundaries/clamping in fused color runs |
mask_interpolation |
nearest for hard labels or bilinear for floating soft masks |
compile |
Opts eligible non-CPU torch warp cores into torch.compile |
antialias |
Enables supported downscale prefiltering |
substitute_passthrough |
Opts into behavior-changing registered passthrough substitutions |
pipeline_dtype |
"bfloat16" or "float16" low-precision execution for fused warp/color/LUT cores; default None |
Extra backend_kwargs are currently reserved and unused; do not rely on them as an extension mechanism.
Compose / FusedCompose¶
FusedCompose ¶
FusedCompose(transforms: list[object], reorder: ReorderPolicy = NONE, interpolation: InterpolationStr | None = None, padding_mode: ComposePaddingModeStr | None = None, data_keys: list[str] | None = None, output_backend: Literal['numpy', 'numpy_hwc', 'torch'] | None = None, randomness: RandomnessPolicy | Literal['backend', 'per_sample'] = BACKEND, execution: ExecutionStr = 'cv2', compile: bool = False, antialias: bool = False, substitute_passthrough: bool = False, clip_policy: ClipPolicyStr = 'final', mask_interpolation: MaskInterpolationStr = 'nearest', pipeline_dtype: PipelineDtypeStr | None = None, **backend_kwargs: object)
Bases: FactoriesMixin, IntrospectionMixin, Module
Fused augmentation pipeline that replaces the backend's native Compose.
Segments the transform list into fused geometric segments and passthrough transforms, then executes them sequentially. Consecutive geometric ops are grouped and executed as either:
- A :class:
~fuse_augmentations.affine.segment.FusedAffineSegment- when the run contains at least oneGEOMETRIC_INTERPop. Matrices are composed and a singlegrid_samplecall is used, eliminating redundant interpolation passes. - An :class:
~fuse_augmentations.affine.segment.ExactAffineSegment- when the run contains onlyGEOMETRIC_EXACTops (HFlip, VFlip). Transforms are applied viatensor.flipwith zero interpolation error.
SPATIAL_KERNEL and nonlinear POINTWISE transforms are passed through
to the backend adapter unchanged. Supported POINTWISE_LINEAR color
transforms, including standard Normalize, are folded into a color segment.
ReorderPolicy.POINTWISE is fully implemented: before segmentation,
POINTWISE and POINTWISE_LINEAR ops are bubbled past geometric ops
within each SPATIAL_KERNEL-bounded stretch, maximising the geometric
run length available for fusion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
transforms
|
list[object]
|
List of augmentation transform objects. |
required |
reorder
|
ReorderPolicy
|
Reorder policy applied before segmentation.
|
NONE
|
interpolation
|
InterpolationStr | None
|
Interpolation mode override for fused segments
( |
None
|
padding_mode
|
ComposePaddingModeStr | None
|
Padding mode override for fused segments
( |
None
|
data_keys
|
list[str] | None
|
List of key names describing positional arguments to
:meth: |
None
|
output_backend
|
Literal['numpy', 'numpy_hwc', 'torch'] | None
|
Target output format. |
None
|
randomness
|
RandomnessPolicy | Literal['backend', 'per_sample']
|
Batch randomness policy. |
BACKEND
|
execution
|
ExecutionStr
|
Warp strategy for the Albumentations fused segments.
|
'cv2'
|
compile
|
bool
|
Opt-in |
False
|
antialias
|
bool
|
Opt-in antialiasing for aggressive downscales. Off by default.
When |
False
|
substitute_passthrough
|
bool
|
When |
False
|
clip_policy
|
ClipPolicyStr
|
Clamp policy for fused color segments. |
'final'
|
mask_interpolation
|
MaskInterpolationStr
|
Auxiliary mask sampling mode. |
'nearest'
|
pipeline_dtype
|
PipelineDtypeStr | None
|
Optional |
None
|
**backend_kwargs
|
object
|
Reserved for backend-specific options (currently unused). |
{}
|
Initialize FusedCompose.
forward ¶
Apply the augmentation pipeline to an image batch and optional auxiliary targets.
Single-tensor mode (data_keys=None, default): accepts one image
tensor and returns one tensor or a NumPy ndarray when
output_backend="numpy". This is the backward-compatible path.
Multi-target mode (data_keys is set): accepts positional
arguments in the same order as data_keys. The first key must map
to the image ("input"); subsequent keys are auxiliary targets
("mask", "bbox_xyxy", "bbox_xywh", "keypoints").
Returns a tuple of tensors in data_keys order, or a bare tensor
when data_keys contains exactly one entry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Tensor
|
Positional tensors matching the |
()
|
return_matrix
|
bool
|
When |
False
|
Returns:
| Type | Description |
|---|---|
object
|
Single |
object
|
|
object
|
|
object
|
|
object
|
When |
object
|
|
object
|
geometric segment, or |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the number of positional arguments does not match
the number of |
Note
Passthrough (non-fused) transforms in the pipeline apply to the image only. Auxiliary targets skip passthrough segments and retain their values from the preceding fused segment. This is by design - passthrough backends do not expose a target-routing API.
output_backend conversion is applied per target in multi-target
mode: image and mask outputs are converted to the requested backend,
while coordinate targets (boxes, keypoints) remain tensors because the
channel-last image layout does not apply to them.
inverse ¶
Map a paired augmented tensor back to its original geometric frame.
Pass the matrix returned by the exact paired forward(...,
return_matrix=True) call. This avoids reading :attr:transform_matrix,
which is mutable compatibility state and therefore unsafe to pair with an
output from another concurrent call. The method supports one fused affine
or projective segment, including a chain already fused into that segment.
It applies one grid_sample to the image and routes declared masks,
boxes, and keypoints through the inverse pixel matrix.
Keypoints and masks recover to sampling precision. Bounding boxes are axis-aligned (AABB), so a forward-then-inverse box is exact only for axis-aligned transforms (flip, scale, translation) and inflates under a rotation, shear, or projective warp. The matrix is not validated against the paired image: a matrix from a different call yields silently wrong geometry, so always pass the matrix returned by the same forward call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
Tensor
|
Augmented |
required |
*auxiliary_targets
|
Tensor
|
Augmented targets in |
()
|
matrix
|
Tensor | None
|
Forward pixel matrix returned by the paired forward call. |
None
|
Returns:
| Type | Description |
|---|---|
object
|
The de-augmented image, or a tuple in |
object
|
auxiliary targets are supplied. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the image or matrix has an unsupported tensor shape or dtype. |
ValueError
|
If the pipeline has a non-invertible segment, no paired
matrix, or targets that do not match |
Examples:
>>> import torch
>>> from fuse_augmentations import Compose
>>> pipe = Compose.from_params(translate_x=(2.0, 2.0))
>>> image = torch.rand(1, 3, 8, 8)
>>> augmented, matrix = pipe(image, return_matrix=True)
>>> recovered = pipe.inverse(augmented, matrix=matrix)
>>> recovered.shape
torch.Size([1, 3, 8, 8])
NumPy converters¶
The converters are useful when conversion should be explicit rather than attached to a pipeline.
NumpyToTorchConverter ¶
Convert NumPy HWC/BHWC arrays to (batch_size, channels, height, width) torch tensors.
All pipeline outputs are (batch_size, channels, height, width) torch.Tensor regardless of backend. uint8
inputs are normalised to float32 in [0, 1] (÷255); uint16 likewise (÷65535); float32 inputs are
passed through unchanged. Any other dtype (float64, float16, signed integers) is cast to float32
WITHOUT rescaling — values keep their original range.
convert ¶
Convert a NumPy array (HW/HWC/BHWC) to a float32 torch tensor (BCHW).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
array
|
NDArray[Any]
|
NumPy array in channel-last layout:
|
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
|
Tensor
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
TorchToNumpyConverter ¶
Convert (batch_size, channels, height, width) torch tensors to NumPy HWC/BHWC arrays.
Single-image batches (1, channels, height, width) are squeezed to (height, width, channels) for convenience.
Multi-image batches produce (batch_size, height, width, channels).
convert ¶
Convert a torch tensor (BCHW) to a NumPy array (HWC or BHWC).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor
|
Tensor
|
|
required |
Returns:
| Type | Description |
|---|---|
NDArray[Any]
|
NumPy |
NDArray[Any]
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |