U
    h2
                 %   @  s	  d dl mZ d dlmZ d dlmZmZmZ d dlm	Z	 d dl
Z
d dlZd dlZd dlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm Z  d dl!m"  m#  m$Z% d dl&m'Z' d dl(m)Z)m*Z*m+Z+ d d	l,m-Z-m.Z. d d
l/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7 dddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/g%Z8d0d0d0d0d0d1d2d3Z9d0d0d0d0d0d1d4d5Z:ed0d0d0d0d0d1d6d&Z;edad0d8d0d9d:d'Z<e eed0d;d0d<d=d%Z=dbd0d>d0d?d@dAZ>dcd0d>d0d?dBdCZ?d0d>dDdEdFdGdHZ@ddd>dId>dJdKdLZAe eded0d>dOdDd0dPdQdZBe ed0dRdRd0dSdTd#ZCed0d0d0dUdVd"ZDe ed0dWdXd0dYdZdZEeed0d0d0d[d\dZFe ed0d8d]d0d^d_dZGe d0dWdWd0d`dadZHe d0dWdWd0d`dbdZIe ed0d8d8d8dcd8dWddd0de	dfdZJe eed0dWdWdddgd0dhdidZKe ed0djd8dkdld0dmdndZLe ed0dXd8dcdld0dmdodZMe ed0dpd0d0dqdrdZNe eed0dld0dsdtdZOd0d0dudvd ZPd0d0d0dwdxdZQed0dWd0dydzdZRdfd0dWdWdDd0d}d~dZSeedgd0dWdWdd0ddd!ZTd0d0duddZUe ed0d0duddZVed0d0duddZWd0d0duddZXd0d0duddZYed0d0duddZZd0d8dd0ddd*Z[dhd0d8d0dddZ\ee
j]e
j^fd0dWd8d8d0dddZ_dddddd$Z`did0d0dd0ddd)Zaeeed0d0d0dddZbed0d0ddddZced0dWd0dddZdeedjd0dWdWd0dddZed0dWd0dddZfd0dWd0dddZged0d8ddId8d0ddd(Zheeedkd0d8dWdWd8d0ddd+Zied0d0dd0dddZjeeed0d>d>d>dd0dddZkd0ddddZldlddddddZme ed0dWdWdWdWd8d0ddd,Znd0d0d0d8d8d8d0dĜddƄZoed0d0d0d[dd-Zped0d0d0d[dd.Zqd0d0dd0dʜdd̄Zre*d0d0ddXd0d͜ddτZsdddgdddgdddgdddgdddgdddgdddgdddgdddgdddgdddgdddgdddgdddgdddgdddgd ddgdddgdddgddd	gd
ddgdddgdddgdddgdddgddddgdddgdddgddd gd!d"d#gdd$dgd%d&d'gd(d)d*gd+d,d-gd.d/d0gd1d2d3gd4d5d6gd7d8d9gd:d;d<gd=d>dgd?d@dAgdBdCdDgdEdCdFgdGdCdHgdIdCdJgdKdCdLgdMdCdNgdOdCdPgdQdRZteed0d8dSd0dTdUdVZudmdXdWdWdWd0dYdZd/Zved0d0d0d[d\d]Zwd0d0d0d0d^d_d`ZxdS (n      )annotations)defaultdict)AnyLiteralSequence)warnN)MAX_VALUES_BY_DTYPEadd	add_arrayadd_weightedclipclipped
float32_io
from_floatget_num_channelsis_grayscale_imageis_rgb_imagemaybe_process_in_chunksmultiplymultiply_addnormalize_per_imagepreserve_channel_dimto_floatuint8_io)random_utils)PCAhandle_empty_arraynon_rgb_error)bboxes_from_masksmasks_from_bboxes)EIGHTMONO_CHANNEL_DIMENSIONSNUM_MULTI_CHANNEL_DIMENSIONSNUM_RGB_CHANNELS	ColorType	ImageModePlanckianJitterModeSpatterModeadd_fogadd_rain
add_shadow
add_graveladd_snow_bleachadd_snow_textureadd_sun_flare_overlayadd_sun_flare_physics_basedadjust_brightness_torchvisionadjust_contrast_torchvisionadjust_hue_torchvisionadjust_saturation_torchvisionbrightness_contrast_adjustchannel_shuffleclaheconvolve	downscaleequalize	fancy_pcagamma_transformimage_compressioninvert	iso_noiselinear_transformation_rgbmove_tone_curvenoop	posterize	shift_hsvsolarizesuperpixelsswap_tiles_on_imageto_grayunsharp_maskchromatic_aberrationerodedilategenerate_approx_gaussian_noise
np.ndarray)img	hue_shift	sat_shift	val_shiftreturnc           	      C  s   | j }t| tj} t| \}}}|dkr`tjddtjd}t|| d	|}t
||}t||}t||}t|||f	|} t| tjS )Nr      dtype   )rU   cv2cvtColorCOLOR_RGB2HSVsplitnparangeint16modastypeLUTr	   mergeCOLOR_HSV2RGB)	rN   rO   rP   rQ   rU   huesatvalZlut_hue rf   K/tmp/pip-unpacked-wheel-e8onvpoz/albumentations/augmentations/functional.py_shift_hsv_uint8[   s    

rh   c                 C  sp   t | t j} t | \}}}|dkr>t ||}t|d}t||}t||}t |||f} t | t jS )Nr   h  )	rW   rX   rY   rZ   r	   r[   r^   ra   rb   )rN   rO   rP   rQ   rc   rd   re   rf   rf   rg   _shift_hsv_non_uint8q   s    

rj   c                 C  s   |dkr|dkr|dkr| S t | }|rZ|dks8|dkrLd}d}tddd t| tj} | jtjkrvt| |||} nt	| |||} |rt| tj
S | S )Nr   zqHueSaturationValue: hue_shift and sat_shift are not applicable to grayscale image. Set them to 0 or use RGB image   
stacklevel)r   r   rW   rX   COLOR_GRAY2RGBrU   r[   uint8rh   rj   COLOR_RGB2GRAY)rN   rO   rP   rQ   Zis_grayrf   rf   rg   rC      s        int)rN   	thresholdrR   c                   s   | j }t|  |tjkrv fddtt d D }| j}t| tj	||d} t
|t
| jkrrt| d} | S |  }| k} ||  ||< |S )zInvert all pixel values above a threshold.

    Args:
        img: The image to solarize.
        threshold: All pixels above this grayscale level are inverted.

    Returns:
        Solarized image.

    c                   s    g | ]}|k r|n | qS rf   rf   .0iZmax_valrs   rf   rg   
<listcomp>   s     zsolarize.<locals>.<listcomp>   rT   )rU   r   r[   ro   rangerr   shaperW   r`   arraylenexpand_dimscopy)rN   rs   rU   lutZ
prev_shape
result_imgZcondrf   rw   rg   rD      s    
 z$Literal[(0, 1, 2, 3, 4, 5, 6, 7, 8)])rN   bitsrR   c                 C  s,  t |}|jrt|dkrx|dkr.t | S |tkr:| S t jddt jd}t dd|  d  }||M }t| |S t 	| }t
|D ]\}}|dkrt | d|f |d|f< q|tkr| d|f  |d|f< qt jddt jd}t dd|  d  }||M }t| d|f ||d|f< q|S )zReduce the number of bits for each color channel.

    Args:
        img: image to posterize.
        bits: number of high bits. Must be in range [0, 8]

    Returns:
        Image with reduced color channels.

    ry   r   rS   rT   rk      .)r[   ro   r|   r~   
zeros_liker    r\   rW   r`   
empty_like	enumerater   )rN   r   Z
bits_arrayr   maskr   rv   Zchannel_bitsrf   rf   rg   rB      s*    


znp.ndarray | None)rN   r   rR   c                 C  s   t | gdg|dgd }dd |D }t|dkr>|  S t|d d d }|s`|  S tjdtjd	}|d
 }t	dD ]"}t
|| d||< ||| 7 }qt | t|S )Nr   rS   r   rS   c                 S  s   g | ]}|r|qS rf   rf   )ru   _frf   rf   rg   rx      s      z!_equalize_pil.<locals>.<listcomp>ry   rz      rT   rk   )rW   calcHistravelr~   r   r[   sumemptyro   r{   minr`   r}   )rN   r   	histogramhstepr   nrv   rf   rf   rg   _equalize_pil   s    r   c           
      C  s   |d krt | S t | gdg|dgd }d}|D ]}|dkrF qP|d7 }q6t|d}t|}|| |kr|t| |S d|||   }d}tjdtj	d}t
|d t|D ](}	|||	 7 }tt|| tj	||	< qt | |S )Nr   rS   r   ry   r   g     o@rT   )rW   ZequalizeHistr   r   r   r[   r   	full_likezerosro   r{   r~   r   roundr`   )
rN   r   r   rv   re   totalscaleZ_sumr   idxrf   rf   rg   _equalize_cv   s&    



r   boolNone)rN   r   by_channelsrR   c                 C  sT   |d k	rPt |r0t| r0td| j d|j |sPt|sPd|j }t|d S )NzWrong mask shape. Image shape: z. Mask shape: zAWhen by_channels=False only 1-channel mask supports. Mask shape: )r   r   
ValueErrorr|   )rN   r   r   msgrf   rf   rg   _check_preconditions  s    r   z
int | None)r   rv   rR   c                 C  s8   | d krd S |  tj} t| s(|d kr,| S | d|f S N.)r_   r[   ro   r   )r   rv   rf   rf   rg   _handle_mask"  s    r   cvTr%   )rN   r   moder   rR   c                 C  s   t | || |dkrtnt}t| r2|| t|S |sht| tj}||d t||d< t|tjS t	
| }ttD ](}t||}|| d|f ||d|f< qz|S )aa  Apply histogram equalization to the input image.

    This function enhances the contrast of the input image by equalizing its histogram.
    It supports both grayscale and color images, and can operate on individual channels
    or on the luminance channel of the image.

    Args:
        img (np.ndarray): Input image. Can be grayscale (2D array) or RGB (3D array).
        mask (np.ndarray | None): Optional mask to apply the equalization selectively.
            If provided, must have the same shape as the input image. Default: None.
        mode (ImageMode): The backend to use for equalization. Can be either "cv" for
            OpenCV or "pil" for Pillow-style equalization. Default: "cv".
        by_channels (bool): If True, applies equalization to each channel independently.
            If False, converts the image to YCrCb color space and equalizes only the
            luminance channel. Only applicable to color images. Default: True.

    Returns:
        np.ndarray: Equalized image. The output has the same dtype as the input.

    Raises:
        ValueError: If the input image or mask have invalid shapes or types.

    Note:
        - If the input image is not uint8, it will be temporarily converted to uint8
          for processing and then converted back to its original dtype.
        - For color images, when by_channels=False, the image is converted to YCrCb
          color space, equalized on the Y channel, and then converted back to RGB.
        - The function preserves the original number of channels in the image.

    Example:
        >>> import numpy as np
        >>> import albumentations as A
        >>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
        >>> equalized = A.equalize(image, mode="cv", by_channels=True)
        >>> assert equalized.shape == image.shape
        >>> assert equalized.dtype == image.dtype
    Zpil.r   .)r   r   r   r   r   rW   rX   ZCOLOR_RGB2YCrCbZCOLOR_YCrCb2RGBr[   r   r{   r#   )rN   r   r   r   functionr   rv   Z_maskrf   rf   rg   r9   /  s    -

float | np.ndarray)rN   low_yhigh_yrR   c                   s   t ddd}ddddddd}t }t |rdt |rdtt ||||t j}t |S t	|t j
rt	|t j
rtt ||d	d	t jf ||jt jt fd
dt|D S tdt| dt| d	S )a  Rescales the relationship between bright and dark areas of the image by manipulating its tone curve.

    Args:
        img: np.ndarray. Any number of channels
        low_y: per-channel or single y-position of a Bezier control point used
            to adjust the tone curve, must be in range [0, 1]
        high_y: per-channel or single y-position of a Bezier control point used
            to adjust image tone curve, must be in range [0, 1]

                  ?rS   rM   r   )tr   r   rR   c                 S  s<   d|  }d|d  |  | d| | d  |  | d  d S )Nry      rk   r   rf   )r   r   r   Zone_minus_trf   rf   rg   evaluate_bez  s    z%move_tone_curve.<locals>.evaluate_bezNc                   s.   g | ]&}t  d d d d |f | qS N)rW   r`   rt   rN   Zlutsrf   rg   rx     s     z#move_tone_curve.<locals>.<listcomp>z?low_y and high_y must both be of type float or np.ndarray. Got z and )r[   linspacer   Zisscalarr   Zrintro   rW   r`   
isinstanceZndarraynewaxisTra   r{   	TypeErrortype)rN   r   r   r   r   num_channelsr   rf   r   rg   r@   p  s    *)rN   transformation_matrixrR   c                 C  s   t | |S r   )rW   Z	transform)rN   r   rf   rf   rg   r?     s    floatztuple[int, int])rN   
clip_limittile_grid_sizerR   c                 C  sr   |   } tj||d}t| r(|| S t| tj} || dddddf | dddddf< t| tjS )a,  Apply Contrast Limited Adaptive Histogram Equalization (CLAHE) to the input image.

    This function enhances the contrast of the input image using CLAHE. For color images,
    it converts the image to the LAB color space, applies CLAHE to the L channel, and then
    converts the image back to RGB.

    Args:
        img (np.ndarray): Input image. Can be grayscale (2D array) or RGB (3D array).
        clip_limit (float): Threshold for contrast limiting. Higher values give more contrast.
        tile_grid_size (tuple[int, int]): Size of grid for histogram equalization.
            Width and height of the grid.

    Returns:
        np.ndarray: Image with CLAHE applied. The output has the same dtype as the input.

    Note:
        - If the input image is float32, it's temporarily converted to uint8 for processing
          and then converted back to float32.
        - For color images, CLAHE is applied only to the luminance channel in the LAB color space.

    Raises:
        ValueError: If the input image is not 2D or 3D.

    Example:
        >>> import numpy as np
        >>> img = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
        >>> result = clahe(img, clip_limit=2.0, tile_grid_size=(8, 8))
        >>> assert result.shape == img.shape
        >>> assert result.dtype == img.dtype
    )Z	clipLimitZtileGridSizeNr   )r   rW   ZcreateCLAHEr   applyrX   COLOR_RGB2LABZCOLOR_LAB2RGB)rN   r   r   Z	clahe_matrf   rf   rg   r6     s    !
.)rN   kernelrR   c                 C  s   t tjd|d}|| S )Nrz   )Zddepthr   )r   rW   Zfilter2D)rN   r   Zconv_fnrf   rf   rg   r7     s    zLiteral[('.jpg', '.webp')])rN   quality
image_typerR   c                 C  sP   |dkrt j}n|dkr t j}ntdt || t||f\}}t |t jS )Nz.jpgz.webpz@Only '.jpg' and '.webp' compression transforms are implemented. )rW   ZIMWRITE_JPEG_QUALITYZIMWRITE_WEBP_QUALITYNotImplementedErrorZimencoderr   ZimdecodeZIMREAD_UNCHANGED)rN   r   r   Zquality_flag_Zencoded_imgrf   rf   rg   r<     s    )rN   
snow_pointbrightness_coeffrR   c                 C  s   t tj }||d 9 }||d 7 }t| tj}tj|tjd}|dddddf |dddddf |k   |9  < t|dddddf tj|dddddf< tj|tjd}t|tj	S )a  Adds a simple snow effect to the image by bleaching out pixels.

    This function simulates a basic snow effect by increasing the brightness of pixels
    that are above a certain threshold (snow_point). It operates in the HLS color space
    to modify the lightness channel.

    Args:
        img (np.ndarray): Input image. Can be either RGB uint8 or float32.
        snow_point (float): A float in the range [0, 1], scaled and adjusted to determine
            the threshold for pixel modification. Higher values result in less snow effect.
        brightness_coeff (float): Coefficient applied to increase the brightness of pixels
            below the snow_point threshold. Larger values lead to more pronounced snow effects.
            Should be greater than 1.0 for a visible effect.

    Returns:
        np.ndarray: Image with simulated snow effect. The output has the same dtype as the input.

    Note:
        - This function converts the image to the HLS color space to modify the lightness channel.
        - The snow effect is created by selectively increasing the brightness of pixels.
        - This method tends to create a 'bleached' look, which may not be as realistic as more
          advanced snow simulation techniques.
        - The function automatically handles both uint8 and float32 input images.

    The snow effect is created through the following steps:
    1. Convert the image from RGB to HLS color space.
    2. Adjust the snow_point threshold.
    3. Increase the lightness of pixels below the threshold.
    4. Convert the image back to RGB.

    Mathematical Formulation:
        Let L be the lightness channel in HLS space.
        For each pixel (i, j):
        If L[i, j] < snow_point:
            L[i, j] = L[i, j] * brightness_coeff

    Examples:
        >>> import numpy as np
        >>> import albumentations as A
        >>> image = np.random.randint(0, 256, [100, 100, 3], dtype=np.uint8)
        >>> snowy_image = A.functional.add_snow_v1(image, snow_point=0.5, brightness_coeff=1.5)

    References:
        - HLS Color Space: https://en.wikipedia.org/wiki/HSL_and_HSV
        - Original implementation: https://github.com/UjjwalSaxena/Automold--Road-Augmentation-Library
    rk   r   rT   Nry   )
r   r[   ro   rW   rX   COLOR_RGB2HLSr}   float32r   COLOR_HLS2RGB)rN   r   r   	max_value	image_hlsrf   rf   rg   r,     s    0
80c                 C  sL  t tj }t| tjtj}t|dddddf d||   d||dddddf< t	j
| jdd ddd}tj|dddd	}| jd }tdd
|ddtjf }||9 }t|gd | | tj}t|d|dd}	t|	d}
t|	d|
d| d}	t|	tjtj}	t	| jdd dk}|||g|	|< |	S )a#	  Add a realistic snow effect to the input image.

    This function simulates snowfall by applying multiple visual effects to the image,
    including brightness adjustment, snow texture overlay, depth simulation, and color tinting.
    The result is a more natural-looking snow effect compared to simple pixel bleaching methods.

    Args:
        img (np.ndarray): Input image in RGB format.
        snow_point (float): Coefficient that controls the amount and intensity of snow.
            Should be in the range [0, 1], where 0 means no snow and 1 means maximum snow effect.
        brightness_coeff (float): Coefficient for brightness adjustment to simulate the
            reflective nature of snow. Should be in the range [0, 1], where higher values
            result in a brighter image.

    Returns:
        np.ndarray: Image with added snow effect. The output has the same dtype as the input.

    Note:
        - The function first converts the image to HSV color space for better control over
          brightness and color adjustments.
        - A snow texture is generated using Gaussian noise and then filtered for a more
          natural appearance.
        - A depth effect is simulated, with more snow at the top of the image and less at the bottom.
        - A slight blue tint is added to simulate the cool color of snow.
        - Random sparkle effects are added to simulate light reflecting off snow crystals.

    The snow effect is created through the following steps:
    1. Brightness adjustment in HSV space
    2. Generation of a snow texture using Gaussian noise
    3. Application of a depth effect to the snow texture
    4. Blending of the snow texture with the original image
    5. Addition of a cool blue tint
    6. Addition of sparkle effects

    Examples:
        >>> import numpy as np
        >>> import albumentations as A
        >>> image = np.random.randint(0, 256, [100, 100, 3], dtype=np.uint8)
        >>> snowy_image = A.functional.add_snow_v2(image, snow_coeff=0.5, brightness_coeff=0.2)

    Note:
        This function works with both uint8 and float32 image types, automatically
        handling the conversion between them.

    References:
        - Perlin Noise: https://en.wikipedia.org/wiki/Perlin_noise
        - HSV Color Space: https://en.wikipedia.org/wiki/HSL_and_HSV
    Nrk   ry   r         ?g333333?)sizelocr   r   r   sigmaXZsigmaY皙?r   )g333333?g      ?ry   g333333?g333333?gGz?)r   r[   ro   rW   rX   rY   r_   r   r   r   normalr|   GaussianBlurr   r   dstackaddWeightedr   rb   random)rN   r   r   r   Zimg_hsvZsnow_textureZrowsZdepth_effectZ
snow_layerZimg_with_snowZ	blue_tintZsparklerf   rf   rg   r-     s     2
>
 ztuple[int, int, int]zlist[tuple[int, int]])	rN   slantdrop_length
drop_width
drop_color
blur_valuebrightness_coefficient
rain_dropsrR   c                 C  s   |D ]2\}}	|| }
|	| }t | ||	f|
|f|| qt | ||f} t | t jtj}|dddddf  |9  < t |tjt j	S )ad  Adds rain drops to the image.

    Args:
        img (np.ndarray): Input image.
        slant (int): The angle of the rain drops.
        drop_length (int): The length of each rain drop.
        drop_width (int): The width of each rain drop.
        drop_color (tuple[int, int, int]): The color of the rain drops in RGB format.
        blur_value (int): The size of the kernel used to blur the image. Rainy views are blurry.
        brightness_coefficient (float): Coefficient to adjust the brightness of the image. Rainy days are usually shady.
        rain_drops (list[tuple[int, int]]): A list of tuples where each tuple represents the (x, y)
            coordinates of the starting point of a rain drop.

    Returns:
        np.ndarray: Image with rain effect added.

    Reference:
        https://github.com/UjjwalSaxena/Automold--Road-Augmentation-Library
    Nrk   )
rW   lineblurrX   rY   r_   r[   r   ro   rb   )rN   r   r   r   r   r   r   r   Zrain_drop_x0Zrain_drop_y0Zrain_drop_x1Zrain_drop_y1Z	image_hsvrf   rf   rg   r)   y  s    znp.random.RandomState)rN   fog_intensity
alpha_coeffog_particle_positionsrandom_staterR   c                 C  s   | j dd \}}t| }tj|||ftjd}ttj }	tdtt||d | }
|D ]T\}}td|
d }t	j
||
|d}|dkr|	n|	f| }tj|||f||dd qZt|d	d
}tj|ddd|	 | | }| d|  ||  }|tjS )a  Add fog to the input image.

    Args:
        img (np.ndarray): Input image.
        fog_intensity (float): Intensity of the fog effect, between 0 and 1.
        alpha_coef (float): Base alpha (transparency) value for fog particles.
        fog_particle_positions (list[tuple[int, int]]): List of (x, y) coordinates for fog particles.
        random_state (np.random.RandomState): Random state used
    Returns:
        np.ndarray: Image with added fog effect.
    Nrk   rT   g?ry   r   rz   )centerradiuscolorZ	thickness)   r   r   T)axisZkeepdims)r|   r   r[   r   ro   r   maxrr   r   r   randintrW   circler   meanr_   )rN   r   r   r   r   heightwidthr   Z	fog_layerr   Zmax_fog_radiusxyZ
min_radiusr   r   alphaZ	fog_imagerf   rf   rg   r(     s2    
	ztuple[float, float]r$   z	list[Any])rN   flare_center
src_radius	src_colorcirclesrR   c              	   C  s  |   }|   }|D ]D\}\}}	}
\}}}t|||	f|
|||fd t|||d| }qdd |D }|  }|d }tjdd|d}tjd||d}t|D ]`}t||t|| |d ||| d  ||| d   ||| d   }t|||d| }q|S )a
  Add a sun flare effect to an image using a simple overlay technique.

    This function creates a basic sun flare effect by overlaying multiple semi-transparent
    circles of varying sizes and intensities on the input image. The effect simulates
    a simple lens flare caused by bright light sources.

    Args:
        img (np.ndarray): The input image.
        flare_center (tuple[float, float]): (x, y) coordinates of the flare center
            in pixel coordinates.
        src_radius (int): The radius of the main sun circle in pixels.
        src_color (ColorType): The color of the sun, represented as a tuple of RGB values.
        circles (list[Any]): A list of tuples, each representing a circle that contributes
            to the flare effect. Each tuple contains:
            - alpha (float): The transparency of the circle (0.0 to 1.0).
            - center (tuple[int, int]): (x, y) coordinates of the circle center.
            - radius (int): The radius of the circle.
            - color (tuple[int, int, int]): RGB color of the circle.

    Returns:
        np.ndarray: The output image with the sun flare effect added.

    Note:
        - This function uses a simple alpha blending technique to overlay flare elements.
        - The main sun is created as a gradient circle, fading from the center outwards.
        - Additional flare circles are added along an imaginary line from the sun's position.
        - This method is computationally efficient but may produce less realistic results
          compared to more advanced techniques.

    The flare effect is created through the following steps:
    1. Create an overlay image and output image as copies of the input.
    2. Add smaller flare circles to the overlay.
    3. Blend the overlay with the output image using alpha compositing.
    4. Add the main sun circle with a radial gradient.

    Examples:
        >>> import numpy as np
        >>> import albumentations as A
        >>> image = np.random.randint(0, 256, [100, 100, 3], dtype=np.uint8)
        >>> flare_center = (50, 50)
        >>> src_radius = 20
        >>> src_color = (255, 255, 200)
        >>> circles = [
        ...     (0.1, (60, 60), 5, (255, 200, 200)),
        ...     (0.2, (70, 70), 3, (200, 255, 200))
        ... ]
        >>> flared_image = A.functional.add_sun_flare_overlay(
        ...     image, flare_center, src_radius, src_color, circles
        ... )

    References:
        - Alpha compositing: https://en.wikipedia.org/wiki/Alpha_compositing
        - Lens flare: https://en.wikipedia.org/wiki/Lens_flare
    rz   ry   c                 S  s   g | ]}t |qS rf   )rr   )ru   r   rf   rf   rg   rx   *  s     z)add_sun_flare_overlay.<locals>.<listcomp>
   r   )num)r   rW   r   r   r[   r   r{   rr   )rN   r   r   r   r   overlayoutputr   r   r   Zrad3Zr_colorZg_colorZb_colorZpointZ	num_timesZradrv   Zalprf   rf   rg   r.     s    ?0c              	   C  s  |   }| jdd \}}tj| tjd}t||||d dD ]b}	t|d tt	|	t
||  t|d tt	|	t
||  f}
t|||
|d q@|D ]&\}}}}t||t|d |d qtj|d	d
d
d}tjd|d|f \}}t||d  d ||d  d  }dt|t
||d  dd }t|gd }||9 }tt|}tj|d d	ddd|d< tj|d d	ddd|d< t|}dd| d|  d  S )a   Add a more realistic sun flare effect to the image.

    This function creates a complex sun flare effect by simulating various optical phenomena
    that occur in real camera lenses when capturing bright light sources. The result is a
    more realistic and physically plausible lens flare effect.

    Args:
        img (np.ndarray): Input image.
        flare_center (tuple[int, int]): (x, y) coordinates of the sun's center in pixels.
        src_radius (int): Radius of the main sun circle in pixels.
        src_color (tuple[int, int, int]): Color of the sun in RGB format.
        circles (list[Any]): List of tuples, each representing a flare circle with parameters:
            (alpha, center, size, color)
            - alpha (float): Transparency of the circle (0.0 to 1.0).
            - center (tuple[int, int]): (x, y) coordinates of the circle center.
            - size (float): Size factor for the circle radius.
            - color (tuple[int, int, int]): RGB color of the circle.

    Returns:
        np.ndarray: Image with added sun flare effect.

    Note:
        This function implements several techniques to create a more realistic flare:
        1. Separate flare layer: Allows for complex manipulations of the flare effect.
        2. Lens diffraction spikes: Simulates light diffraction in camera aperture.
        3. Radial gradient mask: Creates natural fading of the flare from the center.
        4. Gaussian blur: Softens the flare for a more natural glow effect.
        5. Chromatic aberration: Simulates color fringing often seen in real lens flares.
        6. Screen blending: Provides a more realistic blending of the flare with the image.

    The flare effect is created through the following steps:
    1. Create a separate flare layer.
    2. Add the main sun circle and diffraction spikes to the flare layer.
    3. Add additional flare circles based on the input parameters.
    4. Apply Gaussian blur to soften the flare.
    5. Create and apply a radial gradient mask for natural fading.
    6. Simulate chromatic aberration by applying different blurs to color channels.
    7. Blend the flare with the original image using screen blending mode.

    Examples:
        >>> import numpy as np
        >>> import albumentations as A
        >>> image = np.random.randint(0, 256, [1000, 1000, 3], dtype=np.uint8)
        >>> flare_center = (500, 500)
        >>> src_radius = 50
        >>> src_color = (255, 255, 200)
        >>> circles = [
        ...     (0.1, (550, 550), 10, (255, 200, 200)),
        ...     (0.2, (600, 600), 5, (200, 255, 200))
        ... ]
        >>> flared_image = A.functional.add_sun_flare_physics_based(
        ...     image, flare_center, src_radius, src_color, circles
        ... )

    References:
        - Lens flare: https://en.wikipedia.org/wiki/Lens_flare
        - Diffraction: https://en.wikipedia.org/wiki/Diffraction
        - Chromatic aberration: https://en.wikipedia.org/wiki/Chromatic_aberration
        - Screen blending: https://en.wikipedia.org/wiki/Blend_modes#Screen
    Nrk   rT   rz   )r   -   Z      r   ry   gQ?r      r   gffffff?r      r   )r   r|   r[   r   r   rW   r   rr   cosradiansr   sinr   r   Zogridsqrtr   r   listrZ   ra   )rN   r   r   r   r   r   r   r   Zflare_layerZangleZ	end_pointr   r   r   r   r   r   r   Zchannelsrf   rf   rg   r/   8  s,    E$$& 
zlist[np.ndarray])rN   vertices_listintensitiesrR   c           
      C  s   t | }ttj }|  }t||D ]~\}}tj| jd | jd dftjd}t	||g|f tj
||dd}|dddddf |k}	t||	 | tj||	< q$|S )a  Add shadows to the image by reducing the intensity of the pixel values in specified regions.

    Args:
        img (np.ndarray): Input image. Multichannel images are supported.
        vertices_list (list[np.ndarray]): List of vertices for shadow polygons.
        intensities (np.ndarray): Array of shadow intensities. Range is [0, 1].

    Returns:
        np.ndarray: Image with shadows added.

    Reference:
        https://github.com/UjjwalSaxena/Automold--Road-Augmentation-Library
    r   ry   rT   rk   r   N)r   r   r[   ro   r   zipr   r|   rW   ZfillPolyrepeatr   )
rN   r  r  r   r   Zimg_shadowedZverticesZshadow_intensityr   Zshadowed_indicesrf   rf   rg   r*     s    
"

)rN   gravelsrR   c           	      C  sR   t |  t| tj}|D ](}|\}}}}}||||||df< qt|tjS )Nry   )r   rW   rX   r   r   )	rN   r  r   ZgravelZmin_yZmax_yZmin_xZmax_xrd   rf   rf   rg   r+     s    )rN   rR   c                 C  s   t | j |  S r   )r   rU   rN   rf   rf   rg   r=     s    )rN   channels_shuffledrR   c                 C  s   | d|f S r   rf   )rN   r  rf   rf   rg   r5     s    )rN   gammarR   c                 C  sB   | j tjkr6tddd| d }t| |tjS t| |S )Nr   g?gp?r   )rU   r[   ro   r\   rW   r`   r_   power)rN   r  tablerf   rf   rg   r;     s    ry   F)rN   r   betabeta_by_maxrR   c                 C  s2   |rt | j }|| }n|t|  }t| ||S r   )r   rU   r[   r   r   )rN   r   r  r  r   valuerf   rf   rg   r4     s
    

皙?r   znp.random.RandomState | None)imagecolor_shift	intensityr   rR   c                 C  s   t | t j}t |\}}tj|d | d |jdd |d}tjd|d | |jdd |d}|d }	|	|7 }	|	d; }	|d	 }
|
|d d
|
  7 }
t |t jS )a  Apply poisson noise to an image to simulate camera sensor noise.

    Args:
        image (np.ndarray): Input image. Currently, only RGB images are supported.
        color_shift (float): The amount of color shift to apply. Default is 0.05.
        intensity (float): Multiplication factor for noise values. Values of ~0.5 produce a noticeable,
                           yet acceptable level of noise. Default is 0.5.
        random_state (np.random.RandomState | None): If specified, this will be random state used
            for noise generation.

    Returns:
        np.ndarray: The noised image.

    Image types:
        uint8, float32

    Number of channels:
        3
    ry   r   Nrk   )r   r   r   ri   r   .ry   r   )	rW   rX   r   Z
meanStdDevr   Zpoissonr|   r   r   )r  r  r  r   Zhlsr   stddevZluminance_noiseZcolor_noiserc   Z	luminancerf   rf   rg   r>      s    &$c                 C  s   t | t jS )a  Convert an RGB image to grayscale using the weighted average method.

    This function uses OpenCV's cvtColor function with COLOR_RGB2GRAY conversion,
    which applies the following formula:
    Y = 0.299*R + 0.587*G + 0.114*B

    Args:
        img (np.ndarray): Input RGB image as a numpy array.

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

    Image types:
        uint8, float32

    Number of channels:
        3
    )rW   rX   rp   r  rf   rf   rg   to_gray_weighted_average+  s    r  c                 C  s   t | t jd S )a  Convert an RGB image to grayscale using the L channel from the LAB color space.

    This function converts the RGB image to the LAB color space and extracts the L channel.
    The LAB color space is designed to approximate human vision, where L represents lightness.

    Key aspects of this method:
    1. The L channel represents the lightness of each pixel, ranging from 0 (black) to 100 (white).
    2. It's more perceptually uniform than RGB, meaning equal changes in L values correspond to
       roughly equal changes in perceived lightness.
    3. The L channel is independent of the color information (A and B channels), making it
       suitable for grayscale conversion.

    This method can be particularly useful when you want a grayscale image that closely
    matches human perception of lightness, potentially preserving more perceived contrast
    than simple RGB-based methods.

    Args:
        img (np.ndarray): Input RGB image as a numpy array.

    Returns:
        np.ndarray: Grayscale image as a 2D numpy array, representing the L (lightness) channel.
                    Values are scaled to match the input image's data type range.

    Image types:
        uint8, float32

    Number of channels:
        3
    r   )rW   rX   r   r  rf   rf   rg   to_gray_from_labA  s     r  c                 C  s,   |  tj}tj|ddtj|dd d S )a  Convert an image to grayscale using the desaturation method.

    Args:
        img (np.ndarray): Input image as a numpy array.

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

    Image types:
        uint8, float32

    Number of channels:
        any
    rz   r  rk   )r_   r[   r   r   r   )rN   Zfloat_imagerf   rf   rg   to_gray_desaturationd  s    r  c                 C  s   t j| dd| jS )a  Convert an image to grayscale using the average method.

    This function computes the arithmetic mean across all channels for each pixel,
    resulting in a grayscale representation of the image.

    Key aspects of this method:
    1. It treats all channels equally, regardless of their perceptual importance.
    2. Works with any number of channels, making it versatile for various image types.
    3. Simple and fast to compute, but may not accurately represent perceived brightness.
    4. For RGB images, the formula is: Gray = (R + G + B) / 3

    Note: This method may produce different results compared to weighted methods
    (like RGB weighted average) which account for human perception of color brightness.
    It may also produce unexpected results for images with alpha channels or
    non-color data in additional channels.

    Args:
        img (np.ndarray): Input image as a numpy array. Can be any number of channels.

    Returns:
        np.ndarray: Grayscale image as a 2D numpy array. The output data type
                    matches the input data type.

    Image types:
        uint8, float32

    Number of channels:
        any
    rz   r  )r[   r   r_   rU   r  rf   rf   rg   to_gray_averagex  s    r  c                 C  s   t j| ddS )a  Convert an image to grayscale using the maximum channel value method.

    This function takes the maximum value across all channels for each pixel,
    resulting in a grayscale image that preserves the brightest parts of the original image.

    Key aspects of this method:
    1. Works with any number of channels, making it versatile for various image types.
    2. For 3-channel (e.g., RGB) images, this method is equivalent to extracting the V (Value)
       channel from the HSV color space.
    3. Preserves the brightest parts of the image but may lose some color contrast information.
    4. Simple and fast to compute.

    Note:
    - This method tends to produce brighter grayscale images compared to other conversion methods,
      as it always selects the highest intensity value from the channels.
    - For RGB images, it may not accurately represent perceived brightness as it doesn't
      account for human color perception.

    Args:
        img (np.ndarray): Input image as a numpy array. Can be any number of channels.

    Returns:
        np.ndarray: Grayscale image as a 2D numpy array. The output data type
                    matches the input data type.

    Image types:
        uint8, float32

    Number of channels:
        any
    rz   r  )r[   r   r  rf   rf   rg   to_gray_max  s     r  c                 C  sd   | j }| d| jd }tdd}||}|| jdd }t|d}|tjkr`t||dS |S )a  Convert an image to grayscale using Principal Component Analysis (PCA).

    This function applies PCA to reduce a multi-channel image to a single channel,
    effectively creating a grayscale representation that captures the maximum variance
    in the color data.

    Args:
        img (np.ndarray): Input image as a numpy array with shape (height, width, channels).

    Returns:
        np.ndarray: Grayscale image as a 2D numpy array with shape (height, width).
                    If input is uint8, output is uint8 in range [0, 255].
                    If input is float32, output is float32 in range [0, 1].

    Note:
        This method can potentially preserve more information from the original image
        compared to standard weighted average methods, as it accounts for the
        correlations between color channels.

    Image types:
        uint8, float32

    Number of channels:
        any
    rz   rk   ry   )Zn_componentsNZmin_maxZtarget_dtype)	rU   reshaper|   r   Zfit_transformr   r[   ro   r   )rN   rU   ZpixelspcaZ
pca_resultZ	grayscalerf   rf   rg   to_gray_pca  s    


r"  zRLiteral[('weighted_average', 'from_lab', 'desaturation', 'average', 'max', 'pca')])rN   num_output_channelsmethodrR   c                 C  s   |dkrt | }nh|dkr$t| }nV|dkr6t| }nD|dkrHt| }n2|dkrZt| }n |dkrlt| }ntd| t||S )NZweighted_averageZfrom_labZdesaturationZaverager   r!  zUnsupported method: )r  r  r  r  r  r"  r   grayscale_to_multichannel)rN   r#  r$  resultrf   rf   rg   rG     s    





r   )grayscale_imager#  rR   c                 C  s    |    } tj| g| ddS )a  Convert a grayscale image to a multi-channel image.

    This function takes a 2D grayscale image or a 3D image with a single channel
    and converts it to a multi-channel image by repeating the grayscale data
    across the specified number of channels.

    Args:
        grayscale_image (np.ndarray): Input grayscale image. Can be 2D (height, width)
                                      or 3D (height, width, 1).
        num_output_channels (int, optional): Number of channels in the output image. Defaults to 3.

    Returns:
        np.ndarray: Multi-channel image with shape (height, width, num_channels).

    Note:
        If the input is already a multi-channel image with the desired number of channels,
        it will be returned unchanged.
    rz   r  )r   squeezer[   stack)r'  r#  rf   rf   rg   r%    s    r%  )rN   r   down_interpolationup_interpolationrR   c           	      C  s|   | j d d \}}|tjks&|tjko0| jtjk}|r>t| } tj| d |||d}tj|||f|d}|rxt|tjdS |S )Nrk   )ZfxZfyinterpolationr,  r  )	r|   rW   ZINTER_NEARESTrU   r[   ro   r   resizer   )	rN   r   r*  r+  r   r   Z	need_castZ
downscaledZupscaledrf   rf   rg   r8     s    
r   )	input_objparamsrR   c                 K  s   | S r   rf   )r/  r0  rf   rf   rg   rA   *  s    zlist[int] | None)r  tilesmappingrR   c                 C  s~   |j dks|dkr|  S t| }t|D ]L\}}|| \}}}}	|| \}
}}}| |
|||f |||||	f< q,|S )a@  Swap tiles on the image according to the new format.

    Args:
        image: Input image.
        tiles: Array of tiles with each tile as [start_y, start_x, end_y, end_x].
        mapping: list of new tile indices.

    Returns:
        np.ndarray: Output image with tiles swapped according to the random shuffle.
    r   N)r   r   r[   r   r   )r  r1  r2  Z	new_imager   Z	new_indexstart_ystart_xend_yend_xZstart_y_origZstart_x_origZ
end_y_origZ
end_x_origrf   rf   rg   rF   .  s    
&)rN   alpha_vectorrR   c              	   C  s   | j }t| }| d|}tj|dd}|| }|dkrTt|}|d | | }njtj|dd}	tj|	\}
}|
ddd 	 }|
| }
|dd|f }t
t
|t||
 |jj}|| }||}t|ddS )a  Perform 'Fancy PCA' augmentation on an image with any number of channels.

    Args:
        img (np.ndarray): Input image
        alpha_vector (np.ndarray): Vector of scale factors for each principal component.
                                   Should have the same length as the number of channels in the image.

    Returns:
        np.ndarray: Augmented image of the same shape, type, and range as the input.

    Image types:
        uint8, float32

    Number of channels:
        Any

    Note:
        - This function generalizes the Fancy PCA augmentation to work with any number of channels.
        - It preserves the original range of the image ([0, 255] for uint8, [0, 1] for float32).
        - For single-channel images, the augmentation is applied as a simple scaling of pixel intensity variation.
        - For multi-channel images, PCA is performed on the entire image, treating each pixel
          as a point in N-dimensional space (where N is the number of channels).
        - The augmentation preserves the correlation between channels while adding controlled noise.
        - Computation time may increase significantly for images with a large number of channels.

    Reference:
        Krizhevsky, A., Sutskever, I., & Hinton, G. E. (2012).
        ImageNet classification with deep convolutional neural networks.
        In Advances in neural information processing systems (pp. 1097-1105).
    rz   r   r  ry   F)ZrowvarN)r|   r   r   r[   r   ZstdZcovZlinalgZeighZargsortdotZdiagr   r   )rN   r7  
orig_shaper   Zimg_reshapedZimg_meanZimg_centeredZstd_devnoiseZimg_covZeig_valsZeig_vecsZ	sort_permZimg_pcarf   rf   rg   r:   H  s"    "
"
r[   )rN   factorrR   c                 C  s(   |dkrt | S |dkr| S t| |S )Nr   ry   )r[   r   r   rN   r;  rf   rf   rg   r0     s
    
c                 C  st   |dkr| S t | r|  nt| tj }|dkr`| jtjkrNt|d }tj	| || jdS t
| ||d|  S )Nry   r   r   rT   )r   r   rW   rX   rp   rU   r[   r   rr   r   r   )rN   r;  r   rf   rf   rg   r1     s    ")rN   r;  r  rR   c                 C  sX   |dkr| S t | r| S t| tj}t|tj}|dkr@|S tj| ||d| |dS )Nry   r   )r  )r   rW   rX   rp   rn   r   )rN   r;  r  Zgrayrf   rf   rg   r3     s    c                 C  s^   t | t j} tjddtjd}t|d|  dtj}t 	| d || d< t | t j
S )Nr   rS   rT   rV   r   )rW   rX   rY   r[   r\   r]   r^   r_   ro   r`   rb   )rN   r;  r   rf   rf   rg   _adjust_hue_torchvision_uint8  s
    r=  c                 C  sb   t | s|dkr| S | jtjkr*t| |S t| tj} t| d |d  d| d< t| tj	S )Nr   r   ri   )
r   rU   r[   ro   r=  rW   rX   rY   r^   rb   r<  rf   rf   rg   r2     s    
zSequence[bool])r  
n_segmentsreplace_samplesmax_sizer,  rR   c                 C  s  t |s| S | j}|d k	r|t| jd d }||kr||| }| jd d \}}	t|| t|	|  }
}t| |
|f|} tjj	| |d| j
tkrdnd d}d}t| j }t | } | j
tkrt j| dd} t| }t|D ]}tjj|d | d|f d	}t|D ]l\}}||t|  r|j}| d|f }|jjd
kr`tt |}tt|||}n|}||||k< qq|| jkrt| |d d |S | S )Nrk   r   rz   )r>  ZcompactnessZchannel_axisr   r  ry   .)Zintensity_image)rv   ub)r[   anyr|   r   rr   
fgeometricr.  skimageZsegmentationZslicndimr!   r   rU   r   r   r   r{   ZmeasureZregionpropsr   r~   mean_intensitykindr   r   )r  r>  r?  r@  r,  r9  r   r   r   r   Z
new_heightZ	new_widthsegmentsZ	min_valuer   r   cZregionsZ
region_idxZregionrG  Z
image_sp_cr  rf   rf   rg   rE     sD    



r   r   r   )r  ksizesigmar   rs   rR   c                 C  s   t tj||f|d}| jtkr8t| dkr8tj| dd} || }| | }t|d |k}|	tj
}| ||  }	t|	dd}	||}
tt|	|
t| d|
 S )N)rK  r   ry   rz   r  r   r   )r   rW   r   rF  r"   r   r[   r(  absr_   r   r   r	   r   )r  rK  rL  r   rs   Zblur_fnr   Zresidualr   ZsharpZ	soft_maskrf   rf   rg   rH     s    
zfloat | Sequence[float])r  	drop_mask
drop_valuerR   c                 C  s<   t |ttfr"|dkr"t| }nt| |}t||| S )Nr   )r   rr   r   r[   r   r   where)r  rN  rO  Zdrop_valuesrf   rf   rg   pixel_dropout.  s    rQ  r'   )rN   non_mudmudrainr   rR   c                 C  sr   |dkr$|d krd}t || | S |dkr`|d kr@d}t ||d krTd}t || | | S t d| d S )NrT  zRain spatter requires rain maskrS  zMud spatter requires mud maskz!Mud spatter requires non_mud maskzUnsupported spatter mode: )r   )rN   rR  rS  rT  r   r   rf   rf   rg   spatter7  s    
rU  z dict[tuple[int, int], list[int]])r1  rR   c                 C  sD   t t}t| D ].\}\}}}}|| || f}|| | q|S )zBGroups tiles by their shape and stores the indices for each shape.)r   r  r   append)r1  shape_groupsindexr3  r4  r5  r6  r|   rf   rf   rg   create_shape_groupsT  s
    rY  z	list[int])rW  r   rR   c                 C  s`   t dd |  D }dg| }|  D ]2}tj| |d}t||D ]\}}|||< qHq(|S )a  Shuffles indices within each group of similar shapes and creates a list where each
    index points to the index of the tile it should be mapped to.

    Args:
        shape_groups (dict[tuple[int, int], list[int]]): Groups of tile indices categorized by shape.
        random_state (Optional[np.random.RandomState]): Seed for the random number generator for reproducibility.

    Returns:
        list[int]: A list where each index is mapped to the new index of the tile after shuffling.
    c                 s  s   | ]}t |V  qd S r   )r~   )ru   indicesrf   rf   rg   	<genexpr>l  s     z4shuffle_tiles_within_shape_groups.<locals>.<genexpr>rz   r   )r   valuesr   shuffler   r	  )rW  r   Z	num_tilesr2  rZ  Zshuffled_indicesoldnewrf   rf   rg   !shuffle_tiles_within_shape_groups]  s    
r`  )rN   primary_distortion_redsecondary_distortion_redprimary_distortion_bluesecondary_distortion_bluer,  rR   c                 C  s   | j d d \}}tjdtjd}||d< ||d< |d |d< |d |d< tj||d	d	gtjd}	tj||d	d	gtjd}
t| d
 ||	|||}t| d ||
|||}t|| d |gS )Nrk   r   rT   r   )ry   ry   g       @)r   rk   )ry   rk   r   r   ).rk   r  )r|   r[   Zeyer   r}   _distort_channelr   )rN   ra  rb  rc  rd  r,  r   r   
camera_matZdistortion_coeffs_redZdistortion_coeffs_blueZred_distortedZblue_distortedrf   rf   rg   rI   y  s2    
	)channelrf  distortion_coeffsr   r   r,  rR   c                 C  s6   t j||d |||ft jd\}}t j| |||t jdS )N)ZcameraMatrixZ
distCoeffsRZnewCameraMatrixr   Zm1type)r,  Z
borderMode)rW   ZinitUndistortRectifyMapZCV_32FC1ZremapZBORDER_REPLICATE)rg  rf  rh  r   r   r,  Zmap_xZmap_yrf   rf   rg   re    s    
re  c                 C  s   t j| |ddS Nry   )Z
iterations)rW   rJ   rN   r   rf   rf   rg   rJ     s    c                 C  s   t j| |ddS rj  )rW   rK   rk  rf   rf   rg   rK     s    z Literal[('dilation', 'erosion')])rN   r   	operationrR   c                 C  s6   |dkrt | |S |dkr$t| |S td| d S )NZdilationZerosionzUnsupported operation: )rK   rJ   r   )rN   r   rl  rf   rf   rg   
morphology  s
    

rm  )bboxesr   rl  image_shaperR   c                 C  s:   |   } t| |}t|||}t|| d d d df< | S )N   )r   r   rm  r   )rn  r   rl  ro  masksrf   rf   rg   bboxes_morphology  s
    
rr  gk+ݓ?gӼ?g_LU?ga+e?gMSt$?gZd;O?gD?gs?g_L?g<Nё\?gJY?g:#J{/?gJ4?gL7A`?g9m4?gݓ?gx&?gcZB?gj+?g-!lV?gF_?g:pΈ?gŏ1w?g<,Ԛ?g<,Ԛ?g oŏ?gfj+?gu?goʡ?g?W[?gjMS?g1?gSt$?gS?g)Ǻ?gvq-?gsF?g:H?gl	g?gX9v?gW2?g^I+?gs?gy?g6<R?gFx?gӼ?gI.!?gd]K?gn?gTN?gW[?g\ Ac?gW[?g[<?g鷯?g4@?g^)?gZd;O?gAf?gz6>?g%䃞?gOjM?gm?glV}?g
F%u?g{Pk?g:#J{/?)i  i        |  p  d  X  L  @  4!  (#  %  '  )  *  ,  .  0  2  4  6  8  :  g,Ԛ?gAc]K?gQI?goʡ?gZӼ?gY ?gDio?gQI?g46<R?gJ4?g<R!?gb48?g,C?g.n?gGz?gBi?gU0*?g|гY?g|Pk?g\C?go_?gF_?gA`"?gGz?g9#J?gBi?g&1?g<,Ԛ?g:H?g9#?g镲q?gkw#?gy)?g?W[?g6;Nё?gV-?gz6>W[?g]Fx?gX2ı.?g:H?gjM?g|a2U0?gHP?g-1?g"~j?g[B>٬?g߾3?g?ܵ?gʡE?g`"?gۊe?gH}8?gK7?g58EGr?gJ4?g'?g+e?g?gǘ?g/n?)rs  rt  ru  rv  rw  rx  ry  rz  r{  r|  r}  r~  r  r  r  r  r  r  r  r  r  r  r  )Z	blackbodyZciedr&   )rN   temperaturer   rR   c                 C  s6  |   } tt|  }tt|  }t|||}d}t|| | |}t|| d | |}||kr~tt| | }nD|| ||  }	d|	 }
|
tt| |  |	tt| |   }| d d d d df |d |d   | d d d d df< | d d d d df |d |d   | d d d d df< | S )Ni  ry   r   rk   )r   r   PLANCKIAN_COEFFSkeysr   r[   r   r}   )rN   r  r   Zmin_tempZmax_tempr   Zt_leftZt_rightZcoeffsZw_rightZw_leftrf   rf   rg   planckian_jitter  s    ,88r        ?ztuple[int, ...])r|   r   rL  r   rR   c                 C  s   t | d | }t | d | }t| tkrFt||||| d f}nt||||f}tj|| d | d ftjd}|| S )Nr   ry   rz   r-  )	rr   r~   r"   r   r   rW   r.  INTER_LINEARr   )r|   r   rL  r   Zdownscaled_heightZdownsaled_widthZlow_res_noiser&  rf   rf   rg   rL   5  s    )rN   r:  rR   c                 C  s
   t | |S r   )r
   )rN   r:  rf   rf   rg   	add_noiseI  s    r  )	keypointsr1  r2  rR   c                 C  sH  | j s
| S | dddf ddtjf }| dddf ddtjf }|j\}}}}||k||k @ ||k@ ||k @ }	tj|	dd}
tj|	dd }t|rtdtdd t||
 }||
df }||
df }||df }||df }| 	 }| dddf | | |dddf< | dddf | | |dddf< | | ||< |S )a  Swap the positions of keypoints based on a tile mapping.

    This function takes a set of keypoints and repositions them according to a mapping of tile swaps.
    Keypoints are moved from their original tiles to new positions in the swapped tiles.

    Args:
        keypoints (np.ndarray): A 2D numpy array of shape (N, 2) where N is the number of keypoints.
                                Each row represents a keypoint's (x, y) coordinates.
        tiles (np.ndarray): A 2D numpy array of shape (M, 4) where M is the number of tiles.
                            Each row represents a tile's (start_y, start_x, end_y, end_x) coordinates.
        mapping (np.ndarray): A 1D numpy array of shape (M,) where M is the number of tiles.
                              Each element i contains the index of the tile that tile i should be swapped with.

    Returns:
        np.ndarray: A 2D numpy array of the same shape as the input keypoints, containing the new positions
                    of the keypoints after the tile swap.

    Raises:
        RuntimeWarning: If any keypoint is not found within any tile.

    Notes:
        - Keypoints that do not fall within any tile will remain unchanged.
        - The function assumes that the tiles do not overlap and cover the entire image space.
    Nr   ry   r  zsSome keypoints are not in any tile. They will be returned unchanged. This is unexpected and should be investigated.rk   rl   )
r   r[   r   r   ZargmaxrC  r   RuntimeWarningr}   r   )r  r1  r2  Zkp_xZkp_yr3  r4  r5  r6  Zin_tileZtile_indicesZnot_in_any_tileZnew_tile_indicesZold_start_xZold_start_yZnew_start_xZnew_start_yZnew_keypointsrf   rf   rg   swap_tiles_on_keypointsN  s0     
$$r  )rq   )N)N)N)Nr   T)ry   r   F)r  r   N)r   )N)r   )r   r   r   )N)r   ry   r  )y
__future__r   collectionsr   typingr   r   r   warningsr   rW   Znumpyr[   rE  Zalbucorer   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Z1albumentations.augmentations.geometric.functionalZaugmentationsZ	geometricZ
functionalrD  Zalbumentationsr   Z"albumentations.augmentations.utilsr   r   r   Zalbumentations.core.bbox_utilsr   r   Zalbumentations.core.typesr    r!   r"   r#   r$   r%   r&   r'   __all__rh   rj   rC   rD   rB   r   r   r   r   r9   r@   r?   r6   r7   r<   r,   r-   r)   r(   r.   r/   r*   r+   r=   r5   r;   r4   r>   r  r  r  r  r  r"  rG   r%  Z
INTER_AREAr  r8   rA   rF   r:   r0   r1   r3   r=  r2   rE   rH   rQ  rU  rY  r`  rI   re  rJ   rK   rm  rr  r  r  rL   r  r  rf   rf   rf   rg   <module>   s  P())  ?#,@Z"06Rn'	    )!!#)F	
<   *	
8   