AlbumentationsExplore
DocumentationExploreAdoptionPricingBlog
GitHub

Affine3D

Targets:
volume
mask3d
keypoints
Image Types:uint8, float32

Apply a sampled 3D affine mapping to volume and mask3d by rotating, scaling, and shifting voxel coordinates for robust medical-imaging augmentation.

Affine3D resamples depth, height, and width jointly through Albucore warp_affine3d; it never treats depth as a batch axis. The output grid keeps the input (D, H, W) shape. It samples positive per-axis scales, rotations, and relative translations independently, then applies the same forward matrix to volume, mask3d, and xyz keypoints.

Arguments
rotate_range
dict[['x', 'y', 'z'], tuple[float, float]]
{"x":[0,0],"y":[0,0],"z":[0,0]}

Inclusive degree ranges around the x, y, and z axes. Axis names use the (x, y, z) voxel coordinate order. Default: all (0.0, 0.0).

scale_range
dict[['x', 'y', 'z'], tuple[float, float]]
{"x":[1,1],"y":[1,1],"z":[1,1]}

Positive multiplicative scale ranges for x, y, and z. 1.0 leaves an axis unchanged. Default: all (1.0, 1.0).

translate_percent_range
dict[['x', 'y', 'z'], tuple[float, float]]
{"x":[0,0],"y":[0,0],"z":[0,0]}

Relative translation ranges for x, y, and z. A value of 1.0 moves by the corresponding input-axis length. Default: all (0.0, 0.0).

interpolation
0 | 1
1

Volume interpolation: cv2.INTER_NEAREST or cv2.INTER_LINEAR. Default: cv2.INTER_LINEAR.

mask_interpolation
0 | 1
0

mask3d interpolation: cv2.INTER_NEAREST or cv2.INTER_LINEAR. Default: cv2.INTER_NEAREST.

border_mode
0 | 1
0

Border policy: cv2.BORDER_CONSTANT or cv2.BORDER_REPLICATE. Default: cv2.BORDER_CONSTANT.

fill
tuple[float, ...] | float
0

Constant fill for volume channels when border_mode is constant. Default: 0.

fill_mask
tuple[float, ...] | float
0

Constant fill for mask3d when border_mode is constant. Default: 0.

p
float
0.5

Probability of applying the transform. Default: 0.5.

Examples
>>> import albumentations as A
>>> import cv2
>>> import numpy as np
>>> volume = np.random.default_rng(137).random((16, 64, 96, 1), dtype=np.float32)
>>> mask3d = np.zeros((16, 64, 96), dtype=np.uint8)
>>> keypoints = np.array([[48.0, 32.0, 8.0]], dtype=np.float32)
>>> transform = A.Compose([
...     A.Affine3D(
...         rotate_range={"x": (-10.0, 10.0), "y": (-5.0, 5.0), "z": (-15.0, 15.0)},
...         scale_range={"x": (0.9, 1.1), "y": (0.9, 1.1), "z": (0.95, 1.05)},
...         translate_percent_range={"x": (-0.1, 0.1), "y": (-0.1, 0.1), "z": (-0.05, 0.05)},
...         interpolation=cv2.INTER_LINEAR,
...         mask_interpolation=cv2.INTER_NEAREST,
...         p=1.0,
...     ),
... ], keypoint_params=A.KeypointParams(coord_format="xyz"), strict=True)
>>> result = transform(volume=volume, mask3d=mask3d, keypoints=keypoints)
>>> result["volume"].shape, result["mask3d"].shape
((16, 64, 96, 1), (16, 64, 96))
Returns
dict[str, Any]

Augmented targets when the transform is executed through Compose.

Notes
  • Volume arrays are (D, H, W, C) and keypoints are (x, y, z). The centred forward matrix applies scale, then x-, y-, and z-axis rotations, then translation. One sampled matrix is shared across all elements of a sampled transform.
  • Scale factors must be positive, so this transform does not sample reflections. Use Flip3D for reflections.
  • Transform parameters use voxel coordinates only; physical spacing, orientation, and affine metadata remain unchanged.
See Also
  • Resize3D: Resize every spatial axis without sampling an affine matrix.
  • RandomRotate90_3D: Use exact right-angle rotations without interpolation.
  • Flip3D: Apply discrete axis reflections without resampling.