a
    d0                     @   s   d dl Z d dlmZmZ d dlZd dlmZ d dlm  mZ	 d dl
mZmZ g dZejdddZG dd	 d	ejZG d
d dejZG dd dejZdejeeeejdddZdejeeejdddZdejeeeeej dddZdS )    N)ListTuple)filter2dgaussian_blur2d)PyrDownPyrUpScalePyramidpyrdownpyrupbuild_pyramidreturnc                   C   s.   t g dg dg dg dg dggd S )z<Utility function that return a pre-computed gaussian kernel.)      ?      @      @r   r   )r         0@      8@r   r   )r   r   g      B@r   r   g      p@)torchZtensor r   r   j/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/geometry/transform/pyramid.py_get_pyramid_gaussian_kernel   s    r   c                       sB   e Zd ZdZdeeedd fddZej	ej	d	d
dZ
  ZS )r   a2  Blur a tensor and downsamples it.

    Args:
        border_type: the padding mode to be applied before convolving.
          The expected modes are: ``'constant'``, ``'reflect'``,
          ``'replicate'`` or ``'circular'``.
        align_corners: interpolation flag.
        factor: the downsampling factor

    Return:
        the downsampled tensor.

    Shape:
        - Input: :math:`(B, C, H, W)`
        - Output: :math:`(B, C, H / 2, W / 2)`

    Examples:
        >>> input = torch.rand(1, 2, 4, 4)
        >>> output = PyrDown()(input)  # 1x2x2x2
    reflectF       @N)border_typealign_cornersfactorr   c                    s    t    || _|| _|| _d S N)super__init__r   r   r   )selfr   r   r   	__class__r   r   r   5   s    
zPyrDown.__init__inputr   c                 C   s   t || j| j| jS r   )r	   r   r   r   r   r#   r   r   r   forward;   s    zPyrDown.forward)r   Fr   )__name__
__module____qualname____doc__strboolfloatr   r   Tensorr%   __classcell__r   r   r    r   r      s   r   c                       s>   e Zd ZdZd
eed fddZejejddd	Z	  Z
S )r   a  Upsample a tensor and then blurs it.

    Args:
        borde_type: the padding mode to be applied before convolving.
          The expected modes are: ``'constant'``, ``'reflect'``,
          ``'replicate'`` or ``'circular'``.
        align_corners: interpolation flag.

    Return:
        the upsampled tensor.

    Shape:
        - Input: :math:`(B, C, H, W)`
        - Output: :math:`(B, C, H * 2, W * 2)`

    Examples:
        >>> input = torch.rand(1, 2, 4, 4)
        >>> output = PyrUp()(input)  # 1x2x8x8
    r   F)r   r   c                    s   t    || _|| _d S r   )r   r   r   r   )r   r   r   r    r   r   r   T   s    
zPyrUp.__init__r"   c                 C   s   t || j| jS r   )r
   r   r   r$   r   r   r   r%   Y   s    zPyrUp.forward)r   F)r&   r'   r(   r)   r*   r+   r   r   r-   r%   r.   r   r   r    r   r   ?   s   r   c                       sn   e Zd ZdZdeeeed fddZed	d
dZ	edddZ
dd Zejeeeef dddZ  ZS )r   a  Create an scale pyramid of image, usually used for local feature detection.

    Images are consequently smoothed with Gaussian blur and downscaled.

    Args:
        n_levels: number of the levels in octave.
        init_sigma: initial blur level.
        min_size: the minimum size of the octave in pixels.
        double_image: add 2x upscaled image as 1st level of pyramid. OpenCV SIFT does this.

    Returns:
        1st output: images
        2nd output: sigmas (coefficients for scale conversion)
        3rd output: pixelDists (coefficients for coordinate conversion)

    Shape:
        - Input: :math:`(B, C, H, W)`
        - Output 1st: :math:`[(B, C, NL, H, W), (B, C, NL, H/2, W/2), ...]`
        - Output 2nd: :math:`[(B, NL), (B, NL), (B, NL), ...]`
        - Output 3rd: :math:`[(B, NL), (B, NL), (B, NL), ...]`

    Examples:
        >>> input = torch.rand(2, 4, 100, 100)
        >>> sp, sigmas, pds = ScalePyramid(3, 15)(input)
       皙?   F)n_levels
init_sigmamin_sizedouble_imagec                    sN   t    || _d| _|| _|| _|d d | _ddt| j  | _|| _	d S )Nr/         r   )
r   r   r2   extra_levelsr3   r4   borderr,   
sigma_stepr5   )r   r2   r3   r4   r5   r    r   r   r   x   s    
zScalePyramid.__init__r   c                 C   s   | j jd t| j d d t| j d d t| j d d t| j d d t| j d d t| j d d t| j	 d	 S )
Nz
(n_levels=z, zinit_sigma=z	min_size=zextra_levels=zborder=zsigma_step=zdouble_image=))
r!   r&   r*   r2   r3   r4   r8   r9   r:   r5   )r   r   r   r   __repr__   sX    	
zScalePyramid.__repr__)sigmac                 C   s(   t d| d }|d dkr$|d7 }|S )Ng       @r   r6   r   r7   )int)r   r=   ksizer   r   r   get_kernel_size   s    zScalePyramid.get_kernel_sizec                 C   s   d}d}| j r.tj|dddd}d}|d9 }n|}| j|krtt| jd |d  d}| |}t|||f||f}| j}n|}|||fS )	Nr   g      ?r   bilinearF)Zscale_factormoder   r6   g{Gz?)	r5   Finterpolater3   maxmathsqrtr@   r   )r   r#   pixel_distance	cur_sigmaxr=   r?   	cur_levelr   r   r   get_first_level   s    


zScalePyramid.get_first_level)rJ   r   c                 C   sH  |  \}}}}| |\}}}|t|| j| j |j|j g}|t|| j| j |j|j g}|gg}	d}
|	d d }t	d| j| j D ]}|t
| jd d  }| |}t|t| d| d}|d dkr|d7 }t|||f||f}|| j9 }|	d | ||d d d |f< ||d d d |f< q|	d | j  }tj|| dd | dd fdd	}|d
9 }| j}t| d| d| jkrq|	|g ||t|| j| j |j  ||t|| j| j |j  |
d7 }
qt	t|	D ]}tj|	| dd|	|< q |	||fS )Nr   r7   r6   r   r/   Znearest)sizerB   r   )Zdim)rO   rL   r   Zonesr2   r8   toZdeviceZdtyperangerF   rG   r:   r@   minr   appendrC   rD   r3   r4   lenstack)r   rJ   bs_rK   rI   rH   ZsigmasZpixel_distsZpyrZoct_idxZ	level_idxr=   r?   Z_pyrZnextOctaveFirstLevelir   r   r   r%      sB    **

&&
zScalePyramid.forward)r/   r0   r1   F)r&   r'   r(   r)   r>   r,   r+   r   r*   r<   r@   rL   r   r-   r   r   r%   r.   r   r   r    r   r   ]   s   r   r   Fr   )r#   r   r   r   r   c           
      C   sp   t | jdkstd| j t }| j\}}}}t| ||}tj|tt|| tt|| fd|d}	|	S )a  Blur a tensor and downsamples it.

    .. image:: _static/img/pyrdown.png

    Args:
        input: the tensor to be downsampled.
        border_type: the padding mode to be applied before convolving.
          The expected modes are: ``'constant'``, ``'reflect'``,
          ``'replicate'`` or ``'circular'``.
        align_corners: interpolation flag.
        factor: the downsampling factor

    Return:
        the downsampled tensor.

    Examples:
        >>> input = torch.arange(16, dtype=torch.float32).reshape(1, 1, 4, 4)
        >>> pyrdown(input, align_corners=True)
        tensor([[[[ 3.7500,  5.2500],
                  [ 9.7500, 11.2500]]]])
       -Invalid input shape, we expect BxCxHxW. Got: rA   rO   rB   r   )	rT   shape
ValueErrorr   r   rC   rD   r>   r,   )
r#   r   r   r   kernelrW   heightwidthx_bluroutr   r   r   r	      s    r	   )r#   r   r   r   c           	      C   s`   t | jdkstd| j t }| j\}}}}tj| |d |d fd|d}t|||}|S )a  Upsample a tensor and then blurs it.

    .. image:: _static/img/pyrup.png

    Args:
        input: the tensor to be downsampled.
        border_type: the padding mode to be applied before convolving.
          The expected modes are: ``'constant'``, ``'reflect'``, ``'replicate'`` or ``'circular'``.
        align_corners: interpolation flag.

    Return:
        the downsampled tensor.

    Examples:
        >>> input = torch.arange(4, dtype=torch.float32).reshape(1, 1, 2, 2)
        >>> pyrup(input, align_corners=True)
        tensor([[[[0.7500, 0.8750, 1.1250, 1.2500],
                  [1.0000, 1.1250, 1.3750, 1.5000],
                  [1.5000, 1.6250, 1.8750, 2.0000],
                  [1.7500, 1.8750, 2.1250, 2.2500]]]])
    rY   rZ   r6   rA   r[   )rT   r\   r]   r   rC   rD   r   )	r#   r   r   r^   rW   r_   r`   Zx_upra   r   r   r   r
     s    r
   )r#   	max_levelr   r   r   c                 C   s   t | tjstdt|  t| jdks<td| j t |trN|dk r\td| g }|	|  t
|d D ]"}|d }t|||}|	| qv|S )a  Construct the Gaussian pyramid for an image.

    .. image:: _static/img/build_pyramid.png

    The function constructs a vector of images and builds the Gaussian pyramid
    by recursively applying pyrDown to the previously built pyramid layers.

    Args:
        input : the tensor to be used to construct the pyramid.
        max_level: 0-based index of the last (the smallest) pyramid layer.
          It must be non-negative.
        border_type: the padding mode to be applied before convolving.
          The expected modes are: ``'constant'``, ``'reflect'``,
          ``'replicate'`` or ``'circular'``.
        align_corners: interpolation flag.

    Shape:
        - Input: :math:`(B, C, H, W)`
        - Output :math:`[(B, C, H, W), (B, C, H/2, W/2), ...]`
    z&Input type is not a torch.Tensor. Got rY   rZ   r   z7Invalid max_level, it must be a positive integer. Got: r7   rM   )
isinstancer   r-   	TypeErrortyperT   r\   r]   r>   rS   rQ   r	   )r#   rc   r   r   ZpyramidrW   Zimg_currZimg_downr   r   r   r   5  s    
r   )r   Fr   )r   F)r   F)rF   typingr   r   r   Ztorch.nnnnZtorch.nn.functionalZ
functionalrC   Zkornia.filtersr   r   __all__r-   r   Moduler   r   r   r*   r+   r,   r	   r
   r>   r   r   r   r   r   <module>   s,      
*& 
