
    3jg'                        % S SK r S SKJrJr  S SKrS SKJr  S SKJrJr  S SK	J
r
  S SKJr  SSKJrJrJrJrJrJrJr  0 r\\\4   \S	'   S
\S'    " S S\R0                  5      r " S S\R0                  5      r " S S\R0                  5      rg)    N)DictOptional)nn)KORNIA_CHECK_LAFKORNIA_CHECK_SHAPE)get_gaussian_kernel2d)SpatialGradient   )ellipse_to_lafextract_patches_from_pyramidget_laf_orientationget_laf_scalemake_upright	scale_lafset_laf_orientationurlszEhttps://github.com/ducha-aiki/affnet/raw/master/pretrained/AffNet.pthaffnetc                      ^  \ rS rSrSrSS\S\SS4U 4S jjjrS\4S jr	S	\
R                  S\
R                  4S
 jrSrU =r$ )PatchAffineShapeEstimator*   zModule, which estimates the second moment matrix of the patch gradients.

The method determines the affine shape of the local feature as in :cite:`baumberg2000`.

Args:
    patch_size: the input image patch size.
    eps: for safe division.


patch_sizeepsreturnNc                   > [         TU ]  5         Xl        [        SS5      U l        X l        [        U R                  5      [        R                  " S5      -  n[        U R                  U R                  4X34S5      U l
        g )Nsobelr
   g       @T)super__init__r   r	   gradientr   floatmathsqrtr   	weighting)selfr   r   sigma	__class__s       U/home/wildlama/miniconda3/lib/python3.13/site-packages/kornia/feature/affine_shape.pyr   "PatchAffineShapeEstimator.__init__5   sc    )#27A#>T__-		#>'<doot=_bgaoqu'v    c                 h    U R                   R                   SU R                   SU R                   S3$ )N(patch_size=z, eps=))r%   __name__r   r   r#   s    r&   __repr__"PatchAffineShapeEstimator.__repr__=   s0    ..))*,t6GvdhhZWXYYr(   patchc           	         [        U/ SQ5        U R                  R                  UR                  5      R                  UR                  5      U l        U R                  U5      U R                  -  nUSS2SS2S4   nUSS2SS2S4   n[        R                  " UR                  S5      R                  SS9R                  SSS9X4-  R                  SS9R                  SSS9UR                  S5      R                  SS9R                  SSS9/SS9nXPR                  :  R                  5       R                  SSS9S:  R                  UR                  5      n[        R                  " / S	Q5      R                  UR                  5      R                  UR                  5      R                  SSS
5      nUSU-
  -  Xv-  -   nXUR                  SSS9S   -  nU$ )zqRun forward.

Args:
    patch: :math:`(B, 1, H, W)`

Returns:
    torch.Tensor: ellipse_shape :math:`(B, 1, 3)`

B1HWNr   r
      dimTr9   keepdim)      ?g        r<      r<   )r   r"   todtypedevicer   torchcatpowmeanr   r   sumtensorviewmax)r#   r0   gradsgxgyellipse_shapebad_maskcircular_shapes           r&   forward!PatchAffineShapeEstimator.forward@   s    	5"67**5;;7::5<<H"mmE2T^^C Aq> Aq>		q	1%**q$*?1%**q$*?q	1%**q$*?
 
 #XX-446::q$:OSTTXXYfYlYlmo699-:N:NORRS`SfSfgllmnpqstu%x8>;TT%(9(9a(9(Nq(QQr(   )r   r   r   r"   )   g|=)r,   
__module____qualname____firstlineno____doc__intr   r   strr.   rA   TensorrO   __static_attributes____classcell__r%   s   @r&   r   r   *   sZ    w3 w% wD w wZ# Z!U\\ !ell ! !r(   r   c            	          ^  \ rS rSrSr SS\S\\R                     S\	SS4U 4S jjjr
S\4S	 jrS
\R                  S\R                  S\R                  4S jrSrU =r$ )LAFAffineShapeEstimatord   aW  Module, which extracts patches using input images and local affine frames (LAFs).

Then runs :class:`~kornia.feature.PatchAffineShapeEstimator` on patches to estimate LAFs shape.

Then original LAF shape is replaced with estimated one. The original LAF orientation is not preserved,
so it is recommended to first run LAFAffineShapeEstimator and then LAFOrienter,


Args:
    patch_size: the input image patch size.
    affine_shape_detector: Patch affine shape estimator, :class:`~kornia.feature.PatchAffineShapeEstimator`.
    preserve_orientation: if True, the original orientation is preserved.

Nr   affine_shape_detectorpreserve_orientationr   c                    > [         TU ]  5         Xl        U=(       d    [        U R                  5      U l        X0l        g )N)r   r   r   r   r_   r`   )r#   r   r_   r`   r%   s       r&   r    LAFAffineShapeEstimator.__init__t   s5     	$%:%h>WX\XgXg>h"$8!r(   c                     U R                   R                   SU R                   SU R                   SU R                   S3$ )Nr*   z, affine_shape_detector=z, preserve_orientation=r+   )r%   r,   r   r_   r`   r-   s    r&   r.    LAFAffineShapeEstimator.__repr__|   sN    ~~&&'4??+ ,%%)%?%?$@ A$$($=$=#>aA	
r(   lafimgc                 H   [        U5        [        U/ SQ5        UR                  SS u  p4U R                  n[	        U[        U5      US5      R                  SSXU5      nU R                  U5      n[        R                  " UR                  SSS5      S   R                  S5      U/SS	9R                  X4S
5      n[        U5      n	U R                  (       a  [        U5      n
[        U5      n[        U5      n[        XU-  5      nU R                  (       a  [!        UW
5      nU$ )}Run forward.

Args:
    laf: :math:`(B, N, 2, 3)`
    img: :math:`(B, 1, H, W)`

Returns:
    LAF_out: :math:`(B, N, 2, 3)`

r2   Nr7   Tr
   r=   ).r7   r8      )r   r   shaper   r   r   rG   r_   rA   rB   	unsqueezer   r`   r   r   r   r   )r#   re   rf   r3   NPSpatchesrL   ellipses
scale_origori_origlaf_outellipse_scales                r&   rO   LAFAffineShapeEstimator.forward   s    	3 45yy!}// <S,sBSUWY] ^ c cdfhikm r&*&@&@&I99chhr1a08BB1E}U[\]bbcdijk"3'
$$*3/H *%g.G-%?@$$)'8<Gr(   )r_   r   r`   )    NT)r,   rR   rS   rT   rU   rV   r   r   Moduleboolr   rW   r.   rA   rX   rO   rY   rZ   r[   s   @r&   r]   r]   d   sy      uy99;CBII;N9mq9	9 9
# 
5<< ell u||  r(   r]   c                      ^  \ rS rSrSrSS\S\SS4U 4S jjjr\SS\R                  S	\
S\R                  4S
 jj5       rS\R                  S\R                  S\R                  4S jrSrU =r$ )LAFAffNetShapeEstimator   a=  Module, which extracts patches using input images and local affine frames (LAFs).

Then runs AffNet on patches to estimate LAFs shape. This is based on the original code from paper
"Repeatability Is Not Enough: Learning Discriminative Affine Regions via Discriminability"".
See :cite:`AffNet2018` for more details.

Then original LAF shape is replaced with estimated one. The original LAF orientation is not preserved,
so it is recommended to first run LAFAffineShapeEstimator and then LAFOrienter.

Args:
    pretrained: Download and set pretrained weights to the model.


pretrainedr`   r   Nc                   > [         TU ]  5         [        R                  " [        R                  " SSSSSS9[        R
                  " SSS9[        R                  " 5       [        R                  " SSSSSSS9[        R
                  " SSS9[        R                  " 5       [        R                  " SSSS	SSS9[        R
                  " SSS9[        R                  " 5       [        R                  " SSSSSSS9[        R
                  " SSS9[        R                  " 5       [        R                  " SS
SS	SSS9[        R
                  " S
SS9[        R                  " 5       [        R                  " S
S
SSSSS9[        R
                  " S
SS9[        R                  " 5       [        R                  " S5      [        R                  " S
SSSSSS9[        R                  " 5       [        R                  " S5      5      U l
        SU l        U(       aL  [        R                  R                  [        S   [        R                   " S5      S9nU R#                  US   SS9  X l        U R'                  5         g )Nr
      r=   F)kernel_sizepaddingbias)affine)r   strider   r   rv   r7   @   g      ?   r   Tr   cpu)map_location
state_dict)strict)r   r   r   
SequentialConv2dBatchNorm2dReLUDropoutTanhAdaptiveAvgPool2dfeaturesr   rA   hubload_state_dict_from_urlr   r@   load_state_dictr`   eval)r#   r|   r`   pretrained_dictr%   s       r&   r    LAFAffNetShapeEstimator.__init__   s   IIaAEBNN2e,GGIIIb"!AquMNN2e,GGIIIb"!AquMNN2e,GGIIIb"!AquMNN2e,GGIIIb"!AquMNN2e,GGIIIb"!AquMNN2e,GGIJJtIIb!1adKGGI  #-
0 #ii@@h^c^j^jkp^q@rO  !>u M$8!		r(   xr   c                 ~    [         R                  " U SSS9u  p#XR                  5       -
  UR                  5       U-   -  $ )zNormalize the input by batch.)ri   Tr:   )rA   std_meandetach)r   r   spmps       r&   _normalize_input(LAFAffNetShapeEstimator._normalize_input   s8     |TB IIKBIIK#$566r(   re   rf   c           	         [        U5        [        U/ SQ5        UR                  SS u  p4U R                  n[	        U[        U5      US5      R                  SSXU5      nU R                  U R                  U5      5      R                  SS5      n[        R                  " SUSS2S	4   R                  SSS5      -   S	USS2S	4   R                  SSS5      -  /SS
9n[        R                  " USS2S4   R                  SSS5      SUSS2S4   R                  SSS5      -   /SS
9n	[        R                  " X/SS
9R                  X4SS5      n
[        R                  " XSS2SS2SS2SS24   /SS
9n[        U5      nU R                  (       a  [        U5      n[        U5      n[        [        U5      X-  5      nU R                  (       a  [!        UW5      nU$ )rh   r2   Nr7   Tri   r
   r=   r<   r   r8   )r   r   rk   r   r   r   rG   r   r   rA   rB   reshaper   r`   r   r   r   )r#   re   rf   r3   rm   rn   ro   xya1a2new_laf_no_centernew_lafrq   rr   rt   rs   s                   r&   rO   LAFAffNetShapeEstimator.forward   s    	3 45yy!}// <S,sBSUWY] ^ c cdfhikm r]]4009:??AFYYbAh..r1a88!bAh>N>NrSTVW>X:XY_`aYY1a4((Q2C"QT(:J:J2qRS:T4TU[\]!IIrhA6>>qQJ)).Aq!QqSL0ABJ"3'
$$*3/H%g.L1:3MN$$)'8<Gr(   )r   r   r`   )FT)gư>)r,   rR   rS   rT   rU   rx   r   staticmethodrA   rX   r   r   rO   rY   rZ   r[   s   @r&   rz   rz      s     4  t  W[    D 7ELL 7u 7 7 75<< ell u||  r(   rz   )r    typingr   r   rA   r   kornia.core.checkr   r   kornia.filters.kernelsr   kornia.filters.sobelr	   re   r   r   r   r   r   r   r   r   rW   __annotations__rw   r   r]   rz    r(   r&   <module>r      s|   $  !   B 8 0   d38n XX7		 7t:bii :zVbii Vr(   