o
    .wi                     @   s   d dl mZ d dlmZ d dlZd dlmZmZ d dlmZ d dl	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			dd	ed
edee dee deed  defddZ			dd	ed
edee dee deed  defddZdS )    )Sequence)OptionalN)Tensornn)Literal)_gaussian_kernel_2d)_check_same_shape)reducepredstargetreturnc                 C   s`   | j |j krtd| j  d|j  dt| | t| jdkr,td| j d|j d| |fS )zUpdate and returns variables required to compute Universal Image Quality Index.

    Args:
        preds: Predicted tensor
        target: Ground truth tensor

    zEExpected `preds` and `target` to have the same data type. Got preds: z and target: .   z@Expected `preds` and `target` to have BxCxHxW shape. Got preds: )dtype	TypeErrorr   lenshape
ValueError)r
   r    r   ^/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/torchmetrics/functional/image/uqi.py_uqi_update   s   
r      r         ?r   elementwise_meankernel_sizesigma	reduction)r   sumnonec                 C   s  t |dkst |dkrtdt | dt | dtdd |D r,td| dtdd |D r=td	| d| j}| d
}| j}t|||||}|d d
 d }	|d
 d
 d }
tjj	| |	|	|
|
fdd} tjj	||	|	|
|
fdd}t
| || |  || | | f}tjj|||d}|| jd }|d d}|d
 d}|d |d
  }t
j|d | dd}t
j|d | dd}|d | }d| }|| }t
|jj}d| | || | |  }|d|	|	 |
|
 f }t||S )a  Compute Universal Image Quality Index.

    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 (default)
            - ``'sum'``: takes the sum
            - ``'none'`` or ``None``: no reduction will be applied

    Example:
        >>> preds = torch.rand([16, 1, 16, 16])
        >>> target = preds * 0.75
        >>> preds, target = _uqi_update(preds, target)
        >>> _uqi_compute(preds, target)
        tensor(0.9216)

       zOExpected `kernel_size` and `sigma` to have the length of two. Got kernel_size: z and sigma: r   c                 s   s$    | ]}|d  dkp|dkV  qdS )r!   r   Nr   ).0xr   r   r   	<genexpr>Q   s   " z_uqi_compute.<locals>.<genexpr>z8Expected `kernel_size` to have odd positive number. Got c                 s   s    | ]}|d kV  qdS )r   Nr   )r"   yr   r   r   r$   T   s    z.Expected `sigma` to have positive number. Got    r   reflect)mode)groupsg        )min   r   .)r   r   anydevicesizer   r   r   
functionalpadtorchcatconv2dsplitr   powclampfinfoepsr	   )r
   r   r   r   r   r-   channelr   kernelpad_hpad_w
input_listoutputsoutput_list
mu_pred_sqmu_target_sqmu_pred_targetsigma_pred_sqsigma_target_sqsigma_pred_targetupperlowerr8   uqi_idxr   r   r   _uqi_compute/   sF   
 
rI   c                 C   s   t | |\} }t| ||||S )a  Universal Image Quality Index.

    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 (default)
            - ``'sum'``: takes the sum
            - ``'none'`` or ``None``: no reduction will be applied

    Return:
        Tensor with UniversalImageQualityIndex 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 universal_image_quality_index
        >>> preds = torch.rand([16, 1, 16, 16])
        >>> target = preds * 0.75
        >>> universal_image_quality_index(preds, target)
        tensor(0.9216)

    References:
        [1] Zhou Wang and A. C. Bovik, "A universal image quality index," in IEEE Signal Processing Letters, vol. 9,
        no. 3, pp. 81-84, March 2002, doi: 10.1109/97.995823.

        [2] Zhou Wang, A. C. Bovik, H. R. Sheikh and E. P. Simoncelli, "Image quality assessment: from error visibility
        to structural similarity," in IEEE Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, April 2004,
        doi: 10.1109/TIP.2003.819861.

    )r   rI   )r
   r   r   r   r   r   r   r   universal_image_quality_indexw   s   3rJ   )r   r   r   )collections.abcr   typingr   r1   r   r   typing_extensionsr   #torchmetrics.functional.image.utilsr   torchmetrics.utilities.checksr   "torchmetrics.utilities.distributedr	   tupler   intfloatrI   rJ   r   r   r   r   <module>   sR   

K
