a
    d(                     @   sX   d dl mZ d dlZd dlmZ G dd dejjZG dd deZG dd deZ	dS )	    )CallableNc                       s   e Zd ZU dZeed< eed< deeedd fd	d
Z	e
jdddZe
je
je
jdddZe
je
je
jdddZ  ZS )_HausdorffERLossBasea"  Base class for binary Hausdorff loss based on morphological erosion.

    This is an Hausdorff Distance (HD) Loss that based on morphological erosion,which provided
    a differentiable approximation of Hausdorff distance as stated in :cite:`karimi2019reducing`.
    The code is refactored on top of `here <https://github.com/PatRyg99/HausdorffLoss/
        blob/master/hausdorff_loss.py>`__.

    Args:
        alpha: controls the erosion rate in each iteration.
        k: the number of iterations of erosion.
        reduction: Specifies the reduction to apply to the output: 'none' | 'mean' | 'sum'.
            'none': no reduction will be applied, 'mean': the weighted mean of the output is taken,
            'sum': the output will be summed.

    Returns:
        Estimated Hausdorff Loss.
    convmax_pool       @
   meanN)alphak	reductionreturnc                    s0   t    || _|| _|| _| d|   d S )Nkernel)super__init__r	   r
   r   Zregister_buffer
get_kernel)selfr	   r
   r   	__class__ `/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/losses/hausdorff.pyr      s
    
z_HausdorffERLossBase.__init__r   c                 C   s   t dS ),Get kernel for image morphology convolution.N)NotImplementedError)r   r   r   r   r   $   s    z_HausdorffERLossBase.get_kernelpredtargetr   c                 C   s
  || d }t j| j|j|jd}t j||j|jd}t j||jt jd}t|	dd d }t
| jD ]}| j|||dd}	|	d }
d|
|
dk < | |
}| |
  }|| dk}| }| r|
| ||  }t || ||
}
||
|d | j   }|
}qj|S )N   devicedtype   )Zweightpaddinggroupsg      ?r   )torchZ	as_tensorr   r   r   Z
zeros_likeZ	ones_likeboolintsizeranger
   r   r   Zsqueezeanywherer	   )r   r   r   boundr   Zerodedmaskr"   r
   ZdilationZerosionZerosion_maxZerosion_minZ_to_normZto_normZ_erosion_to_fillr   r   r   perform_erosion(   s&    
z$_HausdorffERLossBase.perform_erosionc                    s    j dd j dd kr> ddkr>ddksXtd j  dj  d d  k rvtdt fd	d
t dD }jdkr|	 }n2jdkr|
 }njdkrntdj d|S )an  Compute Hausdorff loss.

        Args:
            pred: predicted tensor with a shape of :math:`(B, C, H, W)` or :math:`(B, C, D, H, W)`.
                Each channel is as binary as: 1 -> fg, 0 -> bg.
            target: target tensor with a shape of :math:`(B, 1, H, W)` or :math:`(B, C, D, H, W)`.

        Returns:
            Estimated Hausdorff Loss.
        r   Nr   r!   zTPrediction and target need to be of same size, and target should not be one-hot.Got z and .zInvalid target value.c                    sZ   g | ]R}  d d ||d f t|ktjdjjdtjdjjdqS )Nr!   r   r   )r-   r$   r*   tensorr   r   ).0ir   r   r   r   r   
<listcomp>b   s   	z0_HausdorffERLossBase.forward.<locals>.<listcomp>r   sumnonezreduction `z` has not been implemented yet.)shaper'   
ValueErrormaxitemr$   stackr(   r   r   r4   r   )r   r   r   outr   r2   r   forwardM   s.    >	




z_HausdorffERLossBase.forward)r   r   r   )__name__
__module____qualname____doc__r   __annotations__floatr&   strr   r$   Tensorr   r-   r<   __classcell__r   r   r   r   r      s   
%r   c                       sP   e Zd ZdZejZedZ	ej
dddZej
ej
ej
d fddZ  ZS )	HausdorffERLossa=  Binary Hausdorff loss based on morphological erosion.

    Hausdorff Distance loss measures the maximum distance of a predicted segmentation boundary to
    the nearest ground-truth edge pixel. For two segmentation point sets X and Y ,
    the one-sided HD from X to Y is defined as:

    .. math::

        hd(X,Y) = \max_{x \in X} \min_{y \in Y}||x - y||_2

    Furthermore, the bidirectional HD is:

    .. math::

        HD(X,Y) = max(hd(X, Y), hd(Y, X))

    This is an Hausdorff Distance (HD) Loss that based on morphological erosion, which provided
    a differentiable approximation of Hausdorff distance as stated in :cite:`karimi2019reducing`.
    The code is refactored on top of `here <https://github.com/PatRyg99/HausdorffLoss/
    blob/master/hausdorff_loss.py>`__.

    Args:
        alpha: controls the erosion rate in each iteration.
        k: the number of iterations of erosion.
        reduction: Specifies the reduction to apply to the output: 'none' | 'mean' | 'sum'.
            'none': no reduction will be applied, 'mean': the weighted mean of the output is taken,
            'sum': the output will be summed.

    Examples:
        >>> hdloss = HausdorffERLoss()
        >>> input = torch.randn(5, 3, 20, 20)
        >>> target = (torch.rand(5, 1, 20, 20) * 2).long()
        >>> res = hdloss(input, target)
    r!   r   c                 C   s.   t g dg dg dgg}|d }|d S )r   r   r!   r   r!   r!   r!   g?N)r$   r/   )r   crossr   r   r   r   r      s    zHausdorffERLoss.get_kernelr   c                    s   |  dkr td|   d| |dk rJ| dkrJ|jtjksttd|d d|  d|  d	t 	||S )
a8  Compute Hausdorff loss.

        Args:
            pred: predicted tensor with a shape of :math:`(B, C, H, W)`.
                Each channel is as binary as: 1 -> fg, 0 -> bg.
            target: target tensor with a shape of :math:`(B, 1, H, W)`.

        Returns:
            Estimated Hausdorff Loss.
           zOnly 2D images supported. Got r.   r!   r   z+Expect long type target value in range (0, z).(z, ))
dimr7   r8   r'   minr   r$   longr   r<   r   r   r   r   r   r   r<      s    *$zHausdorffERLoss.forward)r=   r>   r?   r@   r$   Zconv2dr   nnZAdaptiveMaxPool2dr   rD   r   r<   rE   r   r   r   r   rF   {   s
   #
rF   c                       sP   e Zd ZdZejZedZ	ej
dddZej
ej
ej
d fddZ  ZS )	HausdorffERLoss3DaL  Binary 3D Hausdorff loss based on morphological erosion.

    Hausdorff Distance loss measures the maximum distance of a predicted segmentation boundary to
    the nearest ground-truth edge pixel. For two segmentation point sets X and Y ,
    the one-sided HD from X to Y is defined as:

    .. math::

        hd(X,Y) = \max_{x \in X} \min_{y \in Y}||x - y||_2

    Furthermore, the bidirectional HD is:

    .. math::

        HD(X,Y) = max(hd(X, Y), hd(Y, X))

    This is a 3D Hausdorff Distance (HD) Loss that based on morphological erosion, which provided
    a differentiable approximation of Hausdorff distance as stated in :cite:`karimi2019reducing`.
    The code is refactored on top of `here <https://github.com/PatRyg99/HausdorffLoss/
    blob/master/hausdorff_loss.py>`__.

    Args:
        alpha: controls the erosion rate in each iteration.
        k: the number of iterations of erosion.
        reduction: Specifies the reduction to apply to the output: 'none' | 'mean' | 'sum'.
            'none': no reduction will be applied, 'mean': the weighted mean of the output is taken,
            'sum': the output will be summed.

    Examples:
        >>> hdloss = HausdorffERLoss3D()
        >>> input = torch.randn(5, 3, 20, 20, 20)
        >>> target = (torch.rand(5, 1, 20, 20, 20) * 2).long()
        >>> res = hdloss(input, target)
    r!   r   c                 C   s\   t g dg dg dgg}t g dg dg dgg}t j|||gddd }|d S )r   rG   rH   )r   r   r   r!   )rL   g$I$I?N)r$   r/   r:   )r   rI   r+   r   r   r   r   r      s    zHausdorffERLoss3D.get_kernelr   c                    s.   |  dkr td|   dt ||S )aA  Compute 3D Hausdorff loss.

        Args:
            pred: predicted tensor with a shape of :math:`(B, C, D, H, W)`.
                Each channel is as binary as: 1 -> fg, 0 -> bg.
            target: target tensor with a shape of :math:`(B, 1, D, H, W)`.

        Returns:
            Estimated Hausdorff Loss.
           zOnly 3D images supported. Got r.   )rL   r7   r   r<   rO   r   r   r   r<      s    zHausdorffERLoss3D.forward)r=   r>   r?   r@   r$   Zconv3dr   rP   ZAdaptiveMaxPool3dr   rD   r   r<   rE   r   r   r   r   rQ      s
   #
rQ   )
typingr   r$   Ztorch.nnrP   ZjitZScriptModuler   rF   rQ   r   r   r   r   <module>   s
   tC