o
    oi                     @  sX   d dl mZ d dlmZmZ d dlZd dlm  mZ	 d dlmZ G dd dej
ZdS )    )annotations)OptionalSequenceN)nnc                      sV   e Zd ZdZ						d'd( fddZ	d)d*dd Z	d)d*d!d"Zd+d%d&Z  ZS ),MS_SSIMLossa  Creates a criterion that computes MSSIM + L1 loss.

    According to [1], we compute the MS_SSIM + L1 loss as follows:

    .. math::
        \text{loss}(x, y) = \alpha \cdot \mathcal{L_{MSSIM}}(x,y)+(1 - \alpha) \cdot G_\alpha \cdot \mathcal{L_1}(x,y)

    Where:
        - :math:`\alpha` is the weight parameter.
        - :math:`x` and :math:`y` are the reconstructed and true reference images.
        - :math:`\mathcal{L_{MSSIM}}` is the MS-SSIM loss.
        - :math:`G_\alpha` is the sigma values for computing multi-scale SSIM.
        - :math:`\mathcal{L_1}` is the L1 loss.

    Reference:
        [1]: https://research.nvidia.com/sites/default/files/pubs/2017-03_Loss-Functions-for/NN_ImgProc.pdf#page11

    Args:
        sigmas: gaussian sigma values.
        data_range: the range of the images.
        K: k values.
        alpha : specifies the alpha value
        compensation: specifies the scaling coefficient.
        reduction : Specifies the reduction to apply to the
         output: ``'none'`` | ``'mean'`` | ``'sum'``. ``'none'``: no reduction will be applied,
         ``'mean'``: the sum of the output will be divided by the number of elements
         in the output, ``'sum'``: the output will be summed.

    Returns:
        The computed loss.

    Shape:
        - Input1: :math:`(N, C, H, W)`.
        - Input2: :math:`(N, C, H, W)`.
        - Output: :math:`(N, H, W)` or scalar if reduction is set to ``'mean'`` or ``'sum'``.

    Examples:
        >>> input1 = torch.rand(1, 3, 5, 5)
        >>> input2 = torch.rand(1, 3, 5, 5)
        >>> criterion = kornia.losses.MS_SSIMLoss()
        >>> loss = criterion(input1, input2)

    g      ?      ?g       @g      @g       @r   g{Gz?gQ?皙?      i@meansigmasSequence[float]
data_rangefloatKtuple[float, float]alphacompensation	reductionstrreturnNonec                   s   t    || _|d | d | _|d | d | _td|d  | _|| _|| _|| _	td|d  d }t
dt| d||f}t|D ]@\}	}
| ||
|d|	 d dd d d d f< | ||
|d|	 d dd d d d f< | ||
|d|	 d dd d d d f< qG| d| d S )Nr               _g_masks)super__init__DRC1C2intpadr   r   r   torchzeroslen	enumerate_fspecial_gauss_2dregister_buffer)selfr   r   r   r   r   r   filter_sizeg_masksidxsigma	__class__ I/home/ubuntu/.local/lib/python3.10/site-packages/kornia/losses/ms_ssim.pyr    K   s   
	((*zMS_SSIMLoss.__init__Nsizer$   r0   deviceOptional[torch.device]dtypeOptional[torch.dtype]torch.Tensorc                 C  sN   t j|||d}||d 8 }t |d  d|d   }||  }|dS )a  Create 1-D gauss kernel.

        Args:
            size: the size of gauss kernel.
            sigma: sigma of normal distribution.
            device: device to store the result on.
            dtype: dtype of the result.

        Returns:
            1D kernel (size).

        )r6   r8   r   r   )r&   arangeexpsumreshape)r,   r5   r0   r6   r8   coordsgr3   r3   r4   _fspecial_gauss_1di   s
   
zMS_SSIMLoss._fspecial_gauss_1dc                 C  s   |  ||||}t||S )a   Create 2-D gauss kernel.

        Args:
            size: the size of gauss kernel.
            sigma: sigma of normal distribution.
            device: device to store the result on.
            dtype: dtype of the result.

        Returns:
            2D kernel (size x size).

        )rA   r&   outer)r,   r5   r0   r6   r8   gaussian_vecr3   r3   r4   r*   ~   s   zMS_SSIMLoss._fspecial_gauss_2dimg1img2c                 C  st  t |tjstdt| t |tjstdt| t|jt|jks7tdt| dt| dtj	tj| j
}|jd }tj|||| jd}tj|||| jd}|| }|| }|| }	tj|| ||| jd| }
tj|| ||| jd| }tj|| ||| jd|	 }d|	 | j || | j  }d| | j |
| | j  }|d	d	d
d	d	d	d	f |d	d	dd	d	d	d	f  |d	d	dd	d	d	d	f  }|jdd}d||  }tj||dd}tj||| d	 || jdd}| j| d| j | | j  }| j| }| jdkrt|}|S | jdkr)t|}|S | jdkr2	 |S td| j )zCompute MS_SSIM loss.

        Args:
            img1: the predicted image with shape :math:`(B, C, H, W)`.
            img2: the target image with a shape of :math:`(B, C, H, W)`.

        Returns:
            Estimated MS-SSIM_L1 loss.

        z&Input type is not a torch.Tensor. Got z'Output type is not a torch.Tensor. Got z!Input shapes should be same. Got z and .)groupspaddingr   Nr   r   )dimnone)r   r   r=   zInvalid reduction mode: )
isinstancer&   Tensor	TypeErrortyper(   shape
ValueErrorjitannotater   Fconv2dr%   r"   r#   prodl1_lossr   r   r!   r   r   r=   NotImplementedError)r,   rD   rE   r.   CHmuxmuymux2muy2muxysigmax2sigmay2sigmaxylccslMPIcsloss_ms_ssimloss_l1gaussian_l1lossr3   r3   r4   forward   sF   
T$


zMS_SSIMLoss.forward)r   r   r	   r
   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   )NN)
r5   r$   r0   r   r6   r7   r8   r9   r   r:   )rD   r:   rE   r:   r   r:   )	__name__
__module____qualname____doc__r    rA   r*   rk   __classcell__r3   r3   r1   r4   r      s    .r   )
__future__r   typingr   r   r&   torch.nn.functionalr   
functionalrU   Moduler   r3   r3   r3   r4   <module>   s   