o
    yi                     @   s(  d dl 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 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e dedeeeeef f fddZ				dd	ed
edee dee deed  dee defddZdS )    )OptionalSequenceTupleUnionN)Tensor)
functional)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 )zUpdates and returns variables required to compute Universal Image Quality Index. Checks for same shape and
    type of the input tensors.

    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   U/home/ubuntu/.local/lib/python3.10/site-packages/torchmetrics/functional/image/uqi.py_uqi_update   s$   	
r      r         ?r   elementwise_meanFkernel_sizesigma	reduction)r   sumnone
data_rangereturn_contrast_sensitivityc                 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|d
u rRt|  |   | |  }| j}| d}| j}	t||||	|}
|d d d }|d d d }t	j
| ||||fdd} t	j
|||||fdd}t| || |  || | | f}t	j||
|d}|| jd }|d d}|d d}|d |d  }|d | }|d | }|d | }d| }|| }d| | || |  }|d|| || f }t||S )a  Computes 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

        data_range: Range of the image. If ``None``, it is determined from the image (max - min)

    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>V   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(   Y   s    z.Expected `sigma` to have positive number. Got N   r   reflect)mode)groups   r   .)r   r   anymaxmindevicesizer   r	   Fpadtorchcatconv2dsplitr   powr   )r   r   r   r   r    r#   r$   r2   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loweruqi_idxr   r   r   _uqi_compute1   sH   "
 
rK   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

        data_range: Range of the image. If ``None``, it is determined from the image (max - min)

    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 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   rK   )r   r   r   r   r    r#   r   r   r   universal_image_quality_index~   s   5rL   )r   r   r   NF)r   r   r   N)typingr   r   r   r   r6   r   torch.nnr   r4   typing_extensionsr   $torchmetrics.functional.image.helperr	   torchmetrics.utilities.checksr
   "torchmetrics.utilities.distributedr   r   intfloatboolrK   rL   r   r   r   r   <module>   sd   

P
