a
    dT                     @   s  d dl mZmZmZmZmZ d dlZd dlmZ d dlm	Z
 d dlmZ d dlmZmZmZ d dlmZ d dlmZ eeeeef d	d
dZd-eeeeeee f eeee f eeeeeef f  eeeeeeeeef f dddZd.eed edddZd/eeeeeee f eeee f ed eeeeeef f  eeeeeeeeef f dddZd0eeeeeee f eeee f eeeeeef f  eeeed  eeef d
dd Zd1eeeeeee f eeee f eeeeeef f  eeeeeeeeef eed"f f eed  ed#d$d%Zd2eed ed&d'd(Zd3eeeeeee f eeee f ed eeeeeef f  eeeed"f eed  ed*d+d,ZdS )4    )ListOptionalSequenceTupleUnionN)Tensor)
functional)Literal)_gaussian_kernel_2d_gaussian_kernel_3d_reflection_pad_3d)_check_same_shapereduce)predstargetreturnc                 C   sR   | j |j kr|| j }t| | t| jdvrJtd| j d|j d| |fS )zUpdate and returns variables required to compute Structural Similarity Index Measure.

    Args:
        preds: Predicted tensor
        target: Ground truth tensor

    )      zMExpected `preds` and `target` to have BxCxHxW or BxCxDxHxW shape. Got preds: z and target: .)dtypetor   lenshape
ValueError)r   r    r   k/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/functional/image/ssim.py_ssim_check_inputs   s    
r   T      ?   {Gz?Q?F)r   r   gaussian_kernelsigmakernel_size
data_rangek1k2return_full_imagereturn_contrast_sensitivityr   c
           #      C   s  | j dk}
t|ts,|
r"d|g nd|g }t|tsN|
rDd|g nd|g }t|t|jd krtdt| dt|j t|dvrtdt| t|t|jd krtdt| dt|j t|dvrtdt| |r|	rtdtd	d
 |D r*td| dtdd
 |D rNtd| d|du r|t|  |   | |  }nLt|t	rt
j| |d |d d} t
j||d |d d}|d |d  }t|| d}t|| d}| j}| d}| j}dd |D }|d d d }|d d d }|
rr|d d d }t| |||} t||||}|rt|||||}nFtj| ||||fdd} tj|||||fdd}|rt|||||}|st
j|dg|R ||dt
t
j|||d }t
| || |  || | | f}|
r$tj|||dntj|||d}|| jd }|d d}|d d}|d |d  }|d | }|d | }|d | }d|| | }|| || }d| | | || | |  } |
r| d|| || || f }!n| d|| || f }!|	r|| }"|
rT|"d|| || || f }"n|"d|| || f }"|!|!jd dd|"|"jd ddfS |r|!|!jd dd| fS |!|!jd ddS )a#  Compute Structual Similarity Index Measure.

    Args:
        preds: estimated image
        target: ground truth image
        gaussian_kernel: If true (default), a gaussian kernel is used, if false a uniform kernel is used
        sigma: Standard deviation of the gaussian kernel, anisotropic kernels are possible.
            Ignored if a uniform kernel is used
        kernel_size: the size of the uniform kernel, anisotropic kernels are possible.
            Ignored if a Gaussian kernel is used
        data_range: Range of the image. If ``None``, it is determined from the image (max - min)
        k1: Parameter of SSIM.
        k2: Parameter of SSIM.
        return_full_image: If true, the full ``ssim`` image is returned as a second argument.
            Mutually exlusive with ``return_contrast_sensitivity``
        return_contrast_sensitivity: If true, the contrast term is returned as a second argument.
            The luminance term can be obtained with luminance=ssim/contrast
            Mutually exclusive with ``return_full_image``

    r         z`kernel_size` has dimension zD, but expected to be two less that target dimensionality, which is: )r+   r*   zMExpected `kernel_size` dimension to be 2 or 3. `kernel_size` dimensionality: zWArguments `return_full_image` and `return_contrast_sensitivity` are mutually exclusive.c                 s   s"   | ]}|d  dkp|dkV  qdS )r+   r   Nr   ).0xr   r   r   	<genexpr>j       z_ssim_update.<locals>.<genexpr>z8Expected `kernel_size` to have odd positive number. Got r   c                 s   s   | ]}|d kV  qdS )r   Nr   )r,   yr   r   r   r.   m   r/   z.Expected `sigma` to have positive number. Got Nr      )minmaxc                 S   s$   g | ]}t d | d d d qS )g      @g      ?r+   r1   )int)r,   sr   r   r   
<listcomp>}   r/   z _ssim_update.<locals>.<listcomp>Zreflect)mode)r   device)groupsr   .)ndim
isinstancer   r   r   r   anyr3   r2   tupletorchclamppowr8   sizer   r   r   Fpadr
   ZonesprodtensorcatZconv3dZconv2dsplitr   Zreshapemean)#r   r   r"   r#   r$   r%   r&   r'   r(   r)   is_3dZc1c2r8   Zchannelr   Zgauss_kernel_sizeZpad_hZpad_wZpad_dkernelZ
input_listoutputsZoutput_listZ
mu_pred_sqZmu_target_sqZmu_pred_targetZsigma_pred_sqZsigma_target_sqZsigma_pred_targetupperlowerZssim_idx_full_imageZssim_idxcontrast_sensitivityr   r   r   _ssim_update-   s     



$
 & $$
rQ   elementwise_mean)rR   sumnoneN)similarities	reductionr   c                 C   s
   t | |S )a  Apply the specified reduction to pre-computed structural similarity.

    Args:
        similarities: per image similarities for a batch of images.
        reduction: a method to reduce metric score over individual batch scores

                - ``'elementwise_mean'``: takes the mean
                - ``'sum'``: takes the sum
                - ``'none'`` or ``None``: no reduction will be applied

    Returns:
        The reduced SSIM score

    r   )rU   rV   r   r   r   _ssim_compute   s    rW   )r   r   r"   r#   r$   rV   r%   r&   r'   r(   r)   r   c                 C   sV   t | |\} }t| ||||||||	|

}t|trH|\}}t|||fS |}t||S )a  Compute Structual Similarity Index Measure.

    Args:
        preds: estimated image
        target: ground truth image
        gaussian_kernel: If true (default), a gaussian kernel is used, if false a uniform kernel is used
        sigma: Standard deviation of the gaussian kernel, anisotropic kernels are possible.
            Ignored if a uniform kernel is used
        kernel_size: the size of the uniform kernel, anisotropic kernels are possible.
            Ignored if a Gaussian kernel is used
        reduction: a method to reduce metric score over labels.

            - ``'elementwise_mean'``: takes the mean
            - ``'sum'``: takes the sum
            - ``'none'`` or ``None``: no reduction will be applied

        data_range:
            the range of the data. If None, it is determined from the data (max - min). If a tuple is provided then
            the range is calculated as the difference and input is clamped between the values.
        k1: Parameter of SSIM.
        k2: Parameter of SSIM.
        return_full_image: If true, the full ``ssim`` image is returned as a second argument.
            Mutually exclusive with ``return_contrast_sensitivity``
        return_contrast_sensitivity: If true, the constant term is returned as a second argument.
            The luminance term can be obtained with luminance=ssim/contrast
            Mutually exclusive with ``return_full_image``

    Return:
        Tensor with SSIM score

    Raises:
        TypeError:
            If ``preds`` and ``target`` don't have the same data type.
        ValueError:
            If ``preds`` and ``target`` don't have ``BxCxHxW shape``.
        ValueError:
            If the length of ``kernel_size`` or ``sigma`` is not ``2``.
        ValueError:
            If one of the elements of ``kernel_size`` is not an ``odd positive number``.
        ValueError:
            If one of the elements of ``sigma`` is not a ``positive number``.

    Example:
        >>> from torchmetrics.functional.image import structural_similarity_index_measure
        >>> preds = torch.rand([3, 3, 256, 256])
        >>> target = preds * 0.75
        >>> structural_similarity_index_measure(preds, target)
        tensor(0.9219)

    )r   rQ   r<   r>   rW   )r   r   r"   r#   r$   rV   r%   r&   r'   r(   r)   Zsimilarity_packZ
similarityimager   r   r   #structural_similarity_index_measure   s$    ?
rY   relusimple)
r   r   r"   r#   r$   r%   r&   r'   	normalizer   c	                 C   sB   t | |||||||dd	\}	}
|dkr:t|	}	t|
}
|	|
fS )NT)r)   r[   )rQ   r?   r[   )r   r   r"   r#   r$   r%   r&   r'   r]   simrP   r   r   r   _get_normalized_sim_and_cs%  s    


r_   gǺ?g48EG?ga4?g??g9EGr?.)r   r   r"   r#   r$   r%   r&   r'   betasr]   r   c
                 C   s@  g }
| j dk}t|ts0|r&d|g nd|g }t|tsR|rHd|g nd|g }|  d dt| k s|  d dt| k rtdt| ddt|  dtd	t|d	 d }|  d | |d
 d	 krtdt| d|d
  d|d
 d	 |  d|  d | |d	 d	 krVtdt| d|d	  d|d	 d	 |  dtt|D ]}t| ||||||||	d	\}}|
	| t|dkrt
| d} t
|d}n0t|dkrt
| d} t
|d}ntdqb||
d< t|
}|	dkr|d	 d }tj||jddd	}|| }tj|d
dS )a  Compute Multi-Scale Structual Similarity Index Measure.

    Adapted from: https://github.com/jorge-pessoa/pytorch-msssim/blob/master/pytorch_msssim/__init__.py.

    Args:
        preds: estimated image
        target: ground truth image
        gaussian_kernel: If true, a gaussian kernel is used, if false a uniform kernel is used
        sigma: Standard deviation of the gaussian kernel
        kernel_size: size of the gaussian kernel
        reduction: a method to reduce metric score over labels.

            - ``'elementwise_mean'``: takes the mean
            - ``'sum'``: takes the sum
            - ``'none'`` or ``None``: no reduction will be applied

        data_range: Range of the image. If ``None``, it is determined from the image (max - min)
        k1: Parameter of structural similarity index measure.
        k2: Parameter of structural similarity index measure.
        betas: Exponent parameters for individual similarities and contrastive sensitives returned by different image
            resolutions.
        normalize: When MultiScaleSSIM loss is used for training, it is desirable to use normalizes to improve the
            training stability. This `normalize` argument is out of scope of the original implementation [1], and it is
            adapted from https://github.com/jorge-pessoa/pytorch-msssim instead.

    Raises:
        ValueError:
            If the image height or width is smaller then ``2 ** len(betas)``.
        ValueError:
            If the image height is smaller than ``(kernel_size[0] - 1) * max(1, (len(betas) - 1)) ** 2``.
        ValueError:
            If the image width is smaller than ``(kernel_size[0] - 1) * max(1, (len(betas) - 1)) ** 2``.

    r   r*   r+   r:   z)For a given number of `betas` parameters zH, the image height and width dimensions must be larger than or equal to r   r1   r   z and kernel size z', the image height must be larger than z&, the image width must be larger than )r]   )r+   r+   )r+   r+   r+   z(length of kernel_size is neither 2 nor 3r\   )r8   )Zaxis)r;   r<   r   rB   r   r   r3   ranger_   appendrC   Z
avg_pool2dZ
avg_pool3dr?   stackrF   r8   viewrE   )r   r   r"   r#   r$   r%   r&   r'   ra   r]   Zmcs_listrJ   Z
_betas_div_r^   rP   Z	mcs_stackZmcs_weightedr   r   r   _multiscale_ssim_updateA  sX    4


0




rh   )mcs_per_imagerV   r   c                 C   s
   t | |S )a  Apply the specified reduction to pre-computed multi-scale structural similarity.

    Args:
        mcs_per_image: per image similarities for a batch of images.
        reduction: a method to reduce metric score over individual batch scores

                - ``'elementwise_mean'``: takes the mean
                - ``'sum'``: takes the sum
                - ``'none'`` or ``None``: no reduction will be applied

    Returns:
        The reduced multi-scale structural similarity

    r   )ri   rV   r   r   r   _multiscale_ssim_compute  s    rj   r[   )r   r   r"   r#   r$   rV   r%   r&   r'   ra   r]   r   c                 C   s|   t |	tstdt |	tr6tdd |	D s6td|
rJ|
dvrJtdt| |\} }t| ||||||||	|

}t||S )a{
  Compute `MultiScaleSSIM`_, Multi-scale Structual Similarity Index Measure.

    This metric is a generalization of Structual Similarity Index Measure by incorporating image details at different
    resolution scores.

    Args:
        preds: Predictions from model of shape ``[N, C, H, W]``
        target: Ground truth values of shape ``[N, C, H, W]``
        gaussian_kernel: If true, a gaussian kernel is used, if false a uniform kernel is used
        sigma: Standard deviation of the gaussian kernel
        kernel_size: size of the gaussian kernel
        reduction: a method to reduce metric score over labels.

            - ``'elementwise_mean'``: takes the mean
            - ``'sum'``: takes the sum
            - ``'none'`` or ``None``: no reduction will be applied

        data_range:
            the range of the data. If None, it is determined from the data (max - min). If a tuple is provided then
            the range is calculated as the difference and input is clamped between the values.
        k1: Parameter of structural similarity index measure.
        k2: Parameter of structural similarity index measure.
        betas: Exponent parameters for individual similarities and contrastive sensitivies returned by different image
            resolutions.
        normalize: When MultiScaleSSIM loss is used for training, it is desirable to use normalizes to improve the
            training stability. This `normalize` argument is out of scope of the original implementation [1], and it is
            adapted from https://github.com/jorge-pessoa/pytorch-msssim instead.

    Return:
        Tensor with Multi-Scale SSIM score

    Raises:
        TypeError:
            If ``preds`` and ``target`` don't have the same data type.
        ValueError:
            If ``preds`` and ``target`` don't have ``BxCxHxW shape``.
        ValueError:
            If the length of ``kernel_size`` or ``sigma`` is not ``2``.
        ValueError:
            If one of the elements of ``kernel_size`` is not an ``odd positive number``.
        ValueError:
            If one of the elements of ``sigma`` is not a ``positive number``.

    Example:
        >>> from torchmetrics.functional.image import multiscale_structural_similarity_index_measure
        >>> gen = torch.manual_seed(42)
        >>> preds = torch.rand([3, 3, 256, 256], generator=gen)
        >>> target = preds * 0.75
        >>> multiscale_structural_similarity_index_measure(preds, target, data_range=1.0)
        tensor(0.9627)

    References:
        [1] Multi-Scale Structural Similarity For Image Quality Assessment by Zhou Wang, Eero P. Simoncelli and Alan C.
        Bovik `MultiScaleSSIM`_

    z3Argument `betas` is expected to be of a type tuple.c                 s   s   | ]}t |tV  qd S )N)r<   float)r,   betar   r   r   r.     r/   zAmultiscale_structural_similarity_index_measure.<locals>.<genexpr>z5Argument `betas` is expected to be a tuple of floats.rZ   zNArgument `normalize` to be expected either `None` or one of 'relu' or 'simple')r<   r>   r   allr   rh   rj   )r   r   r"   r#   r$   rV   r%   r&   r'   ra   r]   ri   r   r   r   .multiscale_structural_similarity_index_measure  s    E
rn   )Tr   r   Nr    r!   FF)rR   )	Tr   r   rR   Nr    r!   FF)Tr   r   Nr    r!   N)Tr   r   Nr    r!   r`   N)rR   )	Tr   r   rR   Nr    r!   r`   r[   ) typingr   r   r   r   r   r?   r   Ztorch.nnr   rC   Ztyping_extensionsr	   Z$torchmetrics.functional.image.helperr
   r   r   Ztorchmetrics.utilities.checksr   Z"torchmetrics.utilities.distributedr   r   boolrk   r4   rQ   rW   rY   r_   rh   rj   rn   r   r   r   r   <module>   s                      X       

         
k          

