o
    oi6                     @   s   d dl mZmZmZ d dlZd dlmZmZ d dlm	Z	m
Z
 d dlmZmZmZ ddlmZmZmZ ddlmZ d	efd
dZ				ddededededee deeeef  deeeef  dee d	eeef fddZG dd dZdS )    )OptionalTupleUnionN)Tensor	as_tensor)KORNIA_CHECK_LAFKORNIA_CHECK_SHAPE)get_laf_centerget_laf_orientationget_laf_scale   )AdalamConfig	_no_matchadalam_core)dist_matrixreturnc                   C   s$   t ddddddddd	d	td
dS )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$    r&   r&   P/home/ubuntu/.local/lib/python3.10/site-packages/kornia/feature/adalam/adalam.pyget_adalam_default_config"   s   r(   desc1desc2lafs1lafs2confighw1hw2dmc                 C   s  t | ddg t |ddg t| t| t }|du r#| j|d< n&t }| D ]\}	}
|	| vrDtd|	 dt|  d q*|
||	< q*t|}|j	t
|dd	t
|dd	| |||t|dt|dt|dt|dd
d\}}||fS )a  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: 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 tensor indexes of matching descriptors in desc1 and desc2. Shape: :math:`(B3, 2)`,
          where 0 <= B3 <= B1.

    BDIMNr$   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.   r/   r0   config_keyvaladalam_objectidxsqualityr&   r&   r'   match_adalam3   s@   "


rD   c                   @   s2  e Zd Zddee ddfddZ								ddeded	ed
edee deeeef  deeeef  dee dee dee dee de	de
eeef ef fddZ							ddededededeeeef  deeeef  dee dee dee dee de	de
eeef ef fddZdS )r;   Ncustom_configr   c                 C   s   |dur	|| _ dS t | _ dS )a3  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(   )selfrE   r&   r&   r'   __init__y   s   
zAdalamFilter.__init__Fk1k2putative_matchesscoresmnnim1shapeim2shapeo1o2s1s2r6   c                 C   sP   t   t|||||||||	|
|| j|dW  d   S 1 s!w   Y  dS )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 tensor with shape (num_keypoints_in_source_image, 2).
            k2: keypoint locations in the destination image, in pixel coordinates.
                Expected a float32 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 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 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 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 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 tensor with shape (num_filtered_matches, 2) with indices of corresponding keypoints in k1 and k2.

        )fnn12scores1rL   rM   rN   rO   rP   rQ   rR   r-   r6   N)r%   no_gradr   r-   )rF   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   r6   r&   r&   r'   filter_matches   s"   
7$zAdalamFilter.filter_matchesd1d2c                 C   s  |	du s|
du r| j d durtd|du s|du r&| j d dur&tdt|| j d tjd}t|| j d tjd}t|| j d tjd}t|| j d tjd}|durmt|| j d tjd}t|| j d tjd}n||}}|	durt|	| j d tjd}t|
| j d tjd}n|	|
}}t|dkst|dkrt|\}}|r||fS |S t||d	d
}tj|ddd	d\}}|dddf }|dddf |dddf 	d }| j d rtj
|dd\}}|| tj|jd | j d dk}nd}| ||||||||||||S )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 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_normalizedr5   )kdimlargestr   gMbP?r#   )r\   )r$   )r-   AttributeErrorr   r%   float32lenr   r   topk
clamp_min_minarangeshaperV   )rF   rH   rI   rW   rX   rM   rN   rO   rP   rQ   rR   r6   _k1_k2_d1_d2_o1_o2_s1_s2rB   distsdistmatdd12nn12rJ   rK   _dd21nn21rL   r&   r&   r'   r<      sL   6

&
$zAdalamFilter.match_and_filter)N)NNNNNNNF)NNNNNNF)__name__
__module____qualname__r   r   rG   r   r   intboolr   rV   r<   r&   r&   r&   r'   r;   x   s    	

N	
r;   )NNNN)typingr   r   r   r%   kornia.corer   r   kornia.core.checkr   r   kornia.feature.lafr	   r
   r   corer   r   r   utilsr   r(   rw   rD   r;   r&   r&   r&   r'   <module>   s@   
	
E