o
    yiP                     @   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 d	ed
edeeef fddZ								d5d	ed
ededeeee f deeee f dee dededededeeeeef f fddZ	d6ded ed! defd"d#Z									d7d	ed
ededeeee f deeee f d ed! dee dededededeeeeef f fd$d%Z							d8d	ed
ededeeee f deeee f dee deded&eed'  deeef fd(d)Z							*	d9d	ed
ededeeee f deeee f dee deded+eeeeeeef eed,f f d&eed'  defd-d.Z	d6d/ed ed! defd0d1Z								*	2d:d	ed
ededeeee f deeee f d ed! dee deded+eed,f d&eed'  defd3d4ZdS );    )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r%td| j d|j d| |fS )zUpdates and returns variables required to compute Structural Similarity Index Measure. Checks for same shape
    and type of the input tensors.

    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   V/home/ubuntu/.local/lib/python3.10/site-packages/torchmetrics/functional/image/ssim.py_ssim_check_inputs   s   	
r   T      ?   {Gz?Q?Fgaussian_kernelsigmakernel_size
data_rangek1k2return_full_imagereturn_contrast_sensitivityc
           #      C   s\  t | jdk}
t|ts|
rd|g nd|g }t|ts)|
r$d|g nd|g }t |t |jd krCtdt | dt |j t |dvrRtdt | t |t |jd krltdt | dt |j t |dvr{tdt | |r|	rtdtd	d
 |D rtd| dtdd
 |D rtd| d|du rt|  |   | |  }t|| d}t|| d}| j	}| 
d}| j}dd |D }|d d d }|d d d }|
r|d d d }t| |||} t||||}|rt|||||}n#tj| ||||fdd} tj|||||fdd}|r2t|||||}|sMtj|dg|R ||dttj|||d }t| || |  || | | f}|
rit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|| }"|"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#  Computes 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   s   " 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   s    z.Expected `sigma` to have positive number. Got N   c                 S   s$   g | ]}t d | d d d qS )g      @g      ?r+   r0   )int)r,   sr   r   r   
<listcomp>y   s   $ z _ssim_update.<locals>.<listcomp>r   reflect)mode)r   device)groupsr   .)r   r   
isinstancer   r   anymaxminpowr6   sizer   r   r   Fpadr
   torchonesprodtensorcatconv3dconv2dsplitr   reshapemean)#r   r   r"   r#   r$   r%   r&   r'   r(   r)   is_3dc1c2r6   channelr   gauss_kernel_sizepad_hpad_wpad_dkernel
input_listoutputsoutput_list
mu_pred_sqmu_target_sqmu_pred_targetsigma_pred_sqsigma_target_sqsigma_pred_targetupperlowerssim_idx_full_imagessim_idxcontrast_sensitivityr   r   r   _ssim_update.   s   

"
  $
rb   elementwise_meansimilarities	reduction)rc   sumnoneNc                 C   
   t | |S )a  Applies 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   )rd   re   r   r   r   _ssim_compute      
ri   c                 C   sV   t | |\} }t| ||||||||	|

}t|tr$|\}}t|||fS |}t||S )a(  Computes 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: 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 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 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   rb   r9   tupleri   )r   r   r"   r#   r$   re   r%   r&   r'   r(   r)   similarity_pack
similarityimager   r   r   #structural_similarity_index_measure   s$   <

ro   	normalizerelusimplec	                 C   sB   t | |||||||dd	\}	}
|dkrt|	}	t|
}
|	|
fS )NT)r)   rr   )rb   rA   rr   )r   r   r"   r#   r$   r%   r&   r'   rp   simra   r   r   r   _get_normalized_sim_and_cs  s   


ru   gǺ?g48EG?ga4?g??g9EGr?betas.c
                 C   s<  g }
t | jdk}t|ts|rd|g nd|g }t|ts+|r&d|g nd|g }|  d dt | k sC|  d dt | k rTtdt | ddt |  dtd	t |d	 d }|  d | |d
 d	 krtdt | d|d
  d|d
 d	 |  d|  d | |d	 d	 krtdt | d|d	  d|d	 d	 |  dtt |D ]?}t| ||||||||	d	\}}|
	| t |dkrt
| d} t
|d}qt |dkrt
| d} t
|d}qtd||
d< t|
}|	dkr|d	 d }tj||jddd	}|| }tj|d
d}|S )aQ  Computes 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
        kernel_size: size of the gaussian kernel
        sigma: Standard deviation 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+   r8   z)For a given number of `betas` parameters zH, the image height and width dimensions must be larger than or equal to r   r0   r   z and kernel size z', the image height must be larger than z&, the image width must be larger than )rp   )r+   r+   )r+   r+   r+   z(length of kernel_size is neither 2 nor 3rs   )r6   )axis)r   r   r9   r   r>   r   r;   rangeru   appendr?   
avg_pool2d
avg_pool3drA   stackrD   r6   viewrC   )r   r   r"   r#   r$   r%   r&   r'   rw   rp   mcs_listrK   
_betas_div_rt   ra   	mcs_stackmcs_weightedmcs_per_imager   r   r   _multiscale_ssim_update9  sZ   2

0




r   r   c                 C   rh   )a  Applies 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   )r   re   r   r   r   _multiscale_ssim_compute  rj   r   rr   c                 C   s|   t |	ts	tdt |	trtdd |	D std|
r%|
dvr%tdt| |\} }t| ||||||||	|

}t||S )ao	  Computes `MultiScaleSSIM`_, Multi-scale Structual Similarity Index Measure, which 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]``
        kernel_size: size of the gaussian kernel
        sigma: Standard deviation 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 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 import multiscale_structural_similarity_index_measure
        >>> preds = torch.rand([3, 3, 256, 256], generator=torch.manual_seed(42))
        >>> 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)r9   float)r,   betar   r   r   r.     s    zAmultiscale_structural_similarity_index_measure.<locals>.<genexpr>z5Argument `betas` is expected to be a tuple of floats.rq   zNArgument `normalize` to be expected either `None` or one of 'relu' or 'simple')r9   rk   r   allr   r   r   )r   r   r"   r#   r$   re   r%   r&   r'   rw   rp   r   r   r   r   .multiscale_structural_similarity_index_measure  s   
>
r   )Tr   r   Nr    r!   FF)rc   )	Tr   r   rc   Nr    r!   FF)Tr   r   Nr    r!   N)Tr   r   Nr    r!   rv   N)	Tr   r   rc   Nr    r!   rv   rr   ) typingr   r   r   r   r   rA   r   torch.nnr   r?   typing_extensionsr	   $torchmetrics.functional.image.helperr
   r   r   torchmetrics.utilities.checksr   "torchmetrics.utilities.distributedr   r   boolr   r1   rb   ri   ro   ru   r   r   r   r   r   r   r   <module>   sp  	

 
	

U
	


 	

k
	


