a
    d3                     @   s   d dl mZmZmZ d dlZd dlmZ d dlmZmZm	Z	 d dl
mZmZ d dlmZ ddlmZ dd	lmZ d
d Zdeeeeee ee ee ee eeef d	ddZG dd dZdS )    )DictOptionalTupleN)Tensor)get_laf_centerget_laf_orientationget_laf_scale)KORNIA_CHECK_LAFKORNIA_CHECK_SHAPEget_cuda_device_if_available   )adalam_core)dist_matrixc                  C   s"   ddddddddd	d	t  d
} | S )Nd                  g      ?   T)Z
area_ratioZsearch_expansionZransac_itersZmin_inliersZmin_confidence orientation_difference_thresholdscale_rate_thresholdZdetected_scale_rate_thresholdZrefitforce_seed_mnndevicer   )DEFAULT_CONFIG r   e/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/feature/adalam/adalam.pyget_adalam_default_config   s    r   )	desc1desc2lafs1lafs2confighw1hw2dmreturnc                 C   s   t | ddg t |ddg t| t| |du rFt }| j|d< n|}t|}	|	t|ddt|dd| |||t|dt|dt	|dt	|d
}
t
jt|
d| j| jd}||
fS )	aW  Function, which performs 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, B1, 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)`.

    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      r   )dtyper   )r
   r	   r   r   AdalamFiltermatch_and_filterr   Zreshaper   r   torchZoneslenr,   )r   r    r!   r"   r#   r$   r%   r&   Zconfig_Zadalam_objectZidxsZqualityr   r   r   match_adalam$   s.    r1   c                   @   sj   e Zd Ze ZdedddZdejejejejeje	e	ejejejejdddZ
ddd	Zd
d ZdS )r-   N)custom_configc                 C   sL   t j | _|durH| D ]*\}}|| j vr<td q|| j|< qdS )aN  This class acts as a wrapper to 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.
        NzWARNING: custom configuration contains a key which is not recognized ({key}). Known configurations are {list(self.config.keys())}.)r-   r   copyr#   itemskeysprint)selfr2   keyvalr   r   r   __init__^   s    zAdalamFilter.__init__)k1k2putative_matchesscoresmnnim1shapeim2shapeo1o2s1s2c                 C   sN   t  2 t|||||||||	|
|| jdW  d   S 1 s@0    Y  dS )a
  Call the core functionality of AdaLAM, i.e. just outlier filtering. No sanity check is performed on the
        inputs.

        Inputs:
            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/o2: 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,)
            s1/s2: 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,)

        Returns:
            Filtered putative matches.
            A long tensor with shape (num_filtered_matches, 2) with indices of corresponding keypoints in k1 and k2.
        )
Zfnn12Zscores1r?   r@   rA   rB   rC   rD   rE   r#   N)r/   Zno_gradr   r#   )r7   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   r   r   r   filter_matchesq   s    .
zAdalamFilter.filter_matchesc                 C   s2  |	du s|
du r&| j d dur&td|du s6|du rL| j d durLtd| |||||||	|
\}}}}}}}	}
t||dd}tj|dd	dd
\}}|dddf }|dddf |ddd	f d }| j d rtj|dd\}}|| tj|j	d | j d dk}nd}| 
||||||||||	|
S )a  Standard matching and filtering 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.

        Inputs:
            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/o2: 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,)
            s1/s2: 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,)

        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 filteringF)is_normalizedr+   r   )kdimZlargestr   gMbP?r   )rI   r   )r   )r#   AttributeError_AdalamFilter__to_torchr   r/   ZtopkZ
clamp_min_minZarangeshaperF   )r7   r;   r<   d1Zd2r@   rA   rB   rC   rD   rE   ZdistmatZdd12Znn12r=   r>   Zdd21Znn21r?   r   r   r   r.      s(    !(&$zAdalamFilter.match_and_filterc                    s    fdd|D S )Nc                 3   s<   | ]4}|d u st |r|nt j| jd t jdV  qd S )Nr   )r   r,   )r/   Z	is_tensorZtensorr#   float32).0ar7   r   r   	<genexpr>   s   z*AdalamFilter.__to_torch.<locals>.<genexpr>r   )r7   argsr   rR   r   Z
__to_torch   s    
zAdalamFilter.__to_torch)N)NNNNNNN)NNNNNN)__name__
__module____qualname__r   r   dictr:   r/   r   tuplerF   r.   rK   r   r   r   r   r-   [   s0          >
;r-   )NNNN)typingr   r   r   r/   r   Zkornia.feature.lafr   r   r   Zkornia.testingr	   r
   Zkornia.utils.helpersr   corer   utilsr   r   r1   r-   r   r   r   r   <module>   s0       
7