
    3jG`                     r   S SK JrJrJrJrJrJr  S SKrS SKJ	s  J
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  SS	KJrJr  S
\R0                  S\R0                  S\R0                  4S jrS\\\4   4S jr S%S\R0                  S\R0                  S\\R0                     S\R0                  4S jjrS\R0                  S\\R0                  \R0                  4   4S jr S%S\R0                  S\R0                  S\\R0                     S\\R0                  \R0                  4   4S jjr S%S\R0                  S\R0                  S\\R0                     S\\R0                  \R0                  4   4S jjr S&S\R0                  S\R0                  S\ S\\R0                     S\\R0                  \R0                  4   4
S jjr! S'S\R0                  S\R0                  S\ S\\R0                     S\\R0                  \R0                  4   4
S jjr"    S(S\R0                  S\R0                  S\R0                  S\R0                  S\ S\ S\#S\\R0                     S\\R0                  \R0                  4   4S jjr$ " S S \	RJ                  5      r& " S! S"\	RJ                  5      r' " S# S$\	RJ                  5      r(g))    )AnyClassVarDictListOptionalTupleN)nn)KORNIA_CHECK_DM_DESCKORNIA_CHECK_SHAPE)is_mps_tensor_safe)get_laf_center)DiscreteSteerer   )get_adalam_default_configmatch_adalamd1d2returnc                 H   [         R                  [         R                  4n[        U 5      (       dF  [        U5      (       d6  U R                  U;  a&  UR                  U;  a  [         R
                  " X5      $ U S-  R                  SSS9nUS-  R                  SSS9nUR                  SUR                  S5      5      UR                  SU R                  S5      5      R                  5       -   SU -  UR                  5       -  -
  nUR                  SS9R                  5       nU$ )	aa  Compute pairwise L2 distances between rows of d1 and d2.

Uses ``torch.cdist`` for float32/float64 on non-MPS devices.  Falls back to a
manual expand-and-norm implementation for MPS tensors and for half-precision
dtypes (float16/bfloat16), since ``torch.cdist`` does not support half precision
on CUDA and may be unavailable for these dtypes elsewhere.
   r   T)dimkeepdimr   g       @g        )min)torchfloat16bfloat16r   dtypecdistsumrepeatsizetclampsqrt)r   r   halfd1_sqd2_sqdms         Q/home/wildlama/miniconda3/lib/python3.13/site-packages/kornia/feature/matching.py_cdistr*       s     MM5>>*Dr""-?-C-CY]I]bdbjbjrvbv{{2""UKKAtK,EUKKAtK,E	a	$u||Arwwqz'B'D'D'F	FrTVTXTXTZIZ	ZB	c				!BI    c                      SSSS.n U $ )Ng333333?F      $@)thmutual
spatial_th configs    r)   _get_default_fginn_paramsr4   2   s    E>FMr+   desc1desc2dm_c                 B    Uc  [        X5      nU$ [        XU5        UnU$ )ao  Check validity of provided distance matrix, or calculates L2-distance matrix if dm is not provided.

Args:
    desc1: Batch of descriptors of a shape :math:`(B1, D)`.
    desc2: Batch of descriptors of a shape :math:`(B2, D)`.
    dm_: torch.Tensor containing the distances from each descriptor in desc1
      to each descriptor in desc2, shape of :math:`(B1, B2)`.

)r*   r
   )r5   r6   r7   r(   s       r)   _get_lazy_distance_matrixr9   7   s0     {E! I 	U3/Ir+   r(   c                     [         R                  " SSU R                  U R                  S9n[         R                  " SSU R                  [         R                  S9nX4$ )zOutput empty tensors.

Returns:
        - Descriptor distance of matching descriptors, shape of :math:`(0, 1)`.
        - Long torch.Tensor indexes of matching descriptors in desc1 and desc2, shape of :math:`(0, 2)`.

r   r   )devicer   r   )r   emptyr;   r   long)r(   distsidxss      r)   	_no_matchr@   K   sD     KK1RYYbhh?E;;q!BIIUZZ@D;r+   c                    [        U SS/5        [        USS/5        [        U 5      S:X  d  [        U5      S:X  a  [        U 5      $ [        XU5      n[        R
                  " USS9u  pE[        R                  " SUR                  S5      UR                  S9n[        R                  " UR                  SS5      UR                  SS5      /S5      nUR                  SS5      UR                  SS5      4$ )	aM  Find nearest neighbors in desc2 for each vector in desc1.

If the distance matrix dm is not provided, :py:func:`torch.cdist` is used.

Args:
    desc1: Batch of descriptors of a shape :math:`(B1, D)`.
    desc2: Batch of descriptors of a shape :math:`(B2, D)`.
    dm: torch.Tensor containing the distances from each descriptor in desc1
      to each descriptor in desc2, shape of :math:`(B1, B2)`.

Returns:
    - Descriptor distance of matching descriptors, shape of :math:`(B1, 1)`.
    - Long torch.Tensor indexes of matching descriptors in desc1 and desc2, shape of :math:`(B1, 2)`.

BDIMr   r   r   r;   r   )r   lenr@   r9   r   r   aranger!   r;   catview)r5   r6   r(   distance_matrixmatch_dists	idxs_in_2idxs_in1matches_idxss           r)   match_nnrP   X   s    $ usEl+usEl+E
aSZ1_/bAO"YYA>K||Ay~~a09I9IJH99hmmB2INN2q4IJANLB"L$5$5b!$<<<r+   c                 J   [        U SS/5        [        USS/5        [        U 5      S:X  d  [        U5      S:X  a  [        U 5      $ [        XU5      n[	        UR                  S5      UR                  S5      5      n[        R                  " USS9u  pV[        R                  " USS9u  px[        R                  " XCR                  S9n	UR                  S5      UR                  S5      ::  aK  XU   SU :H  n
[        R                  " U	R                  SS5      UR                  SS5      /S5      U
   nXZ   nOJXU   SU :H  n
[        R                  " UR                  SS5      U	R                  SS5      /S5      U
   nXz   nUR                  SS5      UR                  SS	5      4$ )
aw  Find mutual nearest neighbors in desc2 for each vector in desc1.

If the distance matrix dm is not provided, :py:func:`torch.cdist` is used.

Args:
    desc1: Batch of descriptors of a shape :math:`(B1, D)`.
    desc2: Batch of descriptors of a shape :math:`(B2, D)`.
    dm: torch.Tensor containing the distances from each descriptor in desc1
      to each descriptor in desc2, shape of :math:`(B1, B2)`.

Return:
    - Descriptor distance of matching descriptors, shape of. :math:`(B3, 1)`.
    - Long torch.Tensor indexes of matching descriptors in desc1 and desc2, shape of :math:`(B3, 2)`,
      where 0 <= B3 <= min(B1, B2)

rB   rC   r   r   rD   rE   NrF   r   )r   rG   r@   r9   r   r!   r   rH   r;   rI   rJ   )r5   r6   r(   rK   msrL   rM   match_dists2	idxs_in_1minsize_idxs
mutual_nnsrO   s               r)   	match_mnnrW   u   s   & usEl+usEl+E
aSZ1_/bAO	_!!!$o&:&:1&=	>B"YYA>K#iiQ?L<<+A+ABLA/"6"6q"99!y%9#2%>>
yy,"3"3B":INN2q<Q!RTUVWab!-!y%9#2%>>
yy)..Q"79J9J2q9Q!RTUVWab".B"L$5$5b!$<<<r+   r.   c                    [        U SS/5        [        USS/5        U R                  S   S:X  d  UR                  S   S:  a  [        U 5      $ [        XU5      n[        R
                  " USSSS9u  pVUSS2S4   USS2S4   -  nXr:*  nXx   n	[        U	5      S:X  a  [        U5      $ [        R                  " SUR                  S5      UR                  S	9U   n
USS2S4   U   n[        R                  " U
R                  S
S5      UR                  S
S5      /S5      nU	R                  S
S5      UR                  S
S5      4$ )a  Find nearest neighbors in desc2 for each vector in desc1.

The method satisfies first to second nearest neighbor distance <= th.

If the distance matrix dm is not provided, :py:func:`torch.cdist` is used.

Args:
    desc1: Batch of descriptors of a shape :math:`(B1, D)`.
    desc2: Batch of descriptors of a shape :math:`(B2, D)`.
    th: distance ratio threshold.
    dm: torch.Tensor containing the distances from each descriptor in desc1
      to each descriptor in desc2, shape of :math:`(B1, B2)`.

Return:
    - Descriptor distance of matching descriptors, shape of :math:`(B3, 1)`.
    - Long torch.Tensor indexes of matching descriptors in desc1 and desc2. Shape: :math:`(B3, 2)`,
      where 0 <= B3 <= B1.

rB   rC   r   r   r   Fr   largestNrE   rF   )r   shaper@   r9   r   topkrG   rH   r!   r;   rI   rJ   )r5   r6   r.   r(   rK   valsrM   ratiomaskrL   rN   rO   s               r)   	match_snnr`      s5   , usEl+usEl+{{1~ekk!nq0/bAOjj!EJODAJad#E;D+K
;1))||Ay~~a09O9OPQUVH!Q$%I99hmmB2INN2q4IJANLB"L$5$5b!$<<<r+   c                 p   [        U SS/5        [        USS/5        U R                  S   S:  d  UR                  S   S:  a  [        U 5      $ [        XU5      n[	        XX$5      u  pV[	        XX$R                  5       5      u  px[        U5      S:  Ga  [        U5      S:  Ga  UR                  S5      n[        U5      (       d3  [        R                  " UR                  5       UR                  5       SS9n	OUR                  U 5      R                  UR                  S5      SS9n
UR                  U5      R                  UR                  S5      S5      U
-
  R!                  5       R#                  SS9n	U	R%                  UR                  S5      UR                  S5      5      n	U	R'                  SS9S   S	:  nU	R'                  SS9S   S	:  nXkR)                  S
5         nXR)                  S
5         nX[R)                  S
5         nX|R)                  S
5         n[        R*                  " USS2S4   5      u  nn[        R*                  " USS2S4   5      u  nnUU   n[        R,                  " UU   UU   5      nUnUR)                  S
S5      UR)                  S
S5      nnUU4$ [        U5      u  nnUU4$ )a  Find mutual nearest neighbors in desc2 for each vector in desc1.

the method satisfies first to second nearest neighbor distance <= th.

If the distance matrix dm is not provided, :py:func:`torch.cdist` is used.

Args:
    desc1: Batch of descriptors of a shape :math:`(B1, D)`.
    desc2: Batch of descriptors of a shape :math:`(B2, D)`.
    th: distance ratio threshold.
    dm: torch.Tensor containing the distances from each descriptor in desc1
      to each descriptor in desc2, shape of :math:`(B1, B2)`.

Return:
    - Descriptor distance of matching descriptors, shape of. :math:`(B3, 1)`.
    - Long torch.Tensor indexes of matching descriptors in desc1 and desc2,
      shape of :math:`(B3, 2)` where 0 <= B3 <= B1.

rB   rC   r   r   r   g      ?)prD   g:0yE>rF   N)r   r[   r@   r9   r`   r"   rG   flipr   r   r   floattorepeat_interleaver!   r    absr   reshaper   rJ   sortmax)r5   r6   r.   r(   rK   dists1idx1dists2idx2idxs_dm	idxs1_repmutual_idxs1mutual_idxs2
good_idxs1
good_idxs2dists1_gooddists2_good_idx_upl1idx_upl2rL   rO   s                         r)   
match_smnnrz      sv   , usEl+usEl+AA 2/bAOU2?LFU2/@/@/BCLF
6{Q3v;?yy|!$''kk$**,

DG88118MIwwu~,,TYYq\1=	INNPTTYZT[GoodiilDIIaLAG{{q{)!,t3{{q{)!,t3++B/0
++B/0
..r23..r23jjAqD!128jjAqD!128)
iiH 5{87LM!$/$4$4R$;\=N=NrST=U\ $$ %.o$>!\$$r+   lafs1lafs2r0   r/   c                 :   [        U SS/5        [        USS/5        Sn[        XU5      n	U	R                  n
UR                  S   S:  a  [	        U	5      $ [        S[        SUR                  S   5      5      n[        R                  " XSSS	9u  pUS
S
2S4   n[        U5      R                  SS5      nX   n[        R                  " UUSS -
  SSS9nUS
S
2SS
24   US
S
2SS
24   U:  R                  U
5      U-  -   nUR                  SS9u  nnUnUS
S
2S4   nUU-  nUU:*  nUU   n[        U5      S:X  a  [	        U	5      $ [        R                  " SUR                  S5      U	R                   S9U   nUU   n[        R"                  " UR                  SS5      UR                  SS5      /S5      nUR                  SS5      UR                  SS5      nnU(       d  UU4$ [        R                  " U	SS9u  nnUS
S
2S4   UUS
S
2S4      :H  nUU   UU   4$ )a&  Find nearest neighbors in desc2 for each vector in desc1.

The method satisfies first to second nearest neighbor distance <= th,
and assures 2nd nearest neighbor is geometrically inconsistent with the 1st one
(see :cite:`MODS2015` for more details)

If the distance matrix dm is not provided, :py:func:`torch.cdist` is used.

Args:
    desc1: Batch of descriptors of a shape :math:`(B1, D)`.
    desc2: Batch of descriptors of a shape :math:`(B2, D)`.
    lafs1: LAFs of a shape :math:`(1, B1, 2, 3)`.
    lafs2: LAFs of a shape :math:`(1, B2, 2, 3)`.
    th: distance ratio threshold.
    spatial_th: minimal distance in pixels to 2nd nearest neighbor.
    mutual: also perform mutual nearest neighbor check.
    dm: torch.Tensor containing the distances from each descriptor in desc1
      to each descriptor in desc2, shape of :math:`(B1, B2)`.

Return:
    - Descriptor distance of matching descriptors, shape of :math:`(B3, 1)`.
    - Long torch.Tensor indexes of matching descriptors in desc1 and desc2. Shape: :math:`(B3, 2)`,
      where 0 <= B3 <= B1.

rB   rC   g    .Ar   r   
   r   FrY   NrF   )rb   r   rD   rE   )r   r9   r   r[   r@   rj   r   r   r\   r   rJ   normre   rG   rH   r!   r;   rI   )r5   r6   r{   r|   r.   r0   r/   r(   
BIG_NUMBERrK   r   num_candidates	vals_candrM   r]   xy2candidates_xykdist
fginn_valsfginn_vals_best_fginn_idxs_bestvals_2ndr^   r_   rL   rN   rO   rw   idxs_in_1_mut	good_masks                                 r)   match_fginnr      s:   F usEl+usEl+J/bAO!!E{{1~))CEKKN34N ::o1V[\IQT?D


$
$R
+CNMJJ}}Qq'99QAFE1ab5!U1ab5\J%>$B$B5$IJ$VVJ(21(=%O%
 H!Q$I8OEB;D+K
;1))||Ay~~a09O9OPQUVH$I99hmmB2INN2q4IJANL + 0 0Q 79J9J2q9QKL((yya8A}QT"mLA4F&GGIy!<	#:::r+   c                      ^  \ rS rSrSrSS\S\SS4U 4S jjjrS\R                  S	\R                  S\
\R                  \R                  4   4S
 jrSrU =r$ )DescriptorMatcheriK  a	  nn.Module version of descriptor-only matching functions.

This matcher only requires descriptors (no LAFs). For geometry-aware matching that uses LAFs,
see :class:`~kornia.feature.GeometryAwareDescriptorMatcher`.

See :func:`~kornia.feature.match_nn`, :func:`~kornia.feature.match_snn`,
    :func:`~kornia.feature.match_mnn` or :func:`~kornia.feature.match_smnn` for more details.

Args:
    match_mode: type of matching, can be `nn`, `snn`, `mnn`, `smnn`.
    th: threshold on distance ratio, or other quality measure.


match_moder.   r   Nc                    > [         TU ]  5         UR                  5       n/ SQU l        X0R                  ;  a  [	        U SU R                   35      eX0l        X l        g )Nr	   mnnsnnsmnn is not supported. Try one of )super__init__lowerknown_modesNotImplementedErrorr   r.   )selfr   r.   _match_mode	__class__s       r)   r   DescriptorMatcher.__init__Z  sY    %++-7...%4RSWScScRd&eff%r+   r5   r6   c                 "   U R                   S:X  a  [        X5      nU$ U R                   S:X  a  [        X5      nU$ U R                   S:X  a  [        XU R                  5      nU$ U R                   S:X  a  [        XU R                  5      nU$ [        e)an  Run forward.

Args:
    desc1: Batch of descriptors of a shape :math:`(B1, D)`.
    desc2: Batch of descriptors of a shape :math:`(B2, D)`.

Returns:
    - Descriptor distance of matching descriptors, shape of :math:`(B3, 1)`.
    - Long torch.Tensor indexes of matching descriptors in desc1 and desc2,
        shape of :math:`(B3, 2)` where :math:`0 <= B3 <= B1`.

r	   r   r   r   r   rP   rW   r`   r.   rz   r   )r   r5   r6   outs       r)   forwardDescriptorMatcher.forwardc  s     ??d"5(C 
 __%E)C 
 __%E$''2C
 
	 __&U4773C 
 &%r+   )r   r   r.   )r   皙?)__name__
__module____qualname____firstlineno____doc__strrd   r   r   Tensorr   r   __static_attributes____classcell__r   s   @r)   r   r   K  sc    3 E D  U\\ %,, 5W\WcWcIcCd  r+   r   c                   t  ^  \ rS rSrSr   SS\S\S\S\S\SS	4U 4S
 jjjr	 SS\
R                  S\
R                  S\\
R                     S\\
R                  \
R                  4   4S jjr  SS\
R                  S\
R                  S\S\\   S\\
R                  \
R                  \\   4   4
S jjrSrU =r$ )DescriptorMatcherWithSteereri}  a_  Matching that is invariant under rotations, using Steerers.

Args:
    steerer: An instance of :func:`kornia.feature.steerers.DiscreteSteerer`.
    steerer_order: order of discretisation of rotation angles, e.g. 4 leads to quarter rotations.
    steer_mode: can be `global`, `local`.
        `global` means that the we output matches from the global rotation with most matches.
        `local` means that we output matches from a distance matrix
        where the distance between each descriptor pair is the minimal over rotations.
    match_mode: type of matching, can be `nn`, `snn`, `mnn`, `smnn`.
        WARNING: using steer_mode `global` with match_mode `nn` will lead to bad results
        since `nn` doesn't generate different amount of matches depending on goodness of fit.
    th: threshold on distance ratio, or other quality measure.

Example:
    >>> import kornia as K
    >>> import kornia.feature as KF
    >>> device = K.core.utils.get_cuda_or_mps_device_if_available()
    >>> img1 = torch.randn([1, 3, 768, 768], device=device)
    >>> img2 = torch.randn([1, 3, 768, 768], device=device)
    >>> dedode = KF.DeDoDe.from_pretrained(detector_weights="L-C4-v2", descriptor_weights="B-SO2").to(device)
    >>> steerer_order = 8  # discretisation order of rotation angles
    >>> steerer = KF.steerers.DiscreteSteerer.create_dedode_default(
    ... generator_type="SO2", steerer_order=steerer_order
    ... )
    >>> steerer = steerer.to(device)
    >>> matcher = KF.matching.DescriptorMatcherWithSteerer(
    ... steerer=steerer, steerer_order=steerer_order, steer_mode="global", match_mode="smnn", th=0.98
    ... )
    >>> with torch.inference_mode():
    ...     kps1, scores1, descs1 = dedode(img1, n=20_000)
    ...     kps2, scores2, descs2 = dedode(img2, n=20_000)
    ...     kps1, kps2, descs1, descs2 = kps1[0], kps2[0], descs1[0], descs2[0]
    ...     dists, idxs, num_rot = matcher(
    ...         descs1, descs2, normalize=True, subset_size=1000,
    ...     )
    >>> # print(f"{idxs.shape[0]} tentative matches with steered DeDoDe")
    >>> # print(f"at rotation of {num_rot * 360 / steerer_order} degrees")

steerersteerer_order
steer_moder   r.   r   Nc                 f  > [         TU ]  5         Xl        X l        UR	                  5       nSS/U l        X`R
                  ;  a  [        U SU R
                   35      eX`l        UR	                  5       n/ SQU l        XpR                  ;  a  [        U SU R                   35      eXpl	        XPl
        g )Ngloballocalr   r   )r   r   r   r   r   known_steer_modesr   r   r   r   r.   )	r   r   r   r   r   r.   _steer_moder   r   s	           r)   r   %DescriptorMatcherWithSteerer.__init__  s     	*%++-"*G!4444%4RSWSiSiRj&kll%%++-7...%4RSWScScRd&eff%r+   r   r   r(   c                 
   U R                   S:X  a
  [        XUS9$ U R                   S:X  a
  [        XUS9$ U R                   S:X  a  [        XU R                  US9$ U R                   S:X  a  [        XU R                  US9$ [        e)Nr	   )r(   r   r   r   r   )r   r   r   r(   s       r)   matching_function.DescriptorMatcherWithSteerer.matching_function  sz     ??d"Br**__%R++__%RTWW44__&bdgg"55%%r+   r5   r6   	normalizesubset_sizec                    SnU(       a*  [         R                  " USS9n[         R                  " USS9nU R                  S:X  Ga  Ub  [        R                  " UR
                  S   5      SU n[        R                  " UR
                  S   5      SU nU " X   X'   US9u    pU R                  R                  UUUS9nU R                  XS5      u  pXU4$ U R                  XS5      u  pSn[        SU R                  5       HV  nU R                  R                  XS9nU R                  XS5      u  pUR
                  S   U
R
                  S   :  d  MR  XUpZn	MX     OU R                  S	:X  aw  [        X5      n[        SU R                  5       H=  nU R                  R                  XS9n[        X5      n[        R                  " X5      nM?     U R                  XU5      u  pO[        eXU4$ )
a+  Run forward.

Args:
    desc1: Batch of descriptors of a shape :math:`(B1, D)`.
    desc2: Batch of descriptors of a shape :math:`(B2, D)`.
    normalize: bool to decide whether to F.normalize descriptors to unit norm.
    subset_size: If set, the subset size to use for determining optimal
        number of rotations. Smaller subset size leads to faster but less
        accurate matching. Only used when `self.steer_mode` is `"global"`.

Returns:
    - Descriptor distance of matching descriptors, shape of :math:`(B3, 1)`.
    - Long torch.Tensor indexes of matching descriptors in desc1 and desc2,
        shape of :math:`(B3, 2)` where :math:`0 <= B3 <= B1`.
    - Number of global rotations from desc1 to desc2, in terms of `self.steerer_order`
        (will be `None` if `self.steer_mode` is `local`).

NrF   rD   r   r   )r   )steerer_powerr   r   r   )Fr   r   r   randpermr[   r   steer_descriptionsr   ranger   r*   minimumr   )r   r5   r6   r   r   rot1to2
subsample1
subsample2rw   distidxrdist_newidx_newr(   dm_news                   r)   r   $DescriptorMatcherWithSteerer.forward  s   2 KK2.EKK2.E??h&&"^^EKKN;L[I
"^^EKKN;L[I
 $%%'!1
 77")' 8 
 !225F	'))..uTBIDG1d001777S$($:$:5$N!==#ciil2)1AwDw	 2
 __'%B1d001777S-]]2. 2 ..uR@ID#%%'!!r+   )r   r   r   r   r   r   r.   )r   r   r   N)FN)r   r   r   r   r   r   intr   rd   r   r   r   r   r   r   boolr   r   r   r   s   @r)   r   r   }  s   'Z #   	
   
 2 PT&,,&$)LL&6>u||6L&	u||U\\)	*&$  %)@"||@" ||@" 	@"
 c]@" 
u||U\\8C=8	9@" @"r+   r   c                   $  ^  \ rS rSr% SrSS/r\\\      \	S'   SS\S\
\\\R                  4      S	S4U 4S
 jjjrS\R                  S\R                  S\R                  S\R                  S	\\R                  \R                  4   4
S jrSrU =r$ )GeometryAwareDescriptorMatcheri  a  nn.Module version of geometry-aware matching functions that use LAFs (Local Affine Frames).

Unlike :class:`~kornia.feature.DescriptorMatcher`, this matcher requires both descriptors and LAFs.
See :func:`~kornia.feature.match_fginn` or :func:`~kornia.feature.match_adalam` for more details.

Args:
    match_mode: type of matching, can be `fginn` or `adalam`.
    params: dictionary of parameters for the matching function.

fginnadalamr   Nr   paramsr   c                    > [         TU ]  5         UR                  5       nX0R                  ;  a  [	        U SU R                   35      eX0l        U=(       d    0 U l        g )Nr   )r   r   r   r   r   r   r   )r   r   r   r   r   s       r)   r   'GeometryAwareDescriptorMatcher.__init__  sW    %++-...%4RSWScScRd&eff%lr+   r5   r6   r{   r|   c           
      0   U R                   S:X  a?  [        5       nUR                  U R                  5        [	        XX4US   US   US   5      nU$ U R                   S:X  a2  [        5       nUR                  U R                  5        [        XX4US9nU$ [        e)a  Run forward.

Args:
    desc1: Batch of descriptors of a shape :math:`(B1, D)`.
    desc2: Batch of descriptors of a shape :math:`(B2, D)`.
    lafs1: LAFs of a shape :math:`(1, B1, 2, 3)`.
    lafs2: LAFs of a shape :math:`(1, B2, 2, 3)`.

Returns:
    - Descriptor distance of matching descriptors, shape of :math:`(B3, 1)`.
    - Long torch.Tensor indexes of matching descriptors in desc1 and desc2,
        shape of :math:`(B3, 2)` where :math:`0 <= B3 <= B1`.

r   r.   r0   r/   r   r2   )r   r4   updater   r   r   r   r   )r   r5   r6   r{   r|   r   r   _paramss           r)   r   &GeometryAwareDescriptorMatcher.forward&  s    " ??g%.0FMM$++&eE&,|H\^dem^noC 
 __(/1GNN4;;'uU'JC 
 &%r+   )r   r   )r   N)r   r   r   r   r   r   r   r   r   __annotations__r   r   r   r   r   r   r   r   r   r   s   @r)   r   r     s    	 )0':K$s)$:#3 #(4U\\HYCZ:[ #gk # #\\*/,,?D||TYT`T`	u||U\\)	* r+   r   r   )r   N)gffffff?N)r   r-   FN))typingr   r   r   r   r   r   r   torch.nn.functionalr	   
functionalr   kornia.core.checkr
   r   kornia.core.utilsr   kornia.feature.lafr   kornia.feature.steerersr   r   r   r   r   r*   r   r4   r9   r@   rP   rW   rd   r`   rz   r   r   Moduler   r   r   r1   r+   r)   <module>r      s  $ > =     F 0 - 3 ;u||  %,, $4S>  MQ<< %3;ELL3I
\\(
%,, 
5u||)C#D 
 LP=<<= %=2:5<<2H=
5<<%&=< LP%=<<%= %%=2:5<<2H%=
5<<%&%=R ]a%=<<%= %%=27%=CKELLCY%=
5<<%&%=R ^b6%<<6% %6%276%DLU\\DZ6%
5<<%&6%| !%J;<<J;<<J; <<J; <<	J;
 	J; J; J; 	J; 5<<%&J;Z/		 /dP"299 P"f1RYY 1r+   