U
    h                     @  s   d dl mZ d dlZd dlmZmZ d dlZd dlm	Z	 d dl
mZmZ d dlmZ d dlmZ d dlmZmZ d	d
lmZ dgZdZG dd deZdS )    )annotationsN)AnyMapping)get_num_channels)AfterValidatorField)	Annotated)check_1plus)BaseTransformInitSchemaImageOnlyTransform   )channel_dropoutChannelDropout   c                      sr   e Zd ZdZG dd deZddd	d
d	d fddZdddddddZddddddZddddZ	  Z
S )r   a	  Randomly drop channels in the input image.

    This transform randomly selects a number of channels to drop from the input image
    and replaces them with a specified fill value. This can improve model robustness
    to missing or corrupted channels.

    The technique is conceptually similar to:
    - Dropout layers in neural networks, which randomly set input units to 0 during training.
    - CoarseDropout augmentation, which drops out regions in the spatial dimensions of the image.

    However, ChannelDropout operates on the channel dimension, effectively "dropping out"
    entire color channels or feature maps.

    Args:
        channel_drop_range (tuple[int, int]): Range from which to choose the number
            of channels to drop. The actual number will be randomly selected from
            the inclusive range [min, max]. Default: (1, 1).
        fill_value (float): Pixel value used to fill the dropped channels.
            Default: 0.
        p (float): Probability of applying the transform. Must be in the range
            [0, 1]. Default: 0.5.

    Raises:
        NotImplementedError: If the input image has only one channel.
        ValueError: If the upper bound of channel_drop_range is greater than or
            equal to the number of channels in the input image.

    Targets:
        image

    Image types:
        uint8, float32

    Example:
        >>> import numpy as np
        >>> import albumentations as A
        >>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
        >>> transform = A.ChannelDropout(channel_drop_range=(1, 2), fill_value=128, p=1.0)
        >>> result = transform(image=image)
        >>> dropped_image = result['image']
        >>> assert dropped_image.shape == image.shape
        >>> assert np.any(dropped_image != image)  # Some channels should be different

    Note:
        - The number of channels to drop is randomly chosen within the specified range.
        - Channels are randomly selected for dropping.
        - This transform is not applicable to single-channel (grayscale) images.
        - The transform will raise an error if it's not possible to drop the specified
          number of channels (e.g., trying to drop 3 channels from an RGB image).
        - This augmentation can be particularly useful for training models to be robust
          against missing or corrupted channel data in multi-spectral or hyperspectral imagery.

    c                   @  s   e Zd ZU ded< ded< dS )zChannelDropout.InitSchemaz7Annotated[tuple[int, int], AfterValidator(check_1plus)]channel_drop_rangezKAnnotated[float, Field(description='Pixel value for the dropped channel.')]
fill_valueN)__name__
__module____qualname____annotations__ r   r   X/tmp/pip-unpacked-wheel-e8onvpoz/albumentations/augmentations/dropout/channel_dropout.py
InitSchemaL   s   
r   r   r   r   N      ?ztuple[int, int]floatzbool | None)r   r   always_applypc                   s    t  j||d || _|| _d S )N)r   r   )super__init__r   r   )selfr   r   r   r   	__class__r   r   r   P   s    zChannelDropout.__init__z
np.ndarrayztuple[int, ...]r   )imgchannels_to_dropparamsreturnc                 K  s   t ||| jS )N)r   r   )r    r#   r$   r%   r   r   r   apply\   s    zChannelDropout.applyzMapping[str, Any]zdict[str, Any])r%   datar&   c                 C  sx   d|kr|d n
|d d }t |}|dkr8d}t|| jd |krRd}t|tj| j }tjt||d}d|iS )	NimageZimagesr   r   z6Images has one channel. ChannelDropout is not defined.z,Can not drop all channels in ChannelDropout.)kr$   )r   NotImplementedErrorr   
ValueErrorrandomrandintsamplerange)r    r%   r(   r)   Znum_channelsmsgZnum_drop_channelsr$   r   r   r   get_params_dependent_on_data_   s    z+ChannelDropout.get_params_dependent_on_dataztuple[str, ...])r&   c                 C  s   dS )N)r   r   r   )r    r   r   r   get_transform_init_args_namesq   s    z,ChannelDropout.get_transform_init_args_names)r   r   Nr   )r   r   r   __doc__r
   r   r   r'   r2   r3   __classcell__r   r   r!   r   r      s   6    )
__future__r   r-   typingr   r   ZnumpynpZalbucorer   Zpydanticr   r   Ztyping_extensionsr   Zalbumentations.core.pydanticr	   Z(albumentations.core.transforms_interfacer
   r   Z
functionalr   __all__ZMIN_DROPOUT_CHANNEL_LIST_LENGTHr   r   r   r   r   <module>   s   