
    3j^U                        S SK Jr  S SKJrJrJrJr  S SKJr  S SK	r	S SK
Js  Jr  S SK	Jr  S SKJr  \\\\\4   r\\\\4   \4   r\\\4   rSS\S\S	\4S
 jjr S S\\\\\4   4   S\\\\\4   4   S\\\\\\4   4      S	\4S jjr " S S\R.                  5      r " S S\R.                  5      rS\\\4   S\\\4   S\\\4   S	\4S jr   S!S\	R6                  S\\\\\4   4   S\\\\\4   4   S\\\\\4   4   S\S\S\S	\	R6                  4S jjrS\	R6                  S\\S4   S\\S4   S	\	R6                  4S jr   S"S\	R6                  S\\\\\4   4   S\\\\\4   4   S\S\S	\	R6                  4S jjrg)#    )ceil)OptionalTupleUnioncast)warnN)nn)_pairpadding	unpaddingreturnc                    [        [        [        U 5      5      n [        U 5      S;  a  [	        U(       a  SOS S35      e[        U 5      S:X  a  [        U S   5      n[        U S   5      nO
U SS nU SS n[        [
        X2-   5      n U $ )	zCreate argument for padding op.)      	UnpaddingPaddingz? must be either an int, tuple of two ints or tuple of four intsr   r      N)r   TuplePadTyper
   lenAssertionErrorFullPadType)r   r   pad_vertpad_horzs       X/home/wildlama/miniconda3/lib/python3.13/site-packages/kornia/contrib/extract_patches.pycreate_padding_tupler       s    <w0G
7|6!'{Y77vw
 	
 7|q$$2A;12;; 34GN    original_sizewindow_sizestridec                 \   [        [        [        [        4   [        U 5      5      n [        [        [        [        4   [        U5      5      nUc  Un[        [        [        [        4   [        U5      5      nU S   US   -
  US   -  nU S   US   -
  US   -  nUS:w  a	  US   U-
  nOSnUS:w  a	  US   U-
  nOSnUS-  S:X  a  US-  =pxOUS-  n[	        US-  5      nUS-  S:X  a  US-  =pOUS-  n	[	        US-  5      n
[        U5      [        U5      [        U	5      [        U
5      4nU$ )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 torch.Tensor.
    window_size: the size of the sliding window used while extracting patches.
    stride: The stride of the sliding window. Optional: if not specified, window_size will be used.

Return:
    The required padding as a tuple of four ints: (top, bottom, left, right)

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 will be implicitly used in :func:`extract_tensor_patches` and :func:`combine_tensor_patches` if
    `allow_auto_(un)padding` is set to True.

r   r   r   )r   r   intr
   r   )r   r   r   remainder_verticalremainder_horizontalvertical_paddinghorizontal_paddingtop_paddingbottom_paddingleft_paddingright_paddingr   s               r   compute_paddingr*   4   sc   > sCx%*>?MuS#Xk(:;K~%S/5=1F'*[^;vayH)!,{1~=J Q!!9'99q #AY)==!q '71'<<n&!+.23A"'9Q'>>})Q./!34+N 3S5FMHZZGNr   c                      ^  \ rS rSrSr   SS\\\\\4   4   S\\\\\4   4   S\S\	SS4
U 4S	 jjjr
S
\R                  S\R                  4S jrSrU =r$ )ExtractTensorPatchesx   a	  nn.Module that extract patches from tensors and torch.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 torch.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 torch.zeros-paddings on both
  sizes at each dimension.
* :attr:`allow_auto_padding` allows automatic calculation of the padding required
  to fit the window and stride into the image.

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:
    input: torch.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.
    allow_auto_adding: whether to allow automatic padding if the window and stride do not fit into the image.

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

Returns:
    the torch.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   r   allow_auto_paddingr   Nc                 R   > [         TU ]  5         Xl        X l        X0l        X@l        g N)super__init__r   r   r   r.   )selfr   r   r   r.   	__class__s        r   r2   ExtractTensorPatches.__init__   s&     	8C39 '(:r   inputc                 l    [        UU R                  U R                  U R                  U R                  S9$ )a  Extract sliding-window patches from a batched image tensor.

Args:
    input: Input tensor with shape :math:`(B, C, H, W)`, where:
        - ``B`` is the batch size (number of images),
        - ``C`` is the number of channels,
        - ``H`` is height,
        - ``W`` is width.

Returns:
    A tensor containing stacked patches with shape
    :math:`(B, N, C, H_{out}, W_{out})`, where:
    - ``N`` is the number of extracted windows per image,
    - ``H_{out}`` and ``W_{out}`` are patch height and patch width.
)r   r   r.   )extract_tensor_patchesr   r   r   r.   r3   r6   s     r   forwardExtractTensorPatches.forward   s4      &;;LL#66
 	
r   )r.   r   r   r   r   r   F)__name__
__module____qualname____firstlineno____doc__r   r!   r   PadTypeboolr2   torchTensorr:   __static_attributes____classcell__r4   s   @r   r,   r,   x   s    <B /0#(;3c3h/0; c5c?*+; 	;
 !; 
; ;
U\\ 
ell 
 
r   r,   c                      ^  \ rS rSrSr   SS\\\4   S\\\\\4   4   S\\\\\\4   4      S\	S\
S	S4U 4S
 jjjrS\R                  S	\R                  4S jrSrU =r$ )CombineTensorPatches   a  nn.Module that combines patches back into full 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 torch.Tensor patches and defines the shape of the output patch.
* :attr:`window_size` is the size of the sliding window used while
  extracting torch.Tensor patches.
* :attr:`stride` controls the stride to apply to the sliding window and
  regulates the overlapping between the extracted patches.
* :attr:`unpadding` is the amount of padding to be removed. If specified,
  this value must be the same as padding used while extracting torch.Tensor patches.
* :attr:`allow_auto_unpadding` allows automatic calculation of the padding required
  to fit the window and stride into the image. This must be used if the
  `allow_auto_padding` flag was used for extracting the patches.


The parameters :attr:`original_size`, :attr:`window_size`, :attr:`stride`, 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 torch.Tensor with shape :math:`(B, N, C, H_{out}, W_{out})`.
    original_size: the size of the original torch.Tensor and the output 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.
    allow_auto_unpadding: whether to allow automatic unpadding of the input
        if the window and stride do not fit into the original_size.
    eps: small value used to prevent division by zero.

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`.

Nr   r   r   r   allow_auto_unpaddingr   c                 j   > [         TU ]  5         Xl        X l        Ub  UOUU l        X@l        XPl        g r0   )r1   r2   r   r   r   r   rL   )r3   r   r   r   r   rL   r4   s         r   r2   CombineTensorPatches.__init__!  s6     	.;8C=C=O6U`"+*>!r   r6   c           	          [        UU R                  U R                  U R                  U R                  U R
                  S9$ )a  Reconstruct full images from extracted patches.

Args:
    input: Patch tensor with shape :math:`(B, N, C, H_{out}, W_{out})`, where:
        - ``B`` is the batch size,
        - ``N`` is the number of patches,
        - ``C`` is the number of channels,
        - ``H_{out}`` and ``W_{out}`` are patch height and width.

Returns:
    A reconstructed tensor with shape :math:`(B, C, H, W)`, where ``H``
    and ``W`` correspond to ``original_size`` after optional unpadding.
)r   r   rL   )combine_tensor_patchesr   r   r   r   rL   r9   s     r   r:   CombineTensorPatches.forward0  s=     &;;nn!%!:!:
 	
r   )rL   r   r   r   r   )Nr   F)r=   r>   r?   r@   rA   r   r!   r   r   rB   rC   r2   rD   rE   r:   rF   rG   rH   s   @r   rJ   rJ      s    AN 9=%*?S#X? 3c3h/0? sE#s(O345	?
 ? #? 
? ?
U\\ 
ell 
 
r   rJ   c                 b    U S   US   -
  US   -  nU S   US   -
  US   -  nUS:w  d  US:w  a  gg)Nr   r   FT )r   r   r   r"   r#   s        r   _check_patch_fitrT   H  sT    '*[^;vayH)!,{1~=J 	!'9Q'>r   patchesrL   epsc           	         U R                   S:w  a  [        SU R                   35      e[        [        [
        [
        4   [        U5      5      n[        [        [
        [
        4   [        U5      5      n[        [        [
        [
        4   [        U5      5      nUS   US   :  US   US   :  -  (       a  [        SU SU S35      eU(       d7  [        XU5      (       d&  U(       d  [        SU S	U S
U S3SS9  O
[        XUS9nU(       a  [        U5      n[        R                  " U R                  S   U R                  S   US   US   U R                  U R                  S9nU(       a  [         R"                  " XuS9nUR                  SS nU R%                  SSSSS5      n U R'                  U R                  S   SU R                  S   5      n Sn	[        R(                  " U 5      (       d.  Sn	U R                  n
U R+                  5       n UR+                  5       n[         R,                  " XrUS9n[         R.                  " XX#S9nU(       a'  [         R"                  " X Vs/ s H  o* PM     sn5      n[         R.                  " XX#S9nU(       a'  [         R"                  " X Vs/ s H  o* PM     sn5      nXU-   -  nU	(       a  UR1                  W
5      nU$ s  snf s  snf )a  Restore input from patches.

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

Args:
    patches: patched torch.Tensor with shape :math:`(B, N, C, H_{out}, W_{out})`.
    original_size: the size of the original torch.Tensor and the output 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.
    allow_auto_unpadding: whether to allow automatic unpadding of the input
        if the window and stride do not fit into the original_size.
    eps: small value used to prevent division by zero.

Return:
    The combined patches in an image torch.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Stride=z- should be less than or equal to Window size=z, information is missing6The window will not fit into the image. 
Window size: 	
Stride: 
Image size: aH  
This means we probably cannot correctly recombine patches. By enabling `allow_auto_unpadding`, the input will be unpadded to fit the window and stride.
If the patches have been obtained through `extract_tensor_patches` with the correct padding or the argument `allow_auto_padding`, this will result in a correct reconstruction.
stacklevelr   r   r   r   )devicedtype)padN   r   )kernel_sizer   )r6   output_sizerd   r   )ndim
ValueErrorshaper   r   r!   r
   r   rT   r   r*   r   rD   onesr_   r`   Fra   permutereshapeis_floating_pointfloatunfoldfoldto)rU   r   r   r   rL   r   rV   ones_tensorrestored_sizeint_flagr`   unfold_onesnorm_mapisaturated_restored_tensorrestored_tensors                   r   rP   rP   U  s   L ||qJ7==/Z[[sCx%*>?MuS#Xk(:;K%S/5=1Fq	KN"vay;q>'ABfXJ;-Wop
 	
   FCC'Mk]Zdekdl m##0/ 2gg  ! ,-iop	 (3	**aaaa~~mmK eeK7%%ab)MooaAq!,GoogmmA.GMM"4EFGH""7++--/!'') ((;OKvvKP[kH55	#:	1B	#:; !"W]h x$%EE*CR[E\R[QbR[E\$]! 0c>BO),,U3 $;
 F]s   "K
%K
r6   window_sizes.stridesc                 :  ^ U R                  5       S S u  p4[        SU R                  5       5      m[        TX5       H  u  pVnU R	                  XVU5      n M     U R
                  " S/TQSPU4S jT 5       Q76 R                  5       n U R                  " USU/UQ76 $ )Nr   r   r   c              3   >   >#    U  H  o[        T5      -   v   M     g 7fr0   )r   ).0dimdimss     r   	<genexpr>,_extract_tensor_patchesnd.<locals>.<genexpr>  s     (IDSs4yDs   rc   )sizeranger   zipro   rk   
contiguousview)	r6   rz   r{   
batch_sizenum_channelsr   
patch_sizer   r   s	           @r   _extract_tensor_patchesndr     s      %zz|BQ/JEIIK D#&t\#CSf5 $DMM!JdJAJ(ID(IJUUWE::j"lB\BBr   r.   c           	         [         R                  " U 5      (       d  [        S[        U 5       35      e[	        U R
                  5      S:w  a  [        SU R
                   35      e[        [        [        [        4   [        U5      5      n[        [        [        [        4   [        U5      5      nU R
                  S   U R
                  S   4nU(       d7  [        XQU5      (       d&  U(       d  [        SU SU SU S	3S
S9  O
[        XQUS9nU(       a!  [        U5      n[        R                   " X5      n [#        XU5      $ )a  Extract patches from tensors and stacks them.

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

Args:
    input: torch.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.
    allow_auto_padding: whether to allow automatic padding if the window and stride do not fit into the image.

Returns:
    the torch.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 r   z-Invalid input shape, we expect BxCxHxW. Got: rc   rY   rZ   r[   z
This means that the final incomplete patches will be dropped. By enabling `allow_auto_padding`, the input will be padded to fit the window and stride.r   r\   r^   )rD   	is_tensor	TypeErrortyper   rh   rg   r   r   r!   r
   rT   r   r*   r   rj   ra   r   )r6   r   r   r   r.   r   s         r   r8   r8     s    B ??5!!FtE{mTUU
5;;1HVWW uS#Xk(:;K%S/5=1F[[_ekk"o6M  FCC%Mk]Zdekdl m##0/ 2MM  ! *gmn&w/e%$U@@r   )Fr0   )Fr   g:0yE>r<   ) mathr   typingr   r   r   r   warningsr   rD   torch.nn.functionalr	   
functionalrj   torch.nn.modules.utilsr
   r!   r   r   rB   rC   r   r*   Moduler,   rJ   rT   rE   rn   rP   r   r8   rS   r   r   <module>r      s  $  / /      (Cc3&'U38_k12
\!
"' d { . 59AeCHo-.AsE#s(O+,A U3c3h/01A 	AHb
299 b
Jh
299 h
V
E#s(O 
%S/ 
[`adfiai[j 
os 
$ "'l\\leCHo-.l sE#s(O+,l #uS#X&'	l
 l l 
l \\l^C<<C',S#XCAFsCxC
\\C +,$@A<<@AsE#s(O+,@A #uS#X&'@A 	@A
 @A \\@Ar   