o
    .wiU                     @   s  d dl mZ d dl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								d6d
edededeeee f deeee f deeeeeef f  dededededeeeeef f fddZ	d7d ed!ed" defd#d$Z									d8d
edededeeee f deeee f d!ed" deeeeeef f  dededededeeeeef 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eeeef f  deded'eed(  deeef fd)d*Z							+	d:d
edededeeee f deeee f deeeeeef f  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	d7d0ed!ed" defd1d2Z								+	3d;d
edededeeee f deeee f d!ed" deeeeeef f  deded,eed-f d'eed(  defd4d5Z dS )<    )Sequence)ListOptional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 )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   _/home/ubuntu/sommelier/.venv/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  | 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rAtdt| dt|j t|dvrPtdt| t|t|jd krjtdt| dt|j t|dvrytdt| |r|	rtdtd	d
 |D rtd| dtdd
 |D rtd| d|du rt|  |   | |  }n%t|t	rt
j| |d |d d} t
j||d |d d}|d |d  }t|| d}t|| d}| j}| d}| j}dd |D }|r|d d d }|d d d }n|d d d }|d d d }|
rG|d d d }t| |||} t||||}|rFt|||||}n#tj| ||||fdd} tj|||||fdd}|rjt|||||}|st
j|dg|R ||dt
t
j|||d }t
| || |  || | | f}|
rtj|||dntj|||d}|| jd }|d d}|d d}|d |d  }t
j|d | dd}t
j|d | dd}|d | }d|| | }|| || }d| | | || | |  } |	rE|| }!|
r |!d|| || || f }!n|!d|| || f }!| | jd dd|!|!jd ddfS |rV| | jd dd| fS | | jd ddS )a%  Compute Structural 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 exclusive 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>k   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-   n   s    z.Expected `sigma` to have positive number. Got Nr      )minmaxc                 S   s$   g | ]}t d | d d d qS )g      @g      ?r*   r/   )int)r+   sr   r   r   
<listcomp>~   s   $ z _ssim_update.<locals>.<listcomp>reflect)mode)r   device)groupsg        )r0   r   .)ndim
isinstancer   r   r   r   anyr1   r0   tupletorchclamppowr7   sizer   r   r
   Fpadr	   onesprodtensorcatconv3dconv2dsplitr   reshapemean)"r   r   r!   r"   r#   r$   r%   r&   r'   r(   is_3dc1c2r7   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contrast_sensitivityr   r   r   _ssim_update.   s   
 

$

 & $
rc   elementwise_meansimilarities	reduction)rd   sumnoneNc                 C   
   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   )re   rf   r   r   r   _ssim_compute      
rj   c                 C   sV   t | |\} }t| ||||||||	|

}t|tr$|\}}t|||fS |}t||S )a  Compute Structural 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   rc   r;   r=   rj   )r   r   r!   r"   r#   rf   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   )rc   r>   rr   )r   r   r!   r"   r#   r$   r%   r&   rp   simrb   r   r   r   _get_normalized_sim_and_cs'  s   


ru   gǺ?g48EG?ga4?g??g9EGr?betas.c
                 C   s4  g }
| 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 sA|  d dt| k rRt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 )a  Compute Multi-Scale Structural 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*   r9   z)For a given number of `betas` parameters zH, the image height and width dimensions must be larger than or equal to r   r/   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   )r7   )axis)r:   r;   r   rA   r   r   r1   rangeru   appendrB   
avg_pool2d
avg_pool3dr>   stackrF   r7   viewrE   )r   r   r!   r"   r#   r$   r%   r&   rw   rp   mcs_listrM   
_betas_div_rt   rb   	mcs_stackmcs_weightedr   r   r   _multiscale_ssim_updateC  sX   4


0




r   mcs_per_imagec                 C   ri   )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   )r   rf   r   r   r   _multiscale_ssim_compute  rk   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 )ae
  Compute `MultiScaleSSIM`_, Multi-scale Structural Similarity Index Measure.

    This metric is a generalization of Structural 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 sensitivities 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 torch import rand
        >>> from torchmetrics.functional.image import multiscale_structural_similarity_index_measure
        >>> preds = rand([3, 3, 256, 256])
        >>> target = preds * 0.75
        >>> multiscale_structural_similarity_index_measure(preds, target, data_range=1.0)
        tensor(0.9628)

    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-     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')r;   r=   r   allr   r   r   )r   r   r!   r"   r#   rf   r$   r%   r&   rw   rp   r   r   r   r   .multiscale_structural_similarity_index_measure  s   
E
r   )Tr   r   Nr   r    FF)rd   )	Tr   r   rd   Nr   r    FF)Tr   r   Nr   r    N)Tr   r   Nr   r    rv   N)	Tr   r   rd   Nr   r    rv   rr   )!collections.abcr   typingr   r   r   r>   r   torch.nnr   rB   typing_extensionsr   #torchmetrics.functional.image.utilsr	   r
   r   torchmetrics.utilities.checksr   "torchmetrics.utilities.distributedr   r=   r   boolr   r2   rc   rj   ro   ru   r   r   r   r   r   r   r   <module>   sr  	

 
	

X
	


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


