a
    þd¤  ã                   @   sJ   d dl Z d dlZd dlmZ dd„ Zddd„Zdd	„ Zd
d„ Zdd„ Z	dS )é    N)Ú
functionalc                 C   s4   t j |¡}|dkr| S |dkr(|  ¡ S |  ¡ S dS )zËReduce loss as specified.

    Args:
        loss (Tensor): Elementwise loss tensor.
        reduction (str): Options are 'none', 'mean' and 'sum'.

    Returns:
        Tensor: Reduced loss tensor.
    r   é   N)ÚFZ
_ReductionZget_enumÚmeanÚsum)ÚlossÚ	reductionZreduction_enum© r	   úa/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/basicsr/losses/loss_util.pyÚreduce_loss   s    
r   r   c                 C   s¨   |durJ|  ¡ |   ¡ ksJ ‚| d¡dksB| d¡|  d¡ksBJ ‚| | } |du sZ|dkrft| |ƒ} n>|dkr¤| d¡dkr†| ¡ }n| ¡ |  d¡ }|  ¡ | } | S )aM  Apply element-wise weight and reduce loss.

    Args:
        loss (Tensor): Element-wise loss.
        weight (Tensor): Element-wise weights. Default: None.
        reduction (str): Same as built-in losses of PyTorch. Options are
            'none', 'mean' and 'sum'. Default: 'mean'.

    Returns:
        Tensor: Loss values.
    Nr   r   r   )ÚdimÚsizer   r   )r   Úweightr   r	   r	   r
   Úweight_reduce_loss   s    &
r   c                    s   t  ˆ ¡d‡ fdd„	ƒ}|S )aÄ  Create a weighted version of a given loss function.

    To use this decorator, the loss function must have the signature like
    `loss_func(pred, target, **kwargs)`. The function only needs to compute
    element-wise loss without any reduction. This decorator will add weight
    and reduction arguments to the function. The decorated function will have
    the signature like `loss_func(pred, target, weight=None, reduction='mean',
    **kwargs)`.

    :Example:

    >>> import torch
    >>> @weighted_loss
    >>> def l1_loss(pred, target):
    >>>     return (pred - target).abs()

    >>> pred = torch.Tensor([0, 2, 3])
    >>> target = torch.Tensor([1, 1, 1])
    >>> weight = torch.Tensor([1, 0, 1])

    >>> l1_loss(pred, target)
    tensor(1.3333)
    >>> l1_loss(pred, target, weight)
    tensor(1.5000)
    >>> l1_loss(pred, target, reduction='none')
    tensor([1., 1., 2.])
    >>> l1_loss(pred, target, weight, reduction='sum')
    tensor(3.)
    Nr   c                    s"   ˆ | |fi |¤Ž}t |||ƒ}|S )N)r   )ÚpredÚtargetr   r   Úkwargsr   ©Ú	loss_funcr	   r
   ÚwrapperY   s    zweighted_loss.<locals>.wrapper)Nr   )Ú	functoolsÚwraps)r   r   r	   r   r
   Úweighted_loss:   s    r   c                 C   s^   |d d }t j| ||||gdd}| d|d¡ d|d¡}tj|dddd d	¡ d	¡}|S )
ag  Get local weights for generating the artifact map of LDL.

    It is only called by the `get_refined_artifact_map` function.

    Args:
        residual (Tensor): Residual between predicted and ground truth images.
        ksize (Int): size of the local window.

    Returns:
        Tensor: weight for each pixel to be discriminated as an artifact pixel
    r   é   Zreflect)ÚpadÚmodeé   )éÿÿÿÿéþÿÿÿT)r   ZunbiasedÚkeepdimr   )r   r   ZunfoldÚtorchÚvarZsqueeze)ZresidualÚksizer   Zresidual_padZunfolded_residualÚpixel_level_weightr	   r	   r
   Úget_local_weightsc   s
    r$   c           	      C   sr   t jt  | | ¡ddd}t jt  | | ¡ddd}t j| ¡ dddd }t| ¡ |ƒ}|| }d|||k < |S )a8  Calculate the artifact map of LDL
    (Details or Artifacts: A Locally Discriminative Learning Approach to Realistic Image Super-Resolution. In CVPR 2022)

    Args:
        img_gt (Tensor): ground truth images.
        img_output (Tensor): output images given by the optimizing model.
        img_ema (Tensor): output images given by the ema model.
        ksize (Int): size of the local window.

    Returns:
        overall_weight: weight for each pixel to be discriminated as an artifact pixel
        (calculated based on both local and global observations).
    r   T)r   )r   r   éýÿÿÿ)r   r   gš™™™™™É?r   )r    r   Úabsr!   Úcloner$   )	Zimg_gtZ
img_outputZimg_emar"   Zresidual_emaZresidual_srZpatch_level_weightr#   Zoverall_weightr	   r	   r
   Úget_refined_artifact_mapy   s    r(   )Nr   )
r   r    Ztorch.nnr   r   r   r   r   r$   r(   r	   r	   r	   r
   Ú<module>   s   
 )