
    3j9                        S SK JrJrJr  S SKrS SKJrJr  S SKJ	r	J
r
Jr  SSKJrJrJr  SSKJr  S\4S	 jr    SS
\R&                  S\R&                  S\R&                  S\R&                  S\\   S\\\\4      S\\\\4      S\\R&                     S\\R&                  \R&                  4   4S jjr " S S5      rg)    )OptionalTupleUnionN)KORNIA_CHECK_LAFKORNIA_CHECK_SHAPE)get_laf_centerget_laf_orientationget_laf_scale   )AdalamConfig	_no_matchadalam_core)dist_matrixreturnc                  P    [        SSSSSSSSS	S	[        R                  " S
5      S9$ )zReturn default Adalam Config.d                  g      ?   Tcpu)
area_ratiosearch_expansionransac_itersmin_inliersmin_confidence orientation_difference_thresholdscale_rate_thresholddetected_scale_rate_thresholdrefitforce_seed_mnndevice)r   torchr$        V/home/wildlama/miniconda3/lib/python3.13/site-packages/kornia/feature/adalam/adalam.pyget_adalam_default_configr)   !   s9    )+ &'||E" r'   desc1desc2lafs1lafs2confighw1hw2dmc                    [        U SS/5        [        USS/5        [        U5        [        U5        [        5       nUc  U R                  US'   Oe[        5       nUR	                  5        HG  u  pXR                  5       ;  a+  [        SU	 S[        UR                  5       5       S35        MC  XU	'   MI     [        U5      nUR                  [        U5      R                  SS5      [        U5      R                  SS5      U UUU[        U5      R                  S5      [        U5      R                  S5      [        U5      R                  S5      [        U5      R                  S5      S	S
9u  pX4$ )aY  Perform descriptor matching, followed by AdaLAM filtering.

See :cite:`AdaLAM2020` 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)`.
    config: dict with AdaLAM config
    dm: torch.Tensor containing the distances from each descriptor in desc1
      to each descriptor in desc2, shape of :math:`(B1, B2)`.
    hw1: Height/width of image.
    hw2: Height/width of image.


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.

BDIMr$   zFWARNING: custom configuration contains a key which is not recognized (z). Known configurations are .   T)return_dist)r   r   r)   r$   itemskeysprintlistAdalamFiltermatch_and_filterr   reshaper	   r
   )r*   r+   r,   r-   r.   r/   r0   r1   config_keyvaladalam_objectidxsqualitys                 r(   match_adalamrF   2   s`   D usEl+usEl+UU')G~!LL+-HC,,.(\]`\a b004W\\^0D/EQH CL ' !)M!22u%%b!,u%%b!,E"**2.E"**2.e$$R(e$$R( 3 MD =r'   c                   <   \ rS rSrSrSS\\   SS4S jjr        SS\R                  S\R                  S	\R                  S
\R                  S\\R                     S\\
\\4      S\\
\\4      S\\R                     S\\R                     S\\R                     S\\R                     S\S\\
\R                  \R                  4   \R                  4   4S jjr       SS\R                  S\R                  S\R                  S\R                  S\\
\\4      S\\
\\4      S\\R                     S\\R                     S\\R                     S\\R                     S\S\\
\R                  \R                  4   \R                  4   4S jjrSrg)r=   w   a	  Implement the AdaLAM (Adaptive Locally-Affine Matching) filter for outlier rejection.

This class wraps the AdaLAM algorithm to filter feature matches based on
local affine consistency.

Args:
    custom_config: Optional configuration object for AdaLAM parameters.
Ncustom_configr   c                 6    Ub  Xl         g[        5       U l         g)a  Wrap the method AdaLAM for outlier filtering.

init args:
    custom_config: dictionary overriding the default configuration. Missing parameters are kept as default.
                   See documentation of DEFAULT_CONFIG for specific explanations on the accepted parameters.
N)r.   r)   )selfrI   s     r(   __init__AdalamFilter.__init__   s     $'K35DKr'   k1k2putative_matchesscoresmnnim1shapeim2shapeo1o2s1s2r8   c                     [         R                  " 5          [        UUUUUUUUU	U
UU R                  US9sSSS5        $ ! , (       d  f       g= f)a
  Call the core functionality of AdaLAM, i.e. just outlier filtering.

No sanity check is performed on the inputs.

Args:
    k1: keypoint locations in the source image, in pixel coordinates.
        Expected a float32 torch.Tensor with shape (num_keypoints_in_source_image, 2).
    k2: keypoint locations in the destination image, in pixel coordinates.
        Expected a float32 torch.Tensor with shape (num_keypoints_in_destination_image, 2).
    putative_matches: Initial set of putative matches to be filtered.
                      The current implementation assumes that these are unfiltered nearest neighbor matches,
                      so it requires this to be a list of indices a_i such that the source keypoint i is
                      associated to the destination keypoint a_i. For now to use AdaLAM on different inputs a
                      workaround on the input format is required.
                      Expected a long torch.Tensor with shape (num_keypoints_in_source_image,).
    scores: Confidence scores on the putative_matches. Usually holds Lowe's ratio scores.
    mnn: A mask indicating which putative matches are also mutual nearest neighbors. See documentation on
         'force_seed_mnn' in the DEFAULT_CONFIG. If None, it disables the mutual nearest neighbor filtering on
         seed point selection. Expected a bool torch.Tensor with shape (num_keypoints_in_source_image,)
    im1shape: Shape of the source image. If None, it is inferred from keypoints max and min, at the cost of
              wasted runtime. So please provide it. Expected a tuple with (width, height) or (height, width)
              of source image
    im2shape: Shape of the destination image. If None, it is inferred from keypoints max and min, at the cost
              of wasted runtime. So please provide it. Expected a tuple with (width, height) or (height, width)
              of destination image
    o1: keypoint orientations in degrees. They can be None if 'orientation_difference_threshold' in config
           is set to None. See documentation on 'orientation_difference_threshold' in the DEFAULT_CONFIG.
           Expected a float32 torch.Tensor with shape (num_keypoints_in_source/destination_image,)
    o2: same as o1 but for destination.
    s1: keypoint scales. They can be None if 'scale_rate_threshold' in config is set to None.
           See documentation on 'scale_rate_threshold' in the DEFAULT_CONFIG.
           Expected a float32 torch.Tensor with shape (num_keypoints_in_source/destination_image,)
    s2: same as s1 but for destination.
    return_dist: if True, inverse confidence value is also outputted.

Returns:
    Filtered putative matches.
    A long torch.Tensor with shape (num_filtered_matches, 2) with indices of corresponding
    keypoints in k1 and k2.

)fnn12scores1rR   rS   rT   rU   rV   rW   rX   r.   r8   N)r%   no_gradr   r.   )rK   rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   r8   s                r(   filter_matchesAdalamFilter.filter_matches   sK    p ]]_&!!{{' __s	   ?
Ad1d2c                    U	b  U
c  U R                   S   b  [        S5      eUb  Uc  U R                   S   b  [        S5      e[        R                  " XR                   S   [        R                  S9n[        R                  " X R                   S   [        R                  S9n[        R                  " X0R                   S   [        R                  S9n[        R                  " X@R                   S   [        R                  S9nUba  [        R                  " XpR                   S   [        R                  S9n[        R                  " XR                   S   [        R                  S9nOXxnnU	ba  [        R                  " XR                   S   [        R                  S9n[        R                  " XR                   S   [        R                  S9nOXnn[        U5      S::  d  [        U5      S::  a  [        U5      u  nnU(       a  UU4$ U$ [        XS	S
9n[        R                  " USSS	S9u  nnUSS2S4   nUSS2S4   USS2S4   R                  S5      -  nU R                   S   (       aN  [        R                  " USS9u  nnUU   [        R                  " UR                  S   U R                   S   S9:H  nOSnU R                  XUUUXVUUUUU5      $ )a  Match and filter with AdaLAM.

This function:

    - performs some elementary sanity check on the inputs;
    - wraps input arrays into torch tensors and loads to GPU if necessary;
    - extracts nearest neighbors;
    - finds mutual nearest neighbors if required;
    - finally calls AdaLAM filtering.

Args:
    k1: keypoint locations in the source image, in pixel coordinates.
        Expected an array with shape (num_keypoints_in_source_image, 2).
    k2: keypoint locations in the destination image, in pixel coordinates.
        Expected an array with shape (num_keypoints_in_destination_image, 2).
    d1: descriptors in the source image.
        Expected an array with shape (num_keypoints_in_source_image, descriptor_size).
    d2: descriptors in the destination image.
        Expected an array with shape (num_keypoints_in_destination_image, descriptor_size).
    im1shape: Shape of the source image. If None, it is inferred from keypoints max and min, at the cost of
              wasted runtime. So please provide it. Expected a tuple with (width, height) or (height, width)
              of source image
    im2shape: Shape of the destination image. If None, it is inferred from keypoints max and min, at the cost
              of wasted runtime. So please provide it. Expected a tuple with (width, height) or (height, width)
              of destination image
    o1: keypoint orientations in degrees. They can be None if 'orientation_difference_threshold' in config
           is set to None. See documentation on 'orientation_difference_threshold' in the DEFAULT_CONFIG.
           Expected an array with shape (num_keypoints_in_source/destination_image,)
    o2: Same as o1 for destination.
    s1: keypoint scales. They can be None if 'scale_rate_threshold' in config is set to None.
           See documentation on 'scale_rate_threshold' in the DEFAULT_CONFIG.
           Expected an array with shape (num_keypoints_in_source/destination_image,)
    s2: Same as s1 for destination.
    return_dist: if True, inverse confidence value is also outputted.

Returns:
    Filtered putative matches.
    A long torch.Tensor with shape (num_filtered_matches, 2) with indices of corresponding
    keypoints in k1 and k2.

Nr    zCurrent configuration considers keypoint scales for filtering, but scales have not been provided.
Please either provide scales or set 'scale_rate_threshold' to None to disable scale filteringr   zCurrent configuration considers keypoint orientations for filtering, but orientations have not been provided.
Please either provide orientations or set 'orientation_difference_threshold' to None to disable orientations filteringr$   )r$   dtyper   F)is_normalizedr7   )kdimlargestr   gMbP?r#   )re   )r$   )r.   AttributeErrorr%   	as_tensorfloat32lenr   r   topk
clamp_min_minarangeshaper]   )rK   rN   rO   r_   r`   rS   rT   rU   rV   rW   rX   r8   _k1_k2_d1_d2_o1_o2_s1_s2rD   distsdistmatdd12nn12rP   rQ   _dd21nn21rR   s                                 r(   r>   AdalamFilter.match_and_filter   sk   n :{{12>$t  :{{=>J$M  oobX)>emmToobX)>emmToobX)>emmToobX)>emmT>//"[[-B%--XC//"[[-B%--XCC>//"[[-B%--XC//"[[-B%--XCCHMs3x1}#C.KD%U{"Kce<ZZ1!UC
d1:add1a4j33D99;;'())G3KE4'(ELL1dkkZbNc,ddCC""&XcSVX[]h
 	
r'   )r.   )N)NNNNNNNF)NNNNNNF)__name__
__module____qualname____firstlineno____doc__r   r   rL   r%   Tensorr   intboolr   r]   r>   __static_attributes__r&   r'   r(   r=   r=   w   sW   
6h|&< 
6 
6$ '+.2.2%)%)%)%)!GLLG LLG  ,,	G
 G ell#G 5c?+G 5c?+G U\\"G U\\"G U\\"G U\\"G G 
uU\\5<</0%,,>	?G^ /3.2%)%)%)%)!f
LLf
 LLf
 LL	f

 LLf
 5c?+f
 5c?+f
 U\\"f
 U\\"f
 U\\"f
 U\\"f
 f
 
uU\\5<</0%,,>	?f
 f
r'   r=   )NNNN)typingr   r   r   r%   kornia.core.checkr   r   kornia.feature.lafr   r	   r
   corer   r   r   utilsr   r)   r   r   rF   r=   r&   r'   r(   <module>r      s   , * )  B Q Q 6 6 < , &*%)%)!%B<<B<<B <<B <<	B
 \"B 
%S/	"B 
%S/	"B 	B 5<<%&BJE
 E
r'   