o
    ߥi'                     @   s   d dl mZ d dlZd dl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 eje	ejdG d	d
 d
eZdddZdddZdddZdd Zdd Zdd Zdd ZdS )    )DictN)Metrics)default_group   )Metric)METRICS
MetricKeys)	group_keymodule_namec                       s\   e Zd ZdZdZdZ fddZdedefdd	Zd
d Z	dddZ
dd Zdd Z  ZS )ImageDenoiseMetricz<The metric computation class for image denoise classes.
    predtargetc                    s   t t|   g | _g | _d S N)superr   __init__predslabelsself	__class__ [/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/metrics/image_denoise_metric.pyr      s   
zImageDenoiseMetric.__init__outputsinputsc                 C   s0   |t j }|t j }| j| | j| d S r   )r   
label_name	pred_namer   appendr   )r   r   r   ground_truthseval_resultsr   r   r   add   s   

zImageDenoiseMetric.addc                 C   sv   g g }}t | j| jD ] \}}|t|d |d dd |t|d |d dd qtjt	|tj
t	|iS )Nr   )crop_border)zipr   r   r   calculate_psnrcalculate_ssimr   PSNRnpmeanSSIM)r   	psnr_list	ssim_listr   labelr   r   r   evaluate%   s   
zImageDenoiseMetric.evaluateotherc                 C   s    | j |j  | j|j d S r   )r   extendr   )r   r-   r   r   r   merge/   s   zImageDenoiseMetric.mergec                 C   s   | j | jfS r   )r   r   r   r   r   r   __getstate__3   s   zImageDenoiseMetric.__getstate__c                 C   s   |    |\| _| _d S r   )r   r   r   )r   stater   r   r   __setstate__6   s   zImageDenoiseMetric.__setstate__)r-   r   )__name__
__module____qualname____doc__r   r   r   r   r    r,   r/   r0   r2   __classcell__r   r   r   r   r      s    

r   HWCc                 C   sH   |dvrt d| dt| jdkr| d } |dkr"| ddd} | S )	a  Reorder images to 'HWC' order.
    If the input_order is (h, w), return (h, w, 1);
    If the input_order is (c, h, w), return (h, w, c);
    If the input_order is (h, w, c), return as it is.
    Args:
        img (ndarray): Input image.
        input_order (str): Whether the input order is 'HWC' or 'CHW'.
            If the input image shape is (h, w), input_order will not have
            effects. Default: 'HWC'.
    Returns:
        ndarray: reordered image.
    r8   CHWWrong input_order z,. Supported input_orders are 'HWC' and 'CHW'   ).Nr:   r   r   )
ValueErrorlenshape	transpose)imginput_orderr   r   r   reorder_image;   s   
rC   c                 C   s<  | j |j ksJ d| j  d|j  d|dvrtd| dt| tjkr?t| j dkr2| d} |   	 
d	d
d} t|tjkr_t|j dkrR|d}|  	 
d	d
d}t| |d} t||d}| tj} |tj}|dkr| || || df } ||| || df }dd }|| |S )a^  Calculate PSNR (Peak Signal-to-Noise Ratio).
    Ref: https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio
    Args:
        img1 (ndarray/tensor): Images with range [0, 255]/[0, 1].
        img2 (ndarray/tensor): Images with range [0, 255]/[0, 1].
        crop_border (int): Cropped pixels in each edge of an image. These
            pixels are not involved in the PSNR 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: , .r9   r;   ,. Supported input_orders are "HWC" and "CHW"   r   r   r<   rB   .c                 S   sN   t | | d }|dkrtdS |  dkrdnd}dt |t |  S )Nr<   r   infr   g      ?g     o@g      4@)r&   r'   floatmaxlog10sqrt)img1img2mse	max_valuer   r   r   _psnr{   s
   zcalculate_psnr.<locals>._psnrr?   r=   typetorchTensorr>   squeezedetachcpunumpyr@   rC   astyper&   float64)rO   rP   r!   rB   rS   r   r   r   r#   T   s0   



r#   Tc                    s@  | j |j ksJ d| j  d|j  d|dvrtd| dt| tjkr?t| j dkr2| d} |   	 
d	d
d} t|tjkr_t|j dkrR|d}|  	 
d	d
d}t| |d} t||d}| tj} |tj}|dkr| || || df } ||| || df } fdd}|| |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:
        img1 (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 SSIM 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.
    rD   rE   rF   r9   r;   rG   rH   r   r   r<   rI   .c                    st   g }|   dkr
dnd}t   rt| ||nt| ||}|| W d    n1 s.w   Y  t| S )Nr      )	rL   rV   no_grad_ssim_3d_ssimr   r&   arrayr'   )rO   rP   ssimsrR   
final_ssimssim3dr   r   	_cal_ssim   s   
z!calculate_ssim.<locals>._cal_ssimrT   )rO   rP   r!   rB   rf   rg   r   re   r   r$      s0   



r$   c                 C   sR  d| d }d| d }|  tj} | tj}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.
    {Gz?r<   Q?         ?   )	r\   r&   r]   cv2getGaussianKernelouterr@   filter2Dr'   )rA   rP   rR   c1c2kernelwindowmu1mu2mu1_sqmu2_sqmu1_mu2	sigma1_sq	sigma2_sqsigma12tmp1tmp2ssim_mapr   r   r   ra      s(   
&&&ra   c                 C   s$   ||  d ddd}|S )Nr   )	unsqueezerX   )rA   conv3doutr   r   r   _3d_gaussian_calculator   s    r   c               	      s   t dd} t| |   t dd}ttj fdd|D dd} tjj	ddddd	d
dd}d
|j
_| |j
ddd d d d d d f< |S )Nrj   rk   c                    s   g | ]} | qS r   r   ).0krv   r   r   
<listcomp>   s    z0_generate_3d_gaussian_kernel.<locals>.<listcomp>r   )axisr   )rj   rj   rj   )rm   rm   rm   F	replicate)stridepaddingbiaspadding_mode)ro   rp   r&   rq   r@   rV   tensorstacknnConv3dweightrequires_grad)ru   kernel_3r   r   r   r   _generate_3d_gaussian_kernel   s   " r   c                 C   s&  t | jdkrt |jdksJ 	 d| d }d| d }| tj} |tj}t  }t| 	  } t|	  }t
| |}t
||}|d }|d }	|| }
t
| d || }t
|d ||	 }t
| | ||
 }d|
 | d| |  }||	 | || |  }|| }t	| S )N   rh   r<   ri   )r>   r?   r\   r&   r]   r   cudarV   r   rK   r   r'   )rO   rP   rR   C1C2ru   rw   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   r   r   r`      s*    


r`   )r8   )r8   T)typingr   ro   r[   r&   rV   modelscope.metainfor   modelscope.utils.registryr   baser   builderr   r   register_moduleimage_denoise_metricr   rC   r#   r$   ra   r   r   r`   r   r   r   r   <module>   s&   
'

2<"