a
    d                     @   s   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 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e
d  edddZdeeee ee ee
d  edddZdS )    )OptionalSequenceTupleN)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rXt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   j/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/functional/image/uqi.py_uqi_update   s$    
r      r         ?r   elementwise_mean)r   sumnone)r   r   kernel_sizesigma	reductionr   c                 C   s  t |dkst |dkr6tdt | dt | dtdd |D rXtd| dtdd |D rztd	| d| 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| }|| 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>R       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%   U   r&   z.Expected `sigma` to have positive number. Got    r   Zreflect)mode)groups   r   .)r   r   anydevicesizer   r   FpadtorchcatZconv2dsplitr   powZfinfoZepsr
   )r   r   r   r    r!   r-   Zchannelr   kernelZpad_hZpad_wZ
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uqi_idxr   r   r   _uqi_compute0   sD    
 r9   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   r9   )r   r   r   r    r!   r   r   r   universal_image_quality_indexw   s    3r:   )r   r   r   )r   r   r   )typingr   r   r   r1   r   Ztorch.nnr   r/   Ztyping_extensionsr   Z$torchmetrics.functional.image.helperr   Ztorchmetrics.utilities.checksr	   Z"torchmetrics.utilities.distributedr
   r   intfloatr9   r:   r   r   r   r   <module>   s<      
J   
