o
    oi-                     @   s   d dl mZmZmZmZ d dlZd dlm  mZ	 d dlmZ d dl
mZmZ dZdededeeeef d	dfd
dZdededeeeef deded	dfddZdeded	efddZG dd deZdS )    )AnyDictOptionalUnionN)nn)ModuleTensorg    eAmbvreturnc                 C   s   |dkrdS || ddd|f< || ddddd|f< || ddddddd|f< || ddddddddd|f< || dd| df< || dddd| df< || dddddd| df< || dddddddd| df< dS )zMask borders with value.

    Args:
        m (torch.Tensor): [N, H0, W0, H1, W1]
        b (int): border size.
        v (m.dtype): border value.
    r   N )r	   r
   r   r   r   ^/home/ubuntu/.local/lib/python3.10/site-packages/kornia/feature/loftr/utils/coarse_matching.pymask_border   s    &",r   bdp_m0p_m1c              	   C   s  |dkrdS || ddd|f< || ddddd|f< || ddddddd|f< || ddddddddd|f< | ddd  | ddd  }}| ddd  | ddd  }}tt||||D ]B\}	\}
}}}|| |	|
| df< || |	dd|| df< || |	dddd|| df< || |	dddddd|| df< q{dS )z"Apply masking to a padded boarder.r   N   )summaxint	enumeratezip)r	   r   r   r   r   h0sw0sh1sw1sb_idxh0w0h1w1r   r   r   mask_border_with_padding2   s    &22" (r#   c              	   C   s   |  ddd |  ddd }}| ddd | ddd }}t tt|| || gddd }|S )zCompute the max candidates of all pairs within a batch.

    Args:
        p_m0: padded mask 0
        p_m1: padded mask 1

    r   r   r   )r   r   torchminstack)r   r   r   r   r   r   max_candr   r   r   compute_max_candidatesE   s   ***r(   c                       s   e Zd Zdeeef ddf fddZ		ddededeeef d	ee d
ee ddfddZ	e
 dedeeef deeef fddZ  ZS )CoarseMatchingconfigr   Nc                    s   t    || _|d | _|d | _|d | _|d | _|d | _| jdkr-|d | _d S | jdkrczd	d
l	m
} W n tyF   tdd w || _
ttj|d dd| _|d | _|d | _d S t)Nthr	border_rmtrain_coarse_percenttrain_pad_num_gt_min
match_typedual_softmaxdsmax_temperaturesinkhornr   )log_optimal_transportzdownload superglue.py first!skh_init_bin_scoreT)requires_grad	skh_itersskh_prefilter)super__init__r*   r+   r,   r-   r.   r/   temperature	supergluer3   ImportErrorr   	Parameterr$   tensor	bin_scorer6   r7   NotImplementedError)selfr*   r3   	__class__r   r   r9   T   s(   









zCoarseMatching.__init__feat_c0feat_c1datamask_c0mask_c1c                 C   s  | d| d| d| df\}}}}dd ||fD \}}| jdkrYtd||| j }	|durL|durL|	|d	 |dddf    t  t	|	dt	|	d }
n| jd
krtd||}	|dur|dur|	ddd|d|f |d	 |dddf    t  | 
|	| j| j}| }|ddddddf }
| js| jr|jddd |kddddf }|jddd |kddddf }d|
|d	 dd|< d|
|dddf d|d< | jd r|d| i |d|
i |jdi | |
| dS )a  Run forward.

        Args:
            feat_c0 (torch.Tensor): [N, L, C]
            feat_c1 (torch.Tensor): [N, S, C]
            data (dict)
            mask_c0 (torch.Tensor): [N, L] (optional)
            mask_c1 (torch.Tensor): [N, S] (optional)
        Update:
            data (dict): {
                'b_ids' (torch.Tensor): [M'],
                'i_ids' (torch.Tensor): [M'],
                'j_ids' (torch.Tensor): [M'],
                'gt_mask' (torch.Tensor): [M'],
                'mkpts0_c' (torch.Tensor): [M, 2],
                'mkpts1_c' (torch.Tensor): [M, 2],
                'mconf' (torch.Tensor): [M]}
            NOTE: M' != M during training.

        r   r      c                 s   s"    | ]}||j d  d  V  qdS )r   g      ?N)shape).0featr   r   r   	<genexpr>   s     z)CoarseMatching.forward.<locals>.<genexpr>r0   znlc,nsc->nlsN).Nr2   r   dimsparse_spvsconf_matrix_with_binconf_matrixr   )sizer/   r$   einsumr:   masked_fill_boolINFFsoftmaxr3   r?   r6   exptrainingr7   r   repeatr*   updatecloneget_coarse_match)rA   rD   rE   rF   rG   rH   _LS
sim_matrixrR   log_assign_matrixassign_matrixfilter0filter1r   r   r   forwardn   s.   ,
(
>$$
zCoarseMatching.forwardrR   c              	      s`  |d d |d d |d d |d d d}|j }|| jk}|jd }|||d |d |d |d	 }d
|vrAt|| jd nt|| jd|d
 |d  |||d |d  |d |d	  }|||jdddd k ||jdddd k }|jdd\}}t	|\}	}
||	|
f }||	|
|f }| j
r)d
|vr|dt|d|d }n	t|d
 |d }|| j }t|}t|	}| j|krd}t|||| j krtj||dntj||| j f|dtjt|d t|| | jf|d tjt|d |d} fddt|	|d g|
|d g||d g||gD \}	}
}}|	|
|d}|d d |d d  }d|v rH||d |	  n|}d|v rW||d |	  n|}tj|
|d d  |
|d d  gdd| }tj||d d  ||d d  gdd| }||dk|	|dk ||dk j|jd||dk j|jd||dk d |S )aY  Get corase matching.

        Args:
            conf_matrix (torch.Tensor): [N, L, S]
            data (dict): with keys ['hw0_i', 'hw1_i', 'hw0_c', 'hw1_c']

        Returns:
            coarse_matches (dict): {
                'b_ids' (torch.Tensor): [M'],
                'i_ids' (torch.Tensor): [M'],
                'j_ids' (torch.Tensor): [M'],
                'gt_mask' (torch.Tensor): [M'],
                'm_bids' (torch.Tensor): [M],
                'mkpts0_c' (torch.Tensor): [M, 2],
                'mkpts1_c' (torch.Tensor): [M, 2],
                'mconf' (torch.Tensor): [M]}

        hw0_cr   r   hw1_c)h0cw0ch1cw1crk   rl   rm   rn   mask0Fmask1rI   T)rO   keepdimrN   z4min-num-gt-pad should be less than num-train-matches)device	spv_b_idsc                 3   s.    | ]\}}t j| |  gd dV  qdS )r   rN   N)r$   cat)rK   xygt_pad_indicespred_indicesr   r   rM     s
    
z2CoarseMatching.get_coarse_match.<locals>.<genexpr>	spv_i_ids	spv_j_ids)b_idsi_idsj_idshw0_iscale0scale1)dtype)gt_maskm_bidsmkpts0_cmkpts1_cmconf)rr   r+   rJ   reshaper   r,   r#   r   r$   wherer[   rS   r(   r-   r   lenr.   
ValueErrorarangerandintzerosr   r&   r]   tor   )rA   rR   rF   axes_lengths_devicemaskNmask_v	all_j_idsr|   r}   r~   r   num_candidates_maxnum_matches_trainnum_matches_predmsgmconf_gtcoarse_matchesscaler   r   r   r   r   rw   r   r_      s   





"&"





..


zCoarseMatching.get_coarse_match)NN)__name__
__module____qualname__r   strr   r9   r   r   rh   r$   no_gradr_   __classcell__r   r   rB   r   r)   S   s&    

A0r)   )typingr   r   r   r   r$   torch.nn.functionalr   
functionalrX   kornia.corer   r   rW   r   floatrV   r   r#   r(   r)   r   r   r   r   <module>   s   $,