a
    d5                  	   @   s  d dl mZmZmZmZ d dlZd dlmZ d dlm  m	Z
 d dlmZ eeeef eeeeef f Zeeeeef f eeeeef f eeeeef dddZG dd dejZG d	d
 d
ejZdejeeeeef f eeeeef f eeeeef f eeef ejdddZejeedf eedf ejdddZdejeeeeef f eeeeef f eeef ejdddZdS )    )OptionalTupleUnioncastN)_pair)original_sizewindow_sizereturnc                 C   s~   t tttf t| } t tttf t|}tttttf ddd}|| d |d \}}|| d |d \}}||||fS )a  Compute required padding to ensure chaining of :func:`extract_tensor_patches` and
    :func:`combine_tensor_patches` produces expected result.

    Args:
        original_size: the size of the original tensor.
        window_size: the size of the sliding window used while extracting patches.

    Return:
        The required padding for `(top, bottom, left, right)` as a tuple of 4 ints.

    Example:
        >>> image = torch.arange(12).view(1, 1, 4, 3)
        >>> padding = compute_padding((4,3), (3,3))
        >>> out = extract_tensor_patches(image, window_size=(3, 3), stride=(3, 3), padding=padding)
        >>> combine_tensor_patches(out, original_size=(4, 3), window_size=(3, 3), stride=(3, 3), unpadding=padding)
        tensor([[[[ 0,  1,  2],
                  [ 3,  4,  5],
                  [ 6,  7,  8],
                  [ 9, 10, 11]]]])

    .. note::
        This function is supposed to be used in conjunction with :func:`extract_tensor_patches`
        and :func:`combine_tensor_patches`.
    )dim1dim2r	   c                 S   sL   | | dkrd}d}n.|| |  }|d dkr<|d  }}n|}d}||fS )Nr       )r
   r   p1p2tmpr   r   g/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/contrib/extract_patches.pypaddim)   s    zcompute_padding.<locals>.paddimr      )r   r   intr   )r   r   r   ZpadtZpadbZpadlZpadrr   r   r   compute_padding   s    r   c                       sr   e Zd ZdZdeeeeef f eeeeeef f  eeeef  dd fddZ	e
je
jdd	d
Z  ZS )ExtractTensorPatchesa  Module that extract patches from tensors and stack them.

    In the simplest case, the output value of the operator with input size
    :math:`(B, C, H, W)` is :math:`(B, N, C, H_{out}, W_{out})`.

    where
      - :math:`B` is the batch size.
      - :math:`N` denotes the total number of extracted patches stacked in
      - :math:`C` denotes the number of input channels.
      - :math:`H`, :math:`W` the input height and width of the input in pixels.
      - :math:`H_{out}`, :math:`W_{out}` denote to denote to the patch size
        defined in the function signature.
        left-right and top-bottom order.

    * :attr:`window_size` is the size of the sliding window and controls the
      shape of the output tensor and defines the shape of the output patch.
    * :attr:`stride` controls the stride to apply to the sliding window and
      regulates the overlapping between the extracted patches.
    * :attr:`padding` controls the amount of implicit zeros-paddings on both
      sizes at each dimension.

    The parameters :attr:`window_size`, :attr:`stride` and :attr:`padding` can
    be either:

        - a single ``int`` -- in which case the same value is used for the
          height and width dimension.
        - a ``tuple`` of two ints -- in which case, the first `int` is used for
          the height dimension, and the second `int` for the width dimension.

    :attr:`padding` can also be a ``tuple`` of four ints -- in which case, the
    first two ints are for the height dimension while the last two ints are for
    the width dimension.

    Args:
        window_size: the size of the sliding window and the output patch size.
        stride: stride of the sliding window.
        padding: Zero-padding added to both side of the input.

    Shape:
        - Input: :math:`(B, C, H, W)`
        - Output: :math:`(B, N, C, H_{out}, W_{out})`

    Returns:
        the tensor with the extracted patches.

    Examples:
        >>> input = torch.arange(9.).view(1, 1, 3, 3)
        >>> patches = extract_tensor_patches(input, (2, 3))
        >>> input
        tensor([[[[0., 1., 2.],
                  [3., 4., 5.],
                  [6., 7., 8.]]]])
        >>> patches[:, -1]
        tensor([[[[3., 4., 5.],
                  [6., 7., 8.]]]])
    r   r   N)r   stridepaddingr	   c                    s,   t    t|| _t|| _t|| _d S N)super__init__r   r   r   r   )selfr   r   r   	__class__r   r   r   v   s    


zExtractTensorPatches.__init__inputr	   c                 C   s   t || j| j| jdS )N)r   r   )extract_tensor_patchesr   r   r   r   r    r   r   r   forward   s    zExtractTensorPatches.forward)r   r   )__name__
__module____qualname____doc__r   r   r   r   PadTyper   torchTensorr#   __classcell__r   r   r   r   r   <   s   <  r   c                       sj   e Zd ZdZd
eeeeef f eeeeef f eeef dd fddZe	j
e	j
ddd	Z  ZS )CombineTensorPatchesag	  Module that combine patches from tensors.

    In the simplest case, the output value of the operator with input size
    :math:`(B, N, C, H_{out}, W_{out})` is :math:`(B, C, H, W)`.

    where
      - :math:`B` is the batch size.
      - :math:`N` denotes the total number of extracted patches stacked in
      - :math:`C` denotes the number of input channels.
      - :math:`H`, :math:`W` the input height and width of the input in pixels.
      - :math:`H_{out}`, :math:`W_{out}` denote to denote to the patch size
        defined in the function signature.
        left-right and top-bottom order.

    * :attr:`original_size` is the size of the original image prior to
      extracting tensor patches and defines the shape of the output patch.
    * :attr:`window_size` is the size of the sliding window used while
      extracting tensor patches.
    * :attr:`unpadding` is the amount of padding to be removed. This value
      must be the same as padding used while extracting tensor patches.

    The parameters :attr:`original_size`, :attr:`window_size`, and :attr:`unpadding` can
    be either:

        - a single ``int`` -- in which case the same value is used for the
          height and width dimension.
        - a ``tuple`` of two ints -- in which case, the first `int` is used for
          the height dimension, and the second `int` for the width dimension.

    :attr:`unpadding` can also be a ``tuple`` of four ints -- in which case, the
    first two ints are for the height dimension while the last two ints are for
    the width dimension.

    Args:
        patches: patched tensor.
        original_size: the size of the original tensor and the output patch size.
        window_size: the size of the sliding window used.
        unpadding: remove the padding added to both side of the input.

    Shape:
        - Input: :math:`(B, N, C, H_{out}, W_{out})`
        - Output: :math:`(B, C, H, W)`

    Example:
        >>> out = extract_tensor_patches(torch.arange(16).view(1, 1, 4, 4), window_size=(2, 2), stride=(2, 2))
        >>> combine_tensor_patches(out, original_size=(4, 4), window_size=(2, 2), stride=(2, 2))
        tensor([[[[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7],
                  [ 8,  9, 10, 11],
                  [12, 13, 14, 15]]]])

    .. note::
        This function is supposed to be used in conjunction with :class:`ExtractTensorPatches`.
    r   N)r   r   	unpaddingr	   c                    s,   t    t|| _t|| _t|| _d S r   )r   r   r   r   r   r-   )r   r   r   r-   r   r   r   r      s    


zCombineTensorPatches.__init__r   c                 C   s   t || j| j| j| jdS )N)r   r-   )combine_tensor_patchesr   r   r-   r"   r   r   r   r#      s    zCombineTensorPatches.forward)r   )r$   r%   r&   r'   r   r   r   r(   r   r)   r*   r#   r+   r   r   r   r   r,      s   ; 
r,   )patchesr   r   r   r-   r	   c                 C   sT  t | jdkrtd| j ttttf t|}ttttf t|}ttttf t|}|d |d ks|d |d krtd| d| d|rttt|}t |dvrt	d	t |d
krt|d }t|d }n|dd
 }|d
d }ttttttf || }|d |d
  |d  |d  dk}|d |d  |d  |d  dk}|rj|srtd|d |d
 |d   |d  |d |d |d   |d  f}| j
d|d |d g| jdd R  }	ttj|	|d dddd}
ttj|
|d dddd}
|rPttttttf |}t|
dd |D }
|
S )a  Restore input from patches.

    See :class:`~kornia.contrib.CombineTensorPatches` for details.

    Args:
        patches: patched tensor with shape :math:`(B, N, C, H_{out}, W_{out})`.
        original_size: the size of the original tensor and the output patch size.
        window_size: the size of the sliding window used while extracting patches.
        stride: stride of the sliding window.
        unpadding: remove the padding added to both side of the input.

    Return:
        The combined patches in an image tensor with shape :math:`(B, C, H, W)`.

    Example:
        >>> out = extract_tensor_patches(torch.arange(16).view(1, 1, 4, 4), window_size=(2, 2), stride=(2, 2))
        >>> combine_tensor_patches(out, original_size=(4, 4), window_size=(2, 2), stride=(2, 2))
        tensor([[[[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7],
                  [ 8,  9, 10, 11],
                  [12, 13, 14, 15]]]])

    .. note::
        This function is supposed to be used in conjunction with :func:`extract_tensor_patches`.
       z/Invalid input shape, we expect BxNxCxHxW. Got: r   r   z-Only stride == window_size is supported. Got z and z0.Please feel free to drop a PR to Kornia Github.r      zHUnpadding must be either an int, tuple of two ints or tuple of four intsr   N   zInsufficient padding)dimc                 S   s   g | ]
}| qS r   r   ).0ir   r   r   
<listcomp>      z*combine_tensor_patches.<locals>.<listcomp>)lenshape
ValueErrorr   r   r   r   NotImplementedErrorr(   AssertionErrorviewr)   catchunkZsqueezeFpad)r/   r   r   r   r-   pad_vertpad_horzZ
hpad_checkZ
wpad_checkZpatches_tensorZrestored_tensorr   r   r   r.      sB    ! $$(""r.   .)r    window_sizesstridesr	   c                    s   |   d d \}}td|   t ||D ]\}}}| |||} q.| jdg d fdd D R   } | j|d|g|R  S )Nr   r   r   c                 3   s   | ]}|t   V  qd S r   )r<   )r8   r6   dimsr   r   	<genexpr>&  r;   z,_extract_tensor_patchesnd.<locals>.<genexpr>r4   )sizeranger6   zipZunfoldZpermute
contiguousrA   )r    rH   rI   Z
batch_sizeZnum_channelsr6   Z
patch_sizer   r   rJ   r   _extract_tensor_patchesnd  s    ,rQ   r   )r    r   r   r   r	   c                 C   s   t | stdt|  t| jdkr:td| j |rttt	|}t|dvr`t
dt|dkrt	|d }t	|d }n|d	d }|dd	 }ttttttf || }t| |} t| t	|t	|S )
ad  Function that extract patches from tensors and stack them.

    See :class:`~kornia.contrib.ExtractTensorPatches` for details.

    Args:
        input: tensor image where to extract the patches with shape :math:`(B, C, H, W)`.
        window_size: the size of the sliding window and the output patch size.
        stride: stride of the sliding window.
        padding: Zero-padding added to both side of the input.

    Returns:
        the tensor with the extracted patches with shape :math:`(B, N, C, H_{out}, W_{out})`.

    Examples:
        >>> input = torch.arange(9.).view(1, 1, 3, 3)
        >>> patches = extract_tensor_patches(input, (2, 3))
        >>> input
        tensor([[[[0., 1., 2.],
                  [3., 4., 5.],
                  [6., 7., 8.]]]])
        >>> patches[:, -1]
        tensor([[[[3., 4., 5.],
                  [6., 7., 8.]]]])
    z,Input input type is not a torch.Tensor. Got r2   z-Invalid input shape, we expect BxCxHxW. Got: r1   zFPadding must be either an int, tuple of two ints or tuple of four intsr   r   r   N)r)   Z	is_tensor	TypeErrortyper<   r=   r>   r   r(   r   r@   r   r   rD   rE   rQ   )r    r   r   r   rF   rG   r   r   r   r!   *  s     
r!   )r   )r   r   )typingr   r   r   r   r)   Ztorch.nnnnZtorch.nn.functionalZ
functionalrD   Ztorch.nn.modules.utilsr   r   r(   r   Moduler   r,   r*   r.   rQ   r!   r   r   r   r   <module>   s>    $1IN 
R  
