a
    d;                     @   sf  d dl mZmZmZ d dlZd dlmZ d dlmZ d dl	m
Z
mZmZ ddlmZmZ dd Zd$eeee d	d
dZedddZd%eeee eeef dddZd&eeee eeef dddZd'eeeee eeef dddZd(eeeee eeef dddZd)eeeeeeeee eeef d	ddZG d d! d!ejZG d"d# d#ejZdS )*    )DictOptionalTupleN)get_laf_center)KORNIA_CHECK_DM_DESCKORNIA_CHECK_SHAPETensor   )get_adalam_default_configmatch_adalamc                  C   s   dddd} | S )Ng333333?F      $@)thmutual
spatial_th configr   r   `/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/feature/matching.py_get_default_fginn_params   s    r   )desc1desc2dm_c                 C   s*   |du rt | |}nt| || |}|S )a  Helper function, which checks validity of provided distance matrix, or calculates L2-distance matrix 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: Tensor containing the distances from each descriptor in desc1
          to each descriptor in desc2, shape of :math:`(B1, B2)`.
    N)torchcdistr   )r   r   r   dmr   r   r   _get_lazy_distance_matrix   s
    
r   )r   c                 C   s4   t jdd| j| jd}t jdd| jt jd}||fS )zHelper function, which output empty tensors.

    Returns:
            - Descriptor distance of matching descriptors, shape of :math:`(0, 1)`.
            - Long tensor indexes of matching descriptors in desc1 and desc2, shape of :math:`(0, 2)`.
    r   r	   )devicedtype   )r   emptyr   r   long)r   distsZidxsr   r   r   	_no_match#   s    r"   )r   r   r   returnc                 C   s   t | ddg t |ddg t| ||}tj|dd\}}tjd|d|jd}tj|dd|ddgdd}|dd|ddfS )	ay  Function, which finds 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: 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 tensor indexes of matching descriptors in desc1 and desc2, shape of :math:`(B1, 2)`.
    BDIMr	   dimr   r   r   )	r   r   r   minarangesizer   catview)r   r   r   distance_matrixmatch_dists	idxs_in_2idxs_in1matches_idxsr   r   r   match_nn/   s    "r4   c                 C   s$  t | ddg t |ddg t| ||}t|d|d}tj|dd\}}tj|dd\}}tj||jd}	|d|dkr|	|| d| k}
tj|	dd|ddgdd|
 }||
 }nB|	|| d| k}
tj|dd|	ddgdd|
 }||
 }|dd|dd	fS )
a  Function, which finds 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: 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 of :math:`(B3, 2)`,
          where 0 <= B3 <= min(B1, B2)
    r$   r%   r   r	   r&   r(   Nr)   r   )	r   r   r*   r,   r   r+   r   r-   r.   )r   r   r   r/   msr0   r1   Zmatch_dists2Z	idxs_in_1Zminsize_idxsZ
mutual_nnsr3   r   r   r   	match_mnnH   s    &
&r6   皙?)r   r   r   r   r#   c                 C   s  t | ddg t |ddg t| ||}|jd dk r>t|S tj|dddd\}}|dddf |dddf  }||k}|| }	t|	dkrt|S tjd|d|j	d	| }
|dddf | }tj
|
d
d|d
dgdd}|	d
d|d
dfS )a  Function, which finds 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: 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.
    r$   r%   r   r   r	   Fr'   ZlargestNr(   r)   r&   )r   r   shaper"   r   topklenr+   r,   r   r-   r.   )r   r   r   r   r/   valsr1   ratiomaskr0   r2   r3   r   r   r   	match_snnm   s     "r?   ffffff?c                 C   s  t | ddg t |ddg | jd dk s8|jd dk r@t| S t| ||}t| |||\}}t|| || \}}t|dkrt|dkr|d}tj	|
 |
 dd}	|	jddd d	k }
|	jddd d	k }||
d
 }||d
 }||
d
 }||d
 }t|dddf \}}t|dddf \}}|| }t|| || }|}|d
d|d
d }}nt|\}}||fS )a  Function, which finds 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: 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 of :math:`(B3, 2)` where 0 <= B3 <= B1.
    r$   r%   r   r   r	   g      ?)pr&   g:0yE>r)   N)r   r9   r"   r   r?   tr;   Zflipr   r   floatr*   r.   sortmax)r   r   r   r   r/   Zdists1Zidx1Zdists2Zidx2Zidxs_dmZmutual_idxs1Zmutual_idxs2Z
good_idxs1Z
good_idxs2Zdists1_goodZdists2_good_Zidx_upl1Zidx_upl2r0   r3   r   r   r   
match_smnn   s0    
rG   r   F)	r   r   lafs1lafs2r   r   r   r   r#   c                 C   s  t | ddg t |ddg d}t| ||}	|	j}
|jd dk rHt|	S tdtd|jd }tj|	|ddd	\}}|d
d
df }t	|
dd}|| }tj||dd  ddd}|d
d
dd
f |d
d
dd
f |k |
|  }|jdd\}}|}|d
d
df }|| }||k}|| }t|dkr@t|	S tjd|d|	jd| }|| }tj|
dd|
ddgdd}|
dd|
dd }}|s||fS tj|	dd\}}|d
d
df ||d
d
df  k}|| || fS )av  Function, which finds 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, B1, 2, 3)`.

        th: distance ratio threshold.
        spatial_th: minimal distance in pixels to 2nd nearest neighbor.
        mutual: also perform mutual nearest neighbor check
        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.
    r$   r%   g    .Ar   r   
   r	   Fr8   Nr)   )rA   r'   r&   r(   )r   r   r   r9   r"   rE   r*   r   r:   r   r.   Znormtor;   r+   r,   r   r-   )r   r   rH   rI   r   r   r   r   Z
BIG_NUMBERr/   r   Znum_candidatesZ	vals_candr1   r<   Zxy2Zcandidates_xyZkdistZ
fginn_valsZfginn_vals_bestZfginn_idxs_bestZvals_2ndr=   r>   r0   r2   r3   rF   Zidxs_in_1_mutZ	good_maskr   r   r   match_fginn   s>    #6"$rL   c                       sN   e Zd ZdZg dZdeedd fddZeee	eef d	d
dZ
  ZS )DescriptorMatcheraq  Module version of matching functions.

    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.
    )nnmnnsnnsmnnrP   r7   N)
match_moder   r#   c                    s@   t    | }|| jvr0t| d| j || _|| _d S Nz is not supported. Try one of )super__init__lowerknown_modesNotImplementedErrorrR   r   )selfrR   r   _match_mode	__class__r   r   rU      s    

zDescriptorMatcher.__init__)r   r   r#   c                 C   sh   | j dkrt||}nN| j dkr,t||}n8| j dkrFt||| j}n| j dkr`t||| j}nt|S )  
        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)`.

        Return:
            - Descriptor distance of matching descriptors, shape of :math:`(B3, 1)`.
            - Long tensor indexes of matching descriptors in desc1 and desc2,
                shape of :math:`(B3, 2)` where :math:`0 <= B3 <= B1`.
        rN   rO   rP   rQ   )rR   r4   r6   r?   r   rG   rX   )rY   r   r   outr   r   r   forward(  s    



zDescriptorMatcher.forward)rP   r7   )__name__
__module____qualname____doc__rW   strrC   rU   r   r   r_   __classcell__r   r   r[   r   rM     s   
rM   c                       sV   e Zd ZdZddgZdi feedd fddZeeeee	eef dd	d
Z
  ZS )GeometryAwareDescriptorMatchera^  Module version of matching functions.

    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 `fginn`.
        th: threshold on distance ratio, or other quality measure.
    fginnadalamN)rR   paramsr#   c                    s@   t    | }|| jvr0t| d| j || _|| _d S rS   )rT   rU   rV   rW   rX   rR   ri   )rY   rR   ri   rZ   r[   r   r   rU   O  s    

z'GeometryAwareDescriptorMatcher.__init__)r   r   rH   rI   r#   c              	   C   sv   | j dkr>t }|| j t|||||d |d |d }n4| j dkrnt }|| j t|||||d}nt|S )r]   rg   r   r   r   rh   r   )rR   r   updateri   rL   r
   r   rX   )rY   r   r   rH   rI   ri   r^   r   r   r   r_   W  s    
"
z&GeometryAwareDescriptorMatcher.forward)r`   ra   rb   rc   rW   rd   r   rU   r   r   r_   re   r   r   r[   r   rf   B  s   
rf   )N)N)N)r7   N)r@   N)r7   r   FN)typingr   r   r   r   Ztorch.nnrN   Zkornia.feature.lafr   Zkornia.testingr   r   r   rh   r
   r   r   r   r"   r4   r6   rC   r?   rG   boolrL   ModulerM   rf   r   r   r   r   <module>   s:   ""%$'$7    
M/