SafeRotate

Targets:
image
mask
bboxes
keypoints
volume
mask3d
Image Types:uint8, float32

Rotate the input inside the input's frame by an angle selected randomly from the uniform distribution.

This transformation ensures that the entire rotated image fits within the original frame by scaling it down if necessary. The resulting image maintains its original dimensions but may contain artifacts due to the rotation and scaling process.

Arguments
limit
tuple[float, float] | float
[-90,90]

Range from which a random angle is picked. If limit is a single float, an angle is picked from (-limit, limit). Default: (-90, 90)

interpolation
0 | 1 | 2 | 3 | 4
1

Flag that is used to specify the interpolation algorithm. Should be one of: cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_LANCZOS4. Default: cv2.INTER_LINEAR.

border_mode
0 | 1 | 2 | 3 | 4
0

Flag that is used to specify the pixel extrapolation method. Should be one of: cv2.BORDER_CONSTANT, cv2.BORDER_REPLICATE, cv2.BORDER_REFLECT, cv2.BORDER_WRAP, cv2.BORDER_REFLECT_101. Default: cv2.BORDER_REFLECT_101

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

Padding value if border_mode is cv2.BORDER_CONSTANT.

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

Padding value if border_mode is cv2.BORDER_CONSTANT applied for masks.

rotate_method
largest_box | ellipse
largest_box

Method to rotate bounding boxes. Should be 'largest_box' or 'ellipse'. Default: 'largest_box'

mask_interpolation
0 | 1 | 2 | 3 | 4
0

flag that is used to specify the interpolation algorithm for mask. Should be one of: cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_LANCZOS4. Default: cv2.INTER_NEAREST.

p
float
0.5

Probability of applying the transform. Default: 0.5.

Examples
>>> import numpy as np
>>> import albumentations as A
>>> # Create example data
>>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
>>> mask = np.random.randint(0, 2, (100, 100), dtype=np.uint8)
>>> bboxes = np.array([[10, 10, 50, 50], [40, 40, 80, 80]], dtype=np.float32)
>>> bbox_labels = [1, 2]  # Class labels for bounding boxes
>>> keypoints = np.array([[20, 30], [60, 70]], dtype=np.float32)
>>> keypoint_labels = [0, 1]  # Labels for keypoints
>>> # Define the transform
>>> transform = A.Compose([
...     A.SafeRotate(limit=45, p=1.0),
... ], bbox_params=A.BboxParams(coord_format='pascal_voc', label_fields=['bbox_labels']),
...    keypoint_params=A.KeypointParams(coord_format='xy', label_fields=['keypoint_labels']))
>>> # Apply the transform to all targets
>>> transformed = transform(
...     image=image,
...     mask=mask,
...     bboxes=bboxes,
...     bbox_labels=bbox_labels,
...     keypoints=keypoints,
...     keypoint_labels=keypoint_labels
... )
>>> rotated_image = transformed["image"]
>>> rotated_mask = transformed["mask"]
>>> rotated_bboxes = transformed["bboxes"]
>>> rotated_bbox_labels = transformed["bbox_labels"]
>>> rotated_keypoints = transformed["keypoints"]
>>> rotated_keypoint_labels = transformed["keypoint_labels"]
Notes
  • The rotation is performed around the center of the image.
  • After rotation, the image is scaled to fit within the original frame, which may cause some distortion.
  • The output image will always have the same dimensions as the input image.
  • Bounding boxes and keypoints are transformed along with the image.