a
    d!                     @   s   d dl Z d dlZd dlZd dlm  mZ d dlm	Z	m
Z
 d dlmZ d dlmZ e dddZe dd	d
Ze dddZe dddZdd Zdd ZdS )    N)reorder_imageto_y_channel)rgb2ycbcr_pt)METRIC_REGISTRYHWCFc                 K   s   | j |j ks&J d| j  d|j  d|dvr>td| dt| |d} t||d}|dkr| || || d	f } ||| || d	f }|rt| } t|}| tj} |tj}t| | d
 }|dkrtdS dt	d|  S )a'  Calculate PSNR (Peak Signal-to-Noise Ratio).

    Ref: https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio

    Args:
        img (ndarray): Images with range [0, 255].
        img2 (ndarray): Images with range [0, 255].
        crop_border (int): Cropped pixels in each edge of an image. These pixels are not involved in the calculation.
        input_order (str): Whether the input order is 'HWC' or 'CHW'. Default: 'HWC'.
        test_y_channel (bool): Test on Y channel of YCbCr. Default: False.

    Returns:
        float: PSNR result.
    Image shapes are different: , .r   ZCHWWrong input_order ,. Supported input_orders are "HWC" and "CHW"input_orderr   .   inf      $@g     @)
shape
ValueErrorr   r   astypenpfloat64meanfloatlog10)imgimg2crop_borderr   test_y_channelkwargsmse r    b/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/basicsr/metrics/psnr_ssim.pycalculate_psnr   s"    &r"   c                 K   s   | j |j ks&J d| j  d|j  d|dkrv| dddd|| || f } |dddd|| || f }|rt| dd} t|dd}| tj} |tj}tj| | d g d	d
}dtd|d   S )a	  Calculate PSNR (Peak Signal-to-Noise Ratio) (PyTorch version).

    Ref: https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio

    Args:
        img (Tensor): Images with range [0, 1], shape (n, 3/1, h, w).
        img2 (Tensor): Images with range [0, 1], shape (n, 3/1, h, w).
        crop_border (int): Cropped pixels in each edge of an image. These pixels are not involved in the calculation.
        test_y_channel (bool): Test on Y channel of YCbCr. Default: False.

    Returns:
        float: PSNR result.
    r   r   r	   r   NTZy_onlyr      r      )Zdimr   g      ?g:0yE>)r   r   totorchr   r   r   )r   r   r   r   r   r   r    r    r!   calculate_psnr_pt3   s    &$$r)   c                 K   s  | j |j ks&J d| j  d|j  d|dvr>td| dt| |d} t||d}|dkr| || || d	f } ||| || d	f }|rt| } t|}| tj} |tj}g }t| j d
 D ]$}|t	| d	|f |d	|f  qt
| S )a   Calculate SSIM (structural similarity).

    Ref:
    Image quality assessment: From error visibility to structural similarity

    The results are the same as that of the official released MATLAB code in
    https://ece.uwaterloo.ca/~z70wang/research/ssim/.

    For three-channel images, SSIM is calculated for each channel and then
    averaged.

    Args:
        img (ndarray): Images with range [0, 255].
        img2 (ndarray): Images with range [0, 255].
        crop_border (int): Cropped pixels in each edge of an image. These pixels are not involved in the calculation.
        input_order (str): Whether the input order is 'HWC' or 'CHW'.
            Default: 'HWC'.
        test_y_channel (bool): Test on Y channel of YCbCr. Default: False.

    Returns:
        float: SSIM result.
    r   r   r	   r
   r   r   r   r   .r   )r   r   r   r   r   r   r   rangeappend_ssimarrayr   )r   r   r   r   r   r   Zssimsir    r    r!   calculate_ssimT   s"    &"r/   c                 K   s   | j |j ks&J d| j  d|j  d|dkrv| dddd|| || f } |dddd|| || f }|rt| dd} t|dd}| tj} |tj}t| d |d }|S )	a  Calculate SSIM (structural similarity) (PyTorch version).

    Ref:
    Image quality assessment: From error visibility to structural similarity

    The results are the same as that of the official released MATLAB code in
    https://ece.uwaterloo.ca/~z70wang/research/ssim/.

    For three-channel images, SSIM is calculated for each channel and then
    averaged.

    Args:
        img (Tensor): Images with range [0, 1], shape (n, 3/1, h, w).
        img2 (Tensor): Images with range [0, 1], shape (n, 3/1, h, w).
        crop_border (int): Cropped pixels in each edge of an image. These pixels are not involved in the calculation.
        test_y_channel (bool): Test on Y channel of YCbCr. Default: False.

    Returns:
        float: SSIM result.
    r   r   r	   r   NTr#   g     o@)r   r   r'   r(   r   	_ssim_pth)r   r   r   r   r   Zssimr    r    r!   calculate_ssim_pt   s    &$$r1   c                 C   s"  d}d}t dd}t|| }t | d|ddddf }t |d|ddddf }|d }|d }	|| }
t | d d|ddddf | }t |d d|ddddf |	 }t | | d|ddddf |
 }d|
 | d| |  ||	 | || |   }| S )	a-  Calculate SSIM (structural similarity) for one channel images.

    It is called by func:`calculate_ssim`.

    Args:
        img (ndarray): Images with range [0, 255] with order 'HWC'.
        img2 (ndarray): Images with range [0, 255] with order 'HWC'.

    Returns:
        float: SSIM result.
    (\@zGBM@         ?   r   )cv2getGaussianKernelr   outer	transposeZfilter2Dr   )r   r   c1c2kernelwindowmu1mu2mu1_sqmu2_sqmu1_mu2	sigma1_sq	sigma2_sqsigma12ssim_mapr    r    r!   r,      s    &&&0r,   c                 C   sT  d}d}t dd}t|| }t|dddd| 	dddd
| j
| j}tj| |dd| jd d}tj||dd|jd d}|d}|d}	|| }
tj| |  |dd| jd d| }tj|| |dd| jd d|	 }tj| | |dd| jd d|
 }d| | || |  }d|
 | ||	 |  | }|g d	S )
a/  Calculate SSIM (structural similarity) (PyTorch version).

    It is called by func:`calculate_ssim_pt`.

    Args:
        img (Tensor): Images with range [0, 1], shape (n, 3/1, h, w).
        img2 (Tensor): Images with range [0, 1], shape (n, 3/1, h, w).

    Returns:
        float: SSIM result.
    r2   r3   r4   r5   r%   r   )Zstridepaddinggroupsr   r$   )r9   r:   r   r;   r<   r(   Z
from_numpyviewexpandsizer'   ZdtypeZdeviceFZconv2dr   powr   )r   r   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   Zcs_maprI   r    r    r!   r0      s     8

"""r0   )r   F)F)r   F)F)r9   numpyr   r(   Ztorch.nn.functionalnnZ
functionalrO   Zbasicsr.metrics.metric_utilr   r   Zbasicsr.utils.color_utilr   Zbasicsr.utils.registryr   registerr"   r)   r/   r1   r,   r0   r    r    r    r!   <module>   s    ' /'