
    hV                        S r SSKJr  SSKJrJr  SSKrSSKJ	r	J
r
Jr  SSKJrJr  SSKJrJr  SS	KJr  / S
Qr " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      rg)ah  Geometric transformations for flip and symmetry operations.

This module contains transforms that apply various flip and symmetry operations
to images and other target types. These transforms modify the geometric arrangement
of the input data while preserving the pixel values themselves.

Available transforms:
- VerticalFlip: Flips the input upside down (around the x-axis)
- HorizontalFlip: Flips the input left to right (around the y-axis)
- Transpose: Swaps rows and columns (flips around the main diagonal)
- D4: Applies one of eight possible square symmetry transformations (dihedral group D4)
- SquareSymmetry: Alias for D4 with a more intuitive name

These transforms are particularly useful for:
- Data augmentation to improve model generalization
- Addressing orientation biases in training data
- Working with data that doesn't have a natural orientation (e.g., satellite imagery)
- Exploiting symmetries in the problem domain

All transforms support various target types including images, masks, bounding boxes,
keypoints, volumes, and 3D masks, ensuring consistent transformation across
different data modalities.
    )annotations)AnyLiteralN)batch_transformhflipvflip)BaseTransformInitSchemaDualTransform)ALL_TARGETSd4_group_elements   )
functional)D4HorizontalFlipSquareSymmetry	TransposeVerticalFlipc                  l    \ rS rSrSr\rSS jrSS jrSS jr	SS jr
SS jrSS jrSS	 jrSS
 jrSrg)r   4   a  Flip the input vertically around the x-axis.

Args:
    p (float): Probability of applying the transform. Default: 0.5.

Targets:
    image, mask, bboxes, keypoints, volume, mask3d

Image types:
    uint8, float32

Note:
    - This transform flips the image upside down. The top of the image becomes the bottom and vice versa.
    - The dimensions of the image remain unchanged.
    - For multi-channel images (like RGB), each channel is flipped independently.
    - Bounding boxes are adjusted to match their new positions in the flipped image.
    - Keypoints are moved to their new positions in the flipped image.

Mathematical Details:
    1. For an input image I of shape (H, W, C), the output O is:
       O[i, j, k] = I[H-1-i, j, k] for all i in [0, H-1], j in [0, W-1], k in [0, C-1]
    2. For bounding boxes with coordinates (x_min, y_min, x_max, y_max):
       new_bbox = (x_min, H-y_max, x_max, H-y_min)
    3. For keypoints with coordinates (x, y):
       new_keypoint = (x, H-y)
    where H is the height of the image.

Examples:
    >>> import numpy as np
    >>> import albumentations as A
    >>> image = np.array([
    ...     [[1, 2, 3], [4, 5, 6]],
    ...     [[7, 8, 9], [10, 11, 12]]
    ... ])
    >>> transform = A.VerticalFlip(p=1.0)
    >>> result = transform(image=image)
    >>> flipped_image = result['image']
    >>> print(flipped_image)
    [[[ 7  8  9]
      [10 11 12]]
     [[ 1  2  3]
      [ 4  5  6]]]
    # The original image is flipped vertically, with rows reversed

c                    [        U5      $ )zApply the vertical flip to an image.

Args:
    img (np.ndarray): Image to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped image.

)r   selfimgparamss      e/var/www/fran/franai/venv/lib/python3.13/site-packages/albumentations/augmentations/geometric/flip.pyapplyVerticalFlip.applye        Sz    c                .    [         R                  " U5      $ )zApply the vertical flip to bounding boxes.

Args:
    bboxes (np.ndarray): Bounding boxes to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped bounding boxes.

)
fgeometricbboxes_vflipr   bboxesr   s      r   apply_to_bboxesVerticalFlip.apply_to_bboxesr        &&v..r   c                :    [         R                  " XS   S   5      $ )zApply the vertical flip to keypoints.

Args:
    keypoints (np.ndarray): Keypoints to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped keypoints.

shaper   )r!   keypoints_vflipr   	keypointsr   s      r   apply_to_keypointsVerticalFlip.apply_to_keypoints        )))G_Q5GHHr   c                .    [         R                  " U5      $ )zApply the vertical flip to a batch of images.

Args:
    images (np.ndarray): Images to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped images.

)r!   volume_vflipr   imagesr   s      r   apply_to_imagesVerticalFlip.apply_to_images   r'   r   c                (    U R                   " U40 UD6$ )zApply the vertical flip to a volume.

Args:
    volume (np.ndarray): Volume to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped volume.

r4   r   volumer   s      r   apply_to_volumeVerticalFlip.apply_to_volume        ##F5f55r   c                .    [         R                  " U5      $ )zApply the vertical flip to a batch of volumes.

Args:
    volumes (np.ndarray): Volumes to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped volumes.

)r!   volumes_vflipr   volumesr   s      r   apply_to_volumesVerticalFlip.apply_to_volumes        ''00r   c                (    U R                   " U40 UD6$ )zApply the vertical flip to a 3D mask.

Args:
    mask3d (np.ndarray): 3D mask to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped 3D mask.

r7   r   mask3dr   s      r   apply_to_mask3dVerticalFlip.apply_to_mask3d   r<   r   c                (    U R                   " U40 UD6$ )zApply the vertical flip to a 3D mask.

Args:
    masks3d (np.ndarray): 3D masks to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped 3D mask.

rA   r   masks3dr   s      r   apply_to_masks3dVerticalFlip.apply_to_masks3d   s     $$W777r    Nr   
np.ndarrayr   r   returnrQ   r$   rQ   r   r   rR   rQ   r,   rQ   r   r   rR   rQ   r3   rQ   r   r   rR   rQ   r9   rQ   r   r   rR   rQ   r@   rQ   r   r   rR   rQ   rF   rQ   r   r   rR   rQ   rL   rQ   r   r   rR   rQ   __name__
__module____qualname____firstlineno____doc__r   _targetsr   r%   r-   r4   r:   rA   rG   rM   __static_attributes__rO   r   r   r   r   4   s8    ,\ H/I/6168r   r   c                  l    \ rS rSrSr\rSS jrSS jrSS jr	SS jr
SS jrSS jrSS	 jrSS
 jrSrg)r      a  Flip the input horizontally around the y-axis.

Args:
    p (float): probability of applying the transform. Default: 0.5.

Targets:
    image, mask, bboxes, keypoints, volume, mask3d

Image types:
    uint8, float32

Examples:
    >>> import numpy as np
    >>> import albumentations as A
    >>>
    >>> # Prepare sample data
    >>> image = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
    >>> mask = np.array([[1, 0], [0, 1]])
    >>> bboxes = np.array([[0.1, 0.5, 0.3, 0.9]])  # [x_min, y_min, x_max, y_max] format
    >>> keypoints = np.array([[0.1, 0.5], [0.9, 0.5]])  # [x, y] format
    >>>
    >>> # Create a transform with horizontal flip
    >>> transform = A.Compose([
    ...     A.HorizontalFlip(p=1.0)  # Always apply for this example
    ... ], bbox_params=A.BboxParams(format='yolo', label_fields=[]),
    ...    keypoint_params=A.KeypointParams(format='normalized'))
    >>>
    >>> # Apply the transform
    >>> transformed = transform(image=image, mask=mask, bboxes=bboxes, keypoints=keypoints)
    >>>
    >>> # Get the transformed data
    >>> flipped_image = transformed["image"]  # Image flipped horizontally
    >>> flipped_mask = transformed["mask"]    # Mask flipped horizontally
    >>> flipped_bboxes = transformed["bboxes"]  # BBox coordinates adjusted for horizontal flip
    >>> flipped_keypoints = transformed["keypoints"]  # Keypoint x-coordinates flipped

c                    [        U5      $ )zApply the horizontal flip to an image.

Args:
    img (np.ndarray): Image to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped image.

)r   r   s      r   r   HorizontalFlip.apply   r   r   c                .    [         R                  " U5      $ )zApply the horizontal flip to bounding boxes.

Args:
    bboxes (np.ndarray): Bounding boxes to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped bounding boxes.

)r!   bboxes_hflipr#   s      r   r%   HorizontalFlip.apply_to_bboxes  r'   r   c                :    [         R                  " XS   S   5      $ )zApply the horizontal flip to keypoints.

Args:
    keypoints (np.ndarray): Keypoints to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped keypoints.

r)   r   )r!   keypoints_hflipr+   s      r   r-   !HorizontalFlip.apply_to_keypoints  r/   r   c                .    [         R                  " U5      $ )zApply the horizontal flip to a batch of images.

Args:
    images (np.ndarray): Images to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped images.

)r!   volume_hflipr2   s      r   r4   HorizontalFlip.apply_to_images  r'   r   c                (    U R                   " U40 UD6$ )zApply the horizontal flip to a volume.

Args:
    volume (np.ndarray): Volume to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped volume.

r7   r8   s      r   r:   HorizontalFlip.apply_to_volume+  r<   r   c                .    [         R                  " U5      $ )zApply the horizontal flip to a batch of volumes.

Args:
    volumes (np.ndarray): Volumes to be flipped.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Flipped volumes.

)r!   volumes_hflipr?   s      r   rA   HorizontalFlip.apply_to_volumes8  rC   r   c                (    U R                   " U40 UD6$ )zApply the horizontal flip to a 3D mask.

Args:
    mask3d (np.ndarray): 3D mask to be flipped.
    **params (Any): Additional parameters.

r7   rE   s      r   rG   HorizontalFlip.apply_to_mask3dE  s     ##F5f55r   c                (    U R                   " U40 UD6$ )zApply the horizontal flip to a 3D mask.

Args:
    masks3d (np.ndarray): 3D masks to be flipped.
    **params (Any): Additional parameters.

rJ   rK   s      r   rM   HorizontalFlip.apply_to_masks3dO  s     $$W777r   rO   NrP   rS   rT   rU   rV   rW   rX   rY   rZ   rO   r   r   r   r      s8    $L H/I/6168r   r   c                  :    \ rS rSrSr\rSS jrS	S jrS
S jr	Sr
g)r   iZ  a  Transpose the input by swapping its rows and columns.

This transform flips the image over its main diagonal, effectively switching its width and height.
It's equivalent to a 90-degree rotation followed by a horizontal flip.

Args:
    p (float): Probability of applying the transform. Default: 0.5.

Targets:
    image, mask, bboxes, keypoints, volume, mask3d

Image types:
    uint8, float32

Note:
    - The dimensions of the output will be swapped compared to the input. For example,
      an input image of shape (100, 200, 3) will result in an output of shape (200, 100, 3).
    - This transform is its own inverse. Applying it twice will return the original input.
    - For multi-channel images (like RGB), the channels are preserved in their original order.
    - Bounding boxes will have their coordinates adjusted to match the new image dimensions.
    - Keypoints will have their x and y coordinates swapped.

Mathematical Details:
    1. For an input image I of shape (H, W, C), the output O is:
       O[i, j, k] = I[j, i, k] for all i in [0, W-1], j in [0, H-1], k in [0, C-1]
    2. For bounding boxes with coordinates (x_min, y_min, x_max, y_max):
       new_bbox = (y_min, x_min, y_max, x_max)
    3. For keypoints with coordinates (x, y):
       new_keypoint = (y, x)

Examples:
    >>> import numpy as np
    >>> import albumentations as A
    >>> image = np.array([
    ...     [[1, 2, 3], [4, 5, 6]],
    ...     [[7, 8, 9], [10, 11, 12]]
    ... ])
    >>> transform = A.Transpose(p=1.0)
    >>> result = transform(image=image)
    >>> transposed_image = result['image']
    >>> print(transposed_image)
    [[[ 1  2  3]
      [ 7  8  9]]
     [[ 4  5  6]
      [10 11 12]]]
    # The original 2x2x3 image is now 2x2x3, with rows and columns swapped

c                .    [         R                  " U5      $ )zApply the transpose to an image.

Args:
    img (np.ndarray): Image to be transposed.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Transposed image.

)r!   	transposer   s      r   r   Transpose.apply  s     ##C((r   c                .    [         R                  " U5      $ )zApply the transpose to bounding boxes.

Args:
    bboxes (np.ndarray): Bounding boxes to be transposed.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Transposed bounding boxes.

)r!   bboxes_transposer#   s      r   r%   Transpose.apply_to_bboxes  s     **622r   c                .    [         R                  " U5      $ )zApply the transpose to keypoints.

Args:
    keypoints (np.ndarray): Keypoints to be transposed.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Transposed keypoints.

)r!   keypoints_transposer+   s      r   r-   Transpose.apply_to_keypoints  s     --i88r   rO   NrP   rS   rT   )r[   r\   r]   r^   r_   r   r`   r   r%   r-   ra   rO   r   r   r   r   Z  s    /b H)39r   r   c                  *  ^  \ rS rSrSr\r " S S\5      r S SU 4S jjjr	        SS jr
        SS jr        SS jr\" S	S
SS9SS j5       r\" S	SS
S9SS j5       r\" S	S
S
S9SS j5       r\" S	S
SS9SS j5       rSS jrSrU =r$ )r   i  a  Applies one of the eight possible D4 dihedral group transformations to a square-shaped input,
maintaining the square shape. These transformations correspond to the symmetries of a square,
including rotations and reflections.

The D4 group transformations include:
- 'e' (identity): No transformation is applied.
- 'r90' (rotation by 90 degrees counterclockwise)
- 'r180' (rotation by 180 degrees)
- 'r270' (rotation by 270 degrees counterclockwise)
- 'v' (reflection across the vertical midline)
- 'hvt' (reflection across the anti-diagonal)
- 'h' (reflection across the horizontal midline)
- 't' (reflection across the main diagonal)

Even if the probability (`p`) of applying the transform is set to 1, the identity transformation
'e' may still occur, which means the input will remain unchanged in one out of eight cases.

Args:
    p (float): Probability of applying the transform. Default: 1.0.

Targets:
    image, mask, bboxes, keypoints, volume, mask3d

Image types:
    uint8, float32

Note:
    - This transform is particularly useful for augmenting data that does not have a clear orientation,
      such as top-view satellite or drone imagery, or certain types of medical images.
    - The input image should be square-shaped for optimal results. Non-square inputs may lead to
      unexpected behavior or distortions.
    - When applied to bounding boxes or keypoints, their coordinates will be adjusted according
      to the selected transformation.
    - This transform preserves the aspect ratio and size of the input.

Examples:
    >>> import numpy as np
    >>> import albumentations as A
    >>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
    >>> transform = A.Compose([
    ...     A.D4(p=1.0),
    ... ])
    >>> transformed = transform(image=image)
    >>> transformed_image = transformed['image']
    # The resulting image will be one of the 8 possible D4 transformations of the input

c                      \ rS rSrSrg)D4.InitSchemai  rO   N)r[   r\   r]   r^   ra   rO   r   r   
InitSchemar     s    r   r   c                    > [         TU ]  US9  g )N)p)super__init__)r   r   	__class__s     r   r   D4.__init__  s     	1r   c                .    [         R                  " X5      $ )a  Apply the D4 transform to an image.

Args:
    img (np.ndarray): Image to be transformed.
    group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Transformed image.

)r!   d4)r   r   group_elementr   s       r   r   D4.apply  s    " }}S00r   c                .    [         R                  " X5      $ )a5  Apply the D4 transform to bounding boxes.

Args:
    bboxes (np.ndarray): Bounding boxes to be transformed.
    group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
    **params (Any): Additional parameters.

Returns:
    np.ndarray: Transformed bounding boxes.

)r!   	bboxes_d4)r   r$   r   r   s       r   r%   D4.apply_to_bboxes  s    " ##F::r   c                6    [         R                  " XUS   5      $ )zApply the D4 transform to keypoints.

Args:
    keypoints (np.ndarray): Keypoints to be transformed.
    group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
    **params (Any): Additional parameters.

r)   )r!   keypoints_d4)r   r,   r   r   s       r   r-   D4.apply_to_keypoints  s     &&yQQr   spatialTF)has_batch_dimhas_depth_dimc                (    U R                   " U40 UD6$ )zApply the D4 transform to a batch of images.

Args:
    images (np.ndarray): Images to be transformed.
    **params (Any): Additional parameters.

r   r2   s      r   r4   D4.apply_to_images(       zz&+F++r   c                (    U R                   " U40 UD6$ )zApply the D4 transform to a volume.

Args:
    volume (np.ndarray): Volume to be transformed.
    **params (Any): Additional parameters.

r   r8   s      r   r:   D4.apply_to_volume3  r   r   c                (    U R                   " U40 UD6$ )zApply the D4 transform to a batch of volumes.

Args:
    volumes (np.ndarray): Volumes to be transformed.
    **params (Any): Additional parameters.

r   r?   s      r   rA   D4.apply_to_volumes>  s     zz',V,,r   c                (    U R                   " U40 UD6$ )zApply the D4 transform to a 3D mask.

Args:
    mask3d (np.ndarray): 3D mask to be transformed.
    **params (Any): Additional parameters.

r   rE   s      r   rG   D4.apply_to_mask3dI  r   r   c                D    SU R                   R                  [        5      0$ )zGet the parameters for the D4 transform.

Returns:
    dict[str, Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]]: Parameters.

r   )random_generatorchoicer   )r   s    r   
get_paramsD4.get_paramsT  s%     T2299:KL
 	
r   rO   )r   )r   float)r   rQ   r   9Literal['e', 'r90', 'r180', 'r270', 'v', 'hvt', 'h', 't']r   r   rR   rQ   )r$   rQ   r   r   r   r   rR   rQ   )r,   rQ   r   r   r   r   rR   rQ   rU   rV   rW   rX   )rR   zDdict[str, Literal['e', 'r90', 'r180', 'r270', 'v', 'hvt', 'h', 't']])r[   r\   r]   r^   r_   r   r`   r	   r   r   r   r%   r-   r   r4   r:   rA   rG   r   ra   __classcell__)r   s   @r   r   r     s?   .` H, 
  11 Q1 	1
 
1&;; Q; 	;
 
;&RR QR 	R
 
R  Yd%H, I, Ye4H, I, Yd$G- H- Yd%H, I,	
 	
r   r   c                      \ rS rSrSrSrg)r   i`  u  Applies one of the eight possible square symmetry transformations to a square-shaped input.
This is an alias for D4 transform with a more intuitive name for those not familiar with group theory.

The square symmetry transformations include:
- Identity: No transformation is applied
- 90° rotation: Rotate 90 degrees counterclockwise
- 180° rotation: Rotate 180 degrees
- 270° rotation: Rotate 270 degrees counterclockwise
- Vertical flip: Mirror across vertical axis
- Anti-diagonal flip: Mirror across anti-diagonal
- Horizontal flip: Mirror across horizontal axis
- Main diagonal flip: Mirror across main diagonal

Args:
    p (float): Probability of applying the transform. Default: 1.0.

Targets:
    image, mask, bboxes, keypoints, volume, mask3d

Image types:
    uint8, float32

Note:
    - This transform is particularly useful for augmenting data that does not have a clear orientation,
      such as top-view satellite or drone imagery, or certain types of medical images.
    - The input image should be square-shaped for optimal results. Non-square inputs may lead to
      unexpected behavior or distortions.
    - When applied to bounding boxes or keypoints, their coordinates will be adjusted according
      to the selected transformation.
    - This transform preserves the aspect ratio and size of the input.

Examples:
    >>> import numpy as np
    >>> import albumentations as A
    >>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
    >>> transform = A.Compose([
    ...     A.SquareSymmetry(p=1.0),
    ... ])
    >>> transformed = transform(image=image)
    >>> transformed_image = transformed['image']
    # The resulting image will be one of the 8 possible square symmetry transformations of the input

rO   N)r[   r\   r]   r^   r_   ra   rO   r   r   r   r   `  s    *r   r   )r_   
__future__r   typingr   r   numpynpalbucorer   r   r   (albumentations.core.transforms_interfacer	   r
   $albumentations.core.type_definitionsr   r    r   r!   __all__r   r   r   r   r   rO   r   r   <module>r      sy   0 #   2 2
 'W8= W8tI8] I8XY9 Y9xg
 g
T+R +r   