o
    oi                     @  sf   d dl mZ d dlmZ d dlZd dlmZmZ d dlmZm	Z	m
Z
 ddddZG dd dejZdS )    )annotations)OptionalN)Tensornn)KORNIA_CHECKKORNIA_CHECK_IS_TENSORKORNIA_CHECK_SHAPEpredr   targetweightOptional[Tensor]returnc                 C  sd  t | g d t |g d | jd dkstd| j | jdd |jdd ks7td| j d|j | j|jksItd	| j d|j | jd }|durt|d
 t|jd |kod| |kd| d|j  t|j| jkd|j d| j  | | jd | jd d}||jd d}|j\}}}|d}	t	j
jj|t	j|dddd| j}
|	|
  }t	j|ddd\}}t	j|| jddd|||}|||f }|jddd}||d }|d| d }d||  }|dkr|dddf |dddf  |dddf< || }|dd}|dur,||9 }| }|S )un  Criterion that computes a surrogate multi-class intersection-over-union (IoU) loss.

    According to [1], we compute the IoU as follows:

    .. math::

        \text{IoU}(x, class) = \frac{|X \cap Y|}{|X \cup Y|}

    [1] approximates this fomular with a surrogate, which is fully differentable.

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

    the loss, is finally computed as:

    .. math::

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

    Reference:
        [1] https://arxiv.org/pdf/1705.08790.pdf

    .. note::
        This loss function only supports multi-class (C > 1) labels. For binary
        labels please use the Lovasz-Hinge loss.

    Args:
        pred: logits tensor with shape :math:`(N, C, H, W)` where C = number of classes > 1.
        target: labels tensor with shape :math:`(N, H, W)` where each value
          is :math:`0 ≤ targets[i] ≤ C-1`.
        weight: weights for classes with shape :math:`(num\_of\_classes,)`.

    Return:
        a scalar with 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 = lovasz_softmax_loss(pred, target)
        >>> output.backward()

    )BNHW)r   r   r      z8Invalid pred shape, we expect BxNxHxW, with N > 1. Got: Nz.pred and target shapes must be the same. Got: z and z1pred and target must be in the same device. Got: z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: )num_classes   T)dim
descending)device)keepdimg      ?.)r   shape
ValueErrorr   r   r   numelreshapesoftmaxtorchr   
functionalone_hottoint64permutedtypeabssortarange	unsqueezeexpandsumcumsummean)r	   r
   r   num_of_classespred_flattentarget_flattenr   Cr   	pred_soft
foregrounderrorserrors_sortedpermutationsbatch_indextarget_sortedtarget_sorted_sumintersectionuniongradientweighted_errorsloss_per_class
final_loss rA   P/home/ubuntu/.local/lib/python3.10/site-packages/kornia/losses/lovasz_softmax.pylovasz_softmax_loss   sR   -



*&
,
rC   c                      s.   e Zd ZdZdd fddZdddZ  ZS )LovaszSoftmaxLossu  Criterion that computes a surrogate multi-class intersection-over-union (IoU) loss.

    According to [1], we compute the IoU as follows:

    .. math::

        \text{IoU}(x, class) = \frac{|X \cap Y|}{|X \cup Y|}

    [1] approximates this fomular with a surrogate, which is fully differentable.

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

    the loss, is finally computed as:

    .. math::

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

    Reference:
        [1] https://arxiv.org/pdf/1705.08790.pdf

    .. note::
        This loss function only supports multi-class (C > 1) labels. For binary
        labels please use the Lovasz-Hinge loss.

    Args:
        pred: logits tensor with shape :math:`(N, C, H, W)` where C = number of classes > 1.
        labels: labels tensor with shape :math:`(N, H, W)` where each value
          is :math:`0 ≤ targets[i] ≤ C-1`.
        weight: weights for classes with shape :math:`(num\_of\_classes,)`.

    Return:
        a scalar with the computed loss.

    Example:
        >>> N = 5  # num_classes
        >>> criterion = LovaszSoftmaxLoss()
        >>> 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()

    Nr   r   r   Nonec                   s   t    || _d S N)super__init__r   )selfr   	__class__rA   rB   rH      s   

zLovaszSoftmaxLoss.__init__r	   r   r
   c                 C  s   t ||| jdS )N)r	   r
   r   )rC   r   )rI   r	   r
   rA   rA   rB   forward   s   zLovaszSoftmaxLoss.forwardrF   )r   r   r   rE   )r	   r   r
   r   r   r   )__name__
__module____qualname____doc__rH   rL   __classcell__rA   rA   rJ   rB   rD      s    .rD   rF   )r	   r   r
   r   r   r   r   r   )
__future__r   typingr   r    r   r   kornia.core.checkr   r   r   rC   ModulerD   rA   rA   rA   rB   <module>   s   g