a
    dX                     @   s2  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 eeejeejef eddd	Zeee ee ejeejef ed
ddZeeeeef dddZdeeeeedddZdeeeedddZeeedddZeee ee ejejed
ddZeeeeedddZdS )    )SequenceTupleUnionN)Tensor)
functional)rank_zero_warn)_TORCH_GREATER_EQUAL_1_10)kernel_sizesigmadtypedevicereturnc                 C   sT   t jd|  d d|  d d||d}t t || d d }||  jddS )aY  Compute 1D gaussian kernel.

    Args:
        kernel_size: size of the gaussian kernel
        sigma: Standard deviation of the gaussian kernel
        dtype: data type of the output tensor
        device: device of the output tensor

    Example:
        >>> _gaussian(3, 1, torch.float, 'cpu')
        tensor([[0.2741, 0.4519, 0.2741]])

          )startendstepr   r   r   dim)torcharangeexppowsum	unsqueeze)r	   r
   r   r   distgauss r   m/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/functional/image/helper.py	_gaussian   s    $r   )channelr	   r
   r   r   r   c                 C   sT   t |d |d ||}t |d |d ||}t| |}|| d|d |d S )a  Compute 2D gaussian kernel.

    Args:
        channel: number of channels in the image
        kernel_size: size of the gaussian kernel as a tuple (h, w)
        sigma: Standard deviation of the gaussian kernel
        dtype: data type of the output tensor
        device: device of the output tensor

    Example:
        >>> _gaussian_kernel_2d(1, (5,5), (1,1), torch.float, "cpu")
        tensor([[[[0.0030, 0.0133, 0.0219, 0.0133, 0.0030],
                  [0.0133, 0.0596, 0.0983, 0.0596, 0.0133],
                  [0.0219, 0.0983, 0.1621, 0.0983, 0.0219],
                  [0.0133, 0.0596, 0.0983, 0.0596, 0.0133],
                  [0.0030, 0.0133, 0.0219, 0.0133, 0.0030]]]])

    r   r   )r   r   matmultexpand)r    r	   r
   r   r   gaussian_kernel_xgaussian_kernel_ykernelr   r   r   _gaussian_kernel_2d   s    r'   )inputswindow_sizer   c                 C   sB   t jdd||| j| jd}||d  }t jd| j| jd}||fS )zConstruct uniform weight and bias for a 2d convolution.

    Args:
        inputs: Input image
        window_size: size of convolutional kernel

    Return:
        The weight and bias for 2d convolution

    r   )r   r   r   )r   Zonesr   r   zeros)r(   r)   kernel_weightkernel_biasr   r   r   _uniform_weight_bias_conv2d>   s    r-   )r(   r   pad	outer_padr   c              	   C   sl   | j | }t| |t|d dd| j}t| |t|d || | d| j}t|| |f|S )a,  Apply single-dimension reflection padding to match scipy implementation.

    Args:
        inputs: Input image
        dim: A dimension the image should be padded over
        pad: Number of pads
        outer_pad: Number of outer pads

    Return:
        Image padded over a single dimension

    r   )shaper   Zindex_selectr   tor   cat)r(   r   r.   r/   Z_maxxyr   r   r   _single_dimension_padO   s    
$,r6   )r(   r.   r/   r   c                 C   s   dD ]}t | |||} q| S )zApply reflection padding to the input image.

    Args:
        inputs: Input image
        pad: Number of pads
        outer_pad: Number of outer pads

    Return:
        Padded image

    )r      )r6   )r(   r.   r/   r   r   r   r   _reflection_pad_2db   s    r8   c                    sL   t  |d |d  t |\tj fddt jd D ddS )zApply uniform filter with a window of a given size over the input image.

    Args:
        inputs: Input image
        window_size: Sliding window used for rmse calculation

    Return:
        Image transformed with the uniform input

    r   c                    s0   g | ](}t j d d |f dddqS )Nr   r   )padding)FZconv2dr   ).0r    r(   r,   r+   r   r   
<listcomp>   s   z#_uniform_filter.<locals>.<listcomp>r   r   )r8   r-   r   r3   ranger1   )r(   r)   r   r<   r   _uniform_filters   s    r?   c           
   	   C   s   t |d |d ||}t |d |d ||}t |d |d ||}t| |}t|ddd|d ||d |d |d }	|	| d|d |d |d S )a6  Compute 3D gaussian kernel.

    Args:
        channel: number of channels in the image
        kernel_size: size of the gaussian kernel as a tuple (h, w, d)
        sigma: Standard deviation of the gaussian kernel
        dtype: data type of the output tensor
        device: device of the output tensor

    r   r   r   r0   )r   r   r!   r"   mulr   repeatr#   )
r    r	   r
   r   r   r$   r%   Zgaussian_kernel_zZ	kernel_xyr&   r   r   r   _gaussian_kernel_3d   s    rB   )r(   pad_hpad_wpad_dr   c                 C   sZ   t r"tj| ||||||fdd} n4td t|||gD ]\}}t| |d |dd} q8| S )aU  Reflective padding of 3d input.

    Args:
        inputs: tensor to pad, should be a 3D tensor of shape ``[N, C, H, W, D]``
        pad_w: amount of padding in the height dimension
        pad_h: amount of padding in the width dimension
        pad_d: amount of padding in the depth dimension

    Returns:
        padded input tensor

    Zreflect)modezkAn older version of pyTorch is used. For optimal speed, please upgrade to at least PyTorch v1.10 or higher.r   r   )r/   )r   r:   r.   r   	enumerater6   )r(   rC   rD   rE   r   r.   r   r   r   _reflection_pad_3d   s    rH   )r   )r   )typingr   r   r   r   r   Ztorch.nnr   r:   Ztorchmetrics.utilitiesr   Ztorchmetrics.utilities.importsr   intfloatr   r   strr   r'   r-   r6   r8   r?   rB   rH   r   r   r   r   <module>   s*   " 