o
    oi                     @  s   d dl mZ d dlmZ d dlZd dlm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ddZG dd dejZdS )    )annotations)OptionalN)nn)Tensor)KORNIA_CHECKKORNIA_CHECK_IS_TENSOR)mask_ignore_pixels)one_hotmicro:0yE>predr   targetaveragestrepsfloatweightOptional[Tensor]ignore_indexOptional[int]returnc                 C  s  t |  t| jdkstd| j | jdd |jdd ks-td| j d|j | j|jks?td| j d|j | jd }d	d
h}t||v d| d|  | jdd}t||\}}	t|| jd | j| j	d}
|	dur|	
d |
|	 }
||	 }|durt |d t|jd |ko| |kd| d|j  t|j| jkd|j d| j  n| | jd }d}|d	krdg|R }|ddd}|| }|
| }
t||
 |}t||
 |}d| ||  }| d }|d
kr|| d|  }t|}|S )u0  Criterion that computes Sørensen-Dice Coefficient loss.

    According to [1], we compute the Sørensen-Dice Coefficient as follows:

    .. math::

        \text{Dice}(x, class) = \frac{2 |X \cap Y|}{|X| + |Y|}

    Where:
       - :math:`X` expects to be the scores of each class.
       - :math:`Y` expects to be the one-hot tensor with the class labels.

    the loss, is finally computed as:

    .. math::

        \text{loss}(x, class) = 1 - \text{Dice}(x, class)

    Reference:
        [1] https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient

    Args:
        pred: logits tensor with shape :math:`(N, C, H, W)` where C = number of classes.
        target: labels tensor with shape :math:`(N, H, W)` where each value
          is :math:`0 ≤ targets[i] ≤ C-1`.
        average:
            Reduction applied in multi-class scenario:
            - ``'micro'`` [default]: Calculate the loss across all classes.
            - ``'macro'``: Calculate the loss for each class separately and average the metrics across classes.
        eps: Scalar to enforce numerical stabiliy.
        weight: weights for classes with shape :math:`(num\_of\_classes,)`.
        ignore_index: labels with this value are ignored in the loss computation.

    Return:
        One-element tensor of the computed loss.

    Example:
        >>> N = 5  # num_classes
        >>> pred = torch.randn(1, N, 3, 5, requires_grad=True)
        >>> target = torch.empty(1, 3, 5, dtype=torch.long).random_(N)
        >>> output = dice_loss(pred, target)
        >>> output.backward()

       z,Invalid pred shape, we expect BxNxHxW. Got: Nz.pred and target shapes must be the same. Got: z and z1pred and target must be in the same device. Got:    r
   macrozThe `average` has to be one of z. Got: )dim)num_classesdevicedtypezweight must be Tensor or None.r   z)weight shape must be (num_of_classes,): (z,), got z1weight and pred must be in the same device. Got: )      g       @g      ?)r   lenshape
ValueErrorr   r   softmaxr   r	   r   
unsqueeze_numelnew_onesviewtorchsummean)r   r   r   r   r   r   num_of_classespossible_average	pred_softtarget_masktarget_one_hotdimsintersectioncardinality
dice_score	dice_loss r8   F/home/ubuntu/.local/lib/python3.10/site-packages/kornia/losses/dice.pyr7   #   sT   4






r7   c                      s6   e Zd ZdZ				dd fddZdddZ  ZS )DiceLossu  Criterion that computes Sørensen-Dice Coefficient loss.

    According to [1], we compute the Sørensen-Dice Coefficient as follows:

    .. math::

        \text{Dice}(x, class) = \frac{2 |X| \cap |Y|}{|X| + |Y|}

    Where:
       - :math:`X` expects to be the scores of each class.
       - :math:`Y` expects to be the one-hot tensor with the class labels.

    the loss, is finally computed as:

    .. math::

        \text{loss}(x, class) = 1 - \text{Dice}(x, class)

    Reference:
        [1] https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient

    Args:
        average:
            Reduction applied in multi-class scenario:
            - ``'micro'`` [default]: Calculate the loss across all classes.
            - ``'macro'``: Calculate the loss for each class separately and average the metrics across classes.
        eps: Scalar to enforce numerical stabiliy.
        weight: weights for classes with shape :math:`(num\_of\_classes,)`.
        ignore_index: labels with this value are ignored in the loss computation.

    Shape:
        - Pred: :math:`(N, C, H, W)` where C = number of classes.
        - Target: :math:`(N, H, W)` where each value is
          :math:`0 ≤ targets[i] ≤ C-1`.

    Example:
        >>> N = 5  # num_classes
        >>> criterion = DiceLoss()
        >>> pred = torch.randn(1, N, 3, 5, requires_grad=True)
        >>> target = torch.empty(1, 3, 5, dtype=torch.long).random_(N)
        >>> output = criterion(pred, target)
        >>> output.backward()

    r
   r   Nr   r   r   r   r   r   r   r   r   r   Nonec                   s&   t    || _|| _|| _|| _d S N)super__init__r   r   r   r   )selfr   r   r   r   	__class__r8   r9   r>      s
   

zDiceLoss.__init__r   r   r   c                 C  s   t ||| j| j| j| jS r<   )r7   r   r   r   r   )r?   r   r   r8   r8   r9   forward   s   zDiceLoss.forwardr
   r   Nr   )
r   r   r   r   r   r   r   r   r   r;   )r   r   r   r   r   r   )__name__
__module____qualname____doc__r>   rB   __classcell__r8   r8   r@   r9   r:      s    /r:   rC   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   )
__future__r   typingr   r+   r   kornia.corer   kornia.core.checkr   r   kornia.losses._utilsr   kornia.utils.one_hotr	   r7   Moduler:   r8   r8   r8   r9   <module>   s   
w