
    hO$                    R   S r SSKJr  SSKrSSKJr  SSKJrJrJrJ	r	J
r
  SSK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  \(       a  SS	KJr  / S
Qr\" S5      r\	" S\R6                  S9r\	" S\S\4   S9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5      r$SS jr%g)a  Module containing utility functions for augmentation operations.

This module provides a collection of helper functions and utilities used throughout
the augmentation pipeline. It includes functions for image loading, type checking,
error handling, mathematical operations, and decorators that add functionality to
other functions in the codebase. These utilities help ensure consistent behavior
and simplify common operations across different augmentation transforms.
    )annotationsNwraps)TYPE_CHECKINGAnyCallableTypeVarcast)is_grayscale_imageis_multispectral_imageis_rgb_image)Concatenate	ParamSpec)angle_to_2pi_range)Path)angle_2pi_rangenon_rgb_errorread_bgr_imageread_grayscaleread_rgb_imagePT)boundF.c                ^    [         R                  " [        U 5      [         R                  5      $ )zRead an image in BGR format from the specified path.

Args:
    path (str | Path): Path to the image file.

Returns:
    np.ndarray: Image in BGR format as a numpy array.

)cv2imreadstrIMREAD_COLORpaths    \/var/www/fran/franai/venv/lib/python3.13/site-packages/albumentations/augmentations/utils.pyr   r   ,   s     ::c$i!1!122    c                b    [        U 5      n[        R                  " U[        R                  5      $ )a	  Read an image in RGB format from the specified path.

This function reads an image in BGR format using OpenCV and then
converts it to RGB format.

Args:
    path (str | Path): Path to the image file.

Returns:
    np.ndarray: Image in RGB format as a numpy array.

)r   r   cvtColorCOLOR_BGR2RGB)r!   images     r"   r   r   9   s%     4 E<<s0011r#   c                ^    [         R                  " [        U 5      [         R                  5      $ )zRead a grayscale image from the specified path.

Args:
    path (str | Path): Path to the image file.

Returns:
    np.ndarray: Grayscale image as a numpy array.

)r   r   r   IMREAD_GRAYSCALEr    s    r"   r   r   J   s     ::c$i!5!566r#   c                4   ^  [        T 5      SU 4S jj5       nU$ )u   Decorator to normalize angle values to the range [0, 2π).

This decorator wraps a function that processes keypoints, ensuring that
angle values (stored in the 4th column, index 3) are normalized to the
range [0, 2π) after the wrapped function executes.

Args:
    func (Callable): Function that processes keypoints and returns a numpy array.
        The function should take a keypoints array as its first parameter.

Returns:
    Callable: Wrapped function that normalizes angles after processing keypoints.

c                   > T" U /UQ70 UD6n[        U5      S:  a,  UR                  S   S:  a  [        US S 2S4   5      US S 2S4'   U$ )Nr         )lenshaper   )	keypointsargskwargsresultfuncs       r"   wrapped_function)angle_2pi_range.<locals>.wrapped_functioni   sP    i1$1&1v;?v||A2-fQTl;F1a4Lr#   )r0   
np.ndarrayr1   zP.argsr2   zP.kwargsreturnr7   r   )r4   r5   s   ` r"   r   r   W   s#    $ 4[  r#   c                    [        U 5      (       d7  Sn[        U 5      (       a  US-  n[        U 5      (       a  US-  n[        U5      eg)a  Check if the input image is RGB and raise a ValueError if it's not.

This function is used to ensure that certain transformations are only applied to
RGB images. It provides helpful error messages for grayscale and multi-spectral images.

Args:
    image (np.ndarray): The input image to check. Expected to be a numpy array
                        representing an image.

Raises:
    ValueError: If the input image is not an RGB image (i.e., does not have exactly 3 channels).
                The error message includes specific instructions for grayscale images
                and a note about incompatibility with multi-spectral images.

Note:
    - RGB images are expected to have exactly 3 channels.
    - Grayscale images (1 channel) will trigger an error with conversion instructions.
    - Multi-spectral images (more than 3 channels) will trigger an error stating incompatibility.

Example:
    >>> import numpy as np
    >>> rgb_image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
    >>> non_rgb_error(rgb_image)  # No error raised
    >>>
    >>> grayscale_image = np.random.randint(0, 256, (100, 100), dtype=np.uint8)
    >>> non_rgb_error(grayscale_image)  # Raises ValueError with conversion instructions
    >>>
    >>> multispectral_image = np.random.randint(0, 256, (100, 100, 5), dtype=np.uint8)
    >>> non_rgb_error(multispectral_image)  # Raises ValueError stating incompatibility

z,This transformation expects 3-channel imagesz[
You can convert your grayscale image to RGB using cv2.cvtColor(image, cv2.COLOR_GRAY2RGB))z?
This transformation cannot be applied to multi-spectral imagesN)r   r   r   
ValueError)r'   messages     r"   r   r   s   sQ    @ @e$$uuG!%((YYG!! r#   c           	        ^^ [        UU4S jU  5       5      (       d  [        SU ST ST S35      eU S   U S   ::  d  [        U< SU  35      eg	)
a  Checks if the given value is within the specified bounds

Args:
    value (tuple[float, float]): The value to check and convert. Can be a single float or a tuple of floats.
    lower_bound (float): The lower bound for the range check.
    upper_bound (float): The upper bound for the range check.
    name (str | None): The name of the parameter being checked. Used for error messages.

Raises:
    ValueError: If the value is outside the bounds or if the tuple values are not ordered correctly.

c              3  N   >#    U  H  nTUs=:*  =(       a    T:*  Os  v   M     g 7fN ).0xlower_boundupper_bounds     r"   	<genexpr>check_range.<locals>.<genexpr>   s!     >1{a..;..s   "%zAll values in z must be within [z, z] for tuple inputs.r   r,   z2 tuple values must be ordered as (min, max). Got: N)allr:   )valuerB   rC   names    `` r"   check_rangerI      sg     >>>>>$/@RP[}\opqq8uQxD8#UV[U\]^^  r#   c                  ^    \ rS rSrSSS j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)PCA   Nc                b    Ub  US::  a  [        S5      eXl        S U l        S U l        S U l        g )Nr   z/Number of components must be greater than zero.)r:   n_componentsmeancomponents_explained_variance_)selfrN   s     r"   __init__PCA.__init__   s8    #(9NOO('+	.26: r#   c                   UR                  [        R                  SS9nUR                  u  p#U R                  c  [        X#5      U l        [        R                  " US U R                  S9u  U l        pEX@l	        UR                  5       U l        g )NFcopy)rO   maxComponents)astypenpfloat64r/   rN   minr   PCACompute2rO   rP   flattenrQ   )rR   rA   	n_samples
n_featureseigenvectorseigenvaluess         r"   fitPCA.fit   sv    HHRZZeH, !	 $ #I :D/2qt[_[l[l/m,	<'#.#6#6#8 r#   c                    U R                   c  [        S5      eUR                  [        R                  SS9n[
        R                  " XR                  U R                   5      $ )NgThis PCA instance is not fitted yet. Call 'fit' with appropriate arguments before using this estimator.FrV   )rP   r:   rY   rZ   r[   r   
PCAProjectrO   rR   rA   s     r"   	transformPCA.transform   sT    #U  HHRZZeH,~~aD,<,<==r#   c                F    U R                  U5        U R                  U5      $ r>   )rc   ri   rh   s     r"   fit_transformPCA.fit_transform   s    ~~a  r#   c                    U R                   c  [        S5      e[        R                  " XR                  U R                   5      $ )Nrf   )rP   r:   r   PCABackProjectrO   rh   s     r"   inverse_transformPCA.inverse_transform   s@    #U  !!!YY0@0@AAr#   c                    U R                   c  [        S5      e[        R                  " U R                   5      nU R                   U-  $ )NzdThis PCA instance is not fitted yet. Call 'fit' with appropriate arguments before using this method.)rQ   r:   rZ   sum)rR   total_variances     r"   explained_variance_ratioPCA.explained_variance_ratio   sE    ##+v   8 89''.88r#   c                J    [         R                  " U R                  5       5      $ r>   )rZ   cumsumru   )rR   s    r"   #cumulative_explained_variance_ratio'PCA.cumulative_explained_variance_ratio   s    yy66899r#   )rP   rQ   rO   rN   r>   )rN   z
int | Noner8   None)rA   r7   r8   r{   )rA   r7   r8   r7   )r8   r7   )__name__
__module____qualname____firstlineno__rS   rc   ri   rl   rp   ru   ry   __static_attributes__r?   r#   r"   rK   rK      s&    ;
9>!B9:r#   rK   c                   ^  SU 4S jjnU$ )Nc                b   >^  [         R                  " T 5      SU U4S jj5       n[        SU5      $ )Nc                    > [        U 5      S:  a  U S   nOTU;   a  UT   nO[        ST 35      e[        U5      S:X  a  U$ T" U 0 UD6$ )Nr   zMissing required argument: )r.   r:   )r1   r2   arrayr4   
param_names      r"   wrapper6handle_empty_array.<locals>.decorator.<locals>.wrapper   s^     4y1}Qv%z* #>zl!KLL5zQ(((r#   r   )r1   r   r2   r   r8   r   )	functoolsr   r
   )r4   r   r   s   ` r"   	decorator%handle_empty_array.<locals>.decorator   s-    			) 
	) C!!r#   )r4   r   r8   r   r?   )r   r   s   ` r"   handle_empty_arrayr      s    "$ r#   )r!   z
str | Pathr8   r7   )r4   0Callable[Concatenate[np.ndarray, P], np.ndarray]r8   r   )r'   r7   r8   r{   )
rG   ztuple[float, float]rB   floatrC   r   rH   z
str | Noner8   r{   )r   r   r8   zCallable[[F], F])&__doc__
__future__r   r   r   typingr   r   r   r	   r
   r   numpyrZ   albucore.utilsr   r   r   typing_extensionsr   r   #albumentations.core.keypoints_utilsr   pathlibr   __all__r   ndarrayr   r   r   r   r   r   r   rI   rK   r   r?   r#   r"   <module>r      s    #   > > 
  
 5 B cNCrzz"CxS)*
32"
7
:58'"T_&3: 3:lr#   