o
    oiTS                     @   s  d dl Z d dlmZmZ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mZmZ d dlmZ d dlmZ d dlmZ d	d
lmZ d	dlmZ d	dlmZ d	dlmZm Z m!Z!m"Z"m#Z# d	dl$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/m0Z0m1Z1 d	dl2m3Z3m4Z4m5Z5m6Z6 d	dl7m8Z8 	d2dededede9de:defddZ;G dd deZ<G d d! d!eZ=G d"d# d#e=Z>G d$d% d%e=Z?G d&d' d'e=Z@G d(d) d)e=ZAG d*d+ d+e=ZBG d,d- d-e=ZCG d.d/ d/eZDG d0d1 d1e'ZEdS )3    N)ClassVarDictListOptionalTuple)rgb_to_grayscale)pi)DeviceModuleTensorconcatenatedeg2rad)KORNIA_CHECK_LAF)ConvQuadInterp3d)ScalePyramid   )LAFAffNetShapeEstimator)HardNet)KeyNetDetector)extract_patches_from_pyramidget_laf_centerget_laf_orientationget_laf_scale	scale_laf)	LightGlue)GeometryAwareDescriptorMatcher	_no_match)LAFOrienterOriNetPassLAF)BlobDoGBlobDoGSingleBlobHessian
CornerGFTT)Detector_configMultiResolutionDetectorScaleSpaceDetectorget_default_detector_config)SIFTDescriptor    Timglafspatch_descriptor
patch_sizegrayscale_descriptorreturnc                 C   s   t | || }|  | }|jd dkr4tjd|j ddd tj|jd |jd d|j|j	dS |rA| 
ddkrAt| }t|||}|
 \}}}	}
}|||| |	|
|||d	S )
aL  Get local descriptors, corresponding to LAFs (keypoints).

    Args:
        img: image features with shape :math:`(B,C,H,W)`.
        lafs: local affine frames :math:`(B,N,2,3)`.
        patch_descriptor: patch descriptor module, e.g. :class:`~kornia.feature.SIFTDescriptor`
            or :class:`~kornia.feature.HardNet`.
        patch_size: patch size in pixels, which descriptor expects.
        grayscale_descriptor: True if ``patch_descriptor`` expects single-channel image.

    Returns:
        Local descriptors of shape :math:`(B,N,D)` where :math:`D` is descriptor size.

    r   r   zLAF contains no keypoints z, returning empty tensor)
stacklevel   )dtypedevice   )r   toevalshapewarningswarntorchemptyr2   r3   sizer   r   view)r*   r+   r,   r-   r.   timgpatchesBNCHHW rF   M/home/ubuntu/.local/lib/python3.10/site-packages/kornia/feature/integrated.pyget_laf_descriptors/   s   
$"rH   c                	       s^   e Zd ZdZ	ddee dededdf fd	d
Zde	fddZ
dededefddZ  ZS )LAFDescriptora  Module to get local descriptors, corresponding to LAFs (keypoints).

    Internally uses :func:`~kornia.feature.get_laf_descriptors`.

    Args:
        patch_descriptor_module: patch descriptor module, e.g. :class:`~kornia.feature.SIFTDescriptor`
            or :class:`~kornia.feature.HardNet`. Default: :class:`~kornia.feature.HardNet`.
        patch_size: patch size in pixels, which descriptor expects.
        grayscale_descriptor: ``True`` if patch_descriptor expects single-channel image.

    Nr)   Tpatch_descriptor_moduler-   r.   r/   c                    s0   t    |d u rtd}|| _|| _|| _d S )NT)super__init__r   
descriptorr-   r.   )selfrJ   r-   r.   	__class__rF   rG   rL   _   s   

zLAFDescriptor.__init__c                 C   s*   | j j d| j  d| j d| j dS )Nz(descriptor=z, patch_size=z, grayscale_descriptor='))rP   __name__rM   __repr__r-   r.   )rN   rF   rF   rG   rS   i   s   
zLAFDescriptor.__repr__r*   r+   c                 C   s   t ||| j| j| jS )a  Three stage local feature detection.

        First the location and scale of interest points are determined by
        detect function. Then affine shape and orientation.

        Args:
            img: image features with shape :math:`(B,C,H,W)`.
            lafs: local affine frames :math:`(B,N,2,3)`.

        Returns:
            Local descriptors of shape :math:`(B,N,D)` where :math:`D` is descriptor size.

        )rH   rM   r-   r.   )rN   r*   r+   rF   rF   rG   forwardq   s   zLAFDescriptor.forward)Nr)   T)rR   
__module____qualname____doc__r   r
   intboolrL   strrS   r   rT   __classcell__rF   rF   rO   rG   rI   R   s    
rI   c                
       sZ   e Zd ZdZddedededdf fdd	Zdd
ede	e de
eeef fddZ  ZS )LocalFeaturea  Module, which combines local feature detector and descriptor.

    Args:
        detector: the detection module.
        descriptor: the descriptor module.
        scaling_coef: multiplier for change default detector scale (e.g. it is too small for KeyNet by default)

          ?detectorrM   scaling_coefr/   Nc                    s6   t    || _|| _|dkrtd| || _d S )Nr   z!Scaling coef should be >= 0, got )rK   rL   r^   rM   
ValueErrorr_   )rN   r^   rM   r_   rO   rF   rG   rL      s   

zLocalFeature.__init__r*   maskc                 C   s2   |  ||\}}t|| j}| ||}|||fS )a  Run forward.

        Args:
            img: image to extract features with shape :math:`(B,C,H,W)`.
            mask: a mask with weights where to apply the response function.
                The shape must be the same as the input image.

        Returns:
            - Detected local affine frames with shape :math:`(B,N,2,3)`.
            - Response function values for corresponding lafs with shape :math:`(B,N,1)`.
            - Local descriptors of shape :math:`(B,N,D)` where :math:`D` is descriptor size.

        )r^   r   r_   rM   )rN   r*   ra   r+   	responsesdescsrF   rF   rG   rT      s   
zLocalFeature.forward)r]   N)rR   rU   rV   rW   r
   rI   floatrL   r   r   r   rT   r[   rF   rF   rO   rG   r\      s     	.r\   c                       sN   e Zd ZdZ					ddededed	ee d
ee ddf fddZ	  Z
S )SIFTFeaturea  Convenience module, which implements DoG detector + (Root)SIFT descriptor.

    Using `kornia.feature.MultiResolutionDetector` without blur pyramid Still not as good as OpenCV/VLFeat because of
    https://github.com/kornia/kornia/pull/884,
    but we are working on it
    @  FTNnum_featuresuprightrootsiftr3   configr/   c           	         s   d}|d u rt d}|d u rt }ttdd|||rt ntdt d|}tt	||d|dd	|}t
 || d S )
N)   cpur]   皙?   
ori_module
aff_moduler-   rj   Tr-   r.   )r;   r3   r'   r%   r!   r   r   r6   rI   r(   rK   rL   )	rN   rh   ri   rj   r3   rk   r-   r^   rM   rO   rF   rG   rL      s(   
zSIFTFeature.__init__)rg   FTNNrR   rU   rV   rW   rX   rY   r   r	   r$   rL   r[   rF   rF   rO   rG   rf      s(    	rf   c                       sD   e Zd ZdZ				ddededed	ee d
df
 fddZ  Z	S )SIFTFeatureScaleSpacea  Convenience module, which implements DoG detector + (Root)SIFT descriptor.

    Using `kornia.feature.ScaleSpaceDetector` with blur pyramid.

    Still not as good as OpenCV/VLFeat because of https://github.com/kornia/kornia/pull/884, but we are working on it
    rg   FTNrh   ri   rj   r3   r/   c              
      s   |d u r	t d}d}t|t tdtddddd|rt ntd	ddd
d|}t	t
||d|dd|}t || d S )Nrm   rl   
   r4   rn   r)   T)double_imagero   g      @)resp_module
nms_modulescale_pyr_modulerq   scale_space_responseminima_are_also_goodmr_sizers   rt   )r;   r3   r&   r    r   r   r   r   r6   rI   r(   rK   rL   )rN   rh   ri   rj   r3   r-   r^   rM   rO   rF   rG   rL      s*   
	
zSIFTFeatureScaleSpace.__init__)rg   FTN)
rR   rU   rV   rW   rX   rY   r   r	   rL   r[   rF   rF   rO   rG   rv      s"    	rv   c                       H   e Zd ZdZ				ddededee dee d	df
 fd
dZ	  Z
S )GFTTAffNetHardNetOConvenience module, which implements GFTT detector + AffNet-HardNet descriptor.rg   FNrh   ri   r3   rk   r/   c                    v   |d u r	t d}|d u rt }tt |||rt ntdtd d	|}t
d ddd	|}t || d S Nrm   ro   Trp   r)   rt   )r;   r3   r'   r%   r#   r   r   r   r7   r6   rI   rK   rL   rN   rh   ri   r3   rk   r^   rM   rO   rF   rG   rL         

zGFTTAffNetHardNet.__init__)rg   FNNru   rF   rF   rO   rG   r      "    r   c                       r   )HesAffNetHardNetr      FNrh   ri   r3   rk   r/   c                    r   r   )r;   r3   r'   r%   r"   r   r   r   r7   r6   rI   rK   rL   r   rO   rF   rG   rL     r   zHesAffNetHardNet.__init__)r   FNNru   rF   rF   rO   rG   r     r   r   c                       D   e Zd ZdZ				ddededee d	ed
df
 fddZ	  Z
S )KeyNetHardNetzJConvenience module, which implements KeyNet detector + HardNet descriptor.rg   FNr]   rh   ri   r3   r   r/   c                    sf   |d u r	t d}|rt nttdd}td||d|}td ddd|}t 	||| d S )Nrm   Tangle_detector)rh   rq   r)   rt   )
r;   r3   r   r   r   r   r6   rI   rK   rL   rN   rh   ri   r3   r   rq   r^   rM   rO   rF   rG   rL   !  s   
zKeyNetHardNet.__init__rg   FNr]   rR   rU   rV   rW   rX   rY   r   r	   re   rL   r[   rF   rF   rO   rG   r     s"    r   c                       r   )KeyNetAffNetHardNetzConvenience module, which implements KeyNet detector + AffNet + HardNet descriptor.

    .. image:: _static/img/keynet_affnet.jpg
    rg   FNr]   rh   ri   r3   r   r/   c                    sp   |d u r	t d}|rt nttdd}td||td d|}t	d ddd|}t
 ||| d S )Nrm   Tr   )rh   rq   rr   r)   rt   )r;   r3   r   r   r   r   r   r7   r6   rI   rK   rL   r   rO   rF   rG   rL   6  s   
zKeyNetAffNetHardNet.__init__r   r   rF   rF   rO   rG   r   0  s"    r   c                	       s   e Zd ZdZdededdf fddZdded	ee dee	ef fd
dZ
dedejdee	ef fddZdee	ef dee	ef fddZ  ZS )LocalFeatureMatchera  Module, which finds correspondences between two images based on local features.

    Args:
        local_feature: Local feature detector. See :class:`~kornia.feature.GFTTAffNetHardNet`.
        matcher: Descriptor matcher, see :class:`~kornia.feature.DescriptorMatcher`.

    Returns:
        Dict[str, Tensor]: Dictionary with image correspondences and confidence scores.

    Example:
        >>> img1 = torch.rand(1, 1, 320, 200)
        >>> img2 = torch.rand(1, 1, 128, 128)
        >>> input = {"image0": img1, "image1": img2}
        >>> gftt_hardnet_matcher = LocalFeatureMatcher(
        ...     GFTTAffNetHardNet(10), kornia.feature.DescriptorMatcher('snn', 0.8)
        ... )
        >>> out = gftt_hardnet_matcher(input)

    local_featurematcherr/   Nc                    s"   t    || _|| _|   d S rd   )rK   rL   r   r   r7   )rN   r   r   rO   rF   rG   rL   \  s   
zLocalFeatureMatcher.__init__imagera   c                 C   s   |  ||\}}}|||dS )z#Extract features from simple image.)r+   rb   descriptors)r   )rN   r   ra   lafs0resps0descs0rF   rF   rG   extract_featuresb  s   z$LocalFeatureMatcher.extract_featuresr3   r2   c                 C   sl   t jdd||dt jdd||dt jdddd||dt jdddd||dt jd||dt jd|t jddS )Nr      r3   r2   r4   
keypoints0
keypoints1r   lafs1
confidencebatch_indexes)r;   r<   long)rN   r3   r2   rF   rF   rG   no_match_outputg  s   z#LocalFeatureMatcher.no_match_outputdatac              	   C   sX  |d j d }d| vsd| vr$| |d }|d |d }}n	|d |d }}d| vs9d| vrJ| |d	 }|d |d }}n	|d |d }}t|}	t|}
g }g }g }g }g }g }t|D ]s}| || || \}}t|dkrqk|	||d
d
df f }|
||d
d
df f }|||d
d
df f }|||d
d
df f }|d|  |tj	t||	j
tjd }|| || || || || qkt|dkr| |d j
|d jS t|ddddt|ddddt|ddddddt|ddddddt|dddt|ddddS )a  Run forward.

        Args:
            data: dictionary containing the input data in the following format:

        Keyword Args:
            image0: left image with shape :math:`(N, 1, H1, W1)`.
            image1: right image with shape :math:`(N, 1, H2, W2)`.
            mask0 (optional): left image mask. '0' indicates a padded position :math:`(N, H1, W1)`.
            mask1 (optional): right image mask. '0' indicates a padded position :math:`(N, H2, W2)`.

        Returns:
            - ``keypoints0``, matching keypoints from image0 :math:`(NC, 2)`.
            - ``keypoints1``, matching keypoints from image1 :math:`(NC, 2)`.
            - ``confidence``, confidence score [0, 1] :math:`(NC)`.
            - ``lafs0``, matching LAFs from image0 :math:`(1, NC, 2, 3)`.
            - ``lafs1``, matching LAFs from image1 :math:`(1, NC, 2, 3)`.
            - ``batch_indexes``, batch indexes for the keypoints and lafs :math:`(NC)`.

        image0r   r   descriptors0r+   r   r   descriptors1image1Nr   r]   r   dimr5   r   r4   r   )r8   keysr   r   ranger   lenappendr;   onesr3   r   r   r2   r   r>   )rN   r   num_image_pairsfeats_dict0r   r   feats_dict1r   descs1r   r   out_keypoints0out_keypoints1out_confidenceout_batch_indexes	out_lafs0	out_lafs1	batch_idxdistsidxscurrent_keypoints_0current_keypoints_1current_lafs_0current_lafs_1
batch_idxsrF   rF   rG   rT   q  sR   



zLocalFeatureMatcher.forwardrd   )rR   rU   rV   rW   r
   rL   r   r   r   rZ   r   r	   r;   r2   r   rT   r[   rF   rF   rO   rG   r   G  s    $ *
r   c                       s   e Zd ZU dZg dZeee  ed< ddede	e
 dd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ef fddZ  ZS )LightGlueMatcheraC  LightGlue-based matcher in kornia API.

    This is based on the original code from paper "LightGlue: Local Feature Matching at Light Speed".
    See :cite:`LightGlue2023` for more details.

    Args:
        feature_name: type of feature for matching, can be `disk` or `superpoint`.
        params: LightGlue params.

    )	alikeddedodebdedodegdiskdog_affnet_hardnet
doghardnetkeynet_affnet_hardnetsift
superpointknown_modesr   Nfeature_nameparamsr/   c                    sD   |  }t | || _|d u ri }|| _t| jfi || _d S rd   )lowerrK   rL   r   r   r   r   )rN   r   r   feature_name_rO   rF   rG   rL     s   zLightGlueMatcher.__init__desc1desc2r   lafs2hw1hw2c              
   C   s  |j d dk s|j d dk rt|S t|}t|}t|j dkr&|d}t|j dkr2|d}|j}	|du rG|jddd  d}
nt	j
||	d}
|du r`|jddd  d}nt	j
||	d}tt|dd}||dk   dt 7  < tt|dd}||dk   dt 7  < |t|dd||||
ddd|	d	||t|dd|||ddd|	d
d}| |}|d |d }}|dk}t	t	|d || gd}|| dd|fS )ak  Run forward.

        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)`.
            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 of :math:`(B3, 2)` where :math:`0 <= B3 <= B1`.

        r   r   Nr   r   )r3   r5   g       @)	keypointsscalesorisr+   r   
image_size)r   r+   r   r   r   r   )r   r   matches0matching_scores0)r8   r   r   r   	unsqueezer3   maxsqueezeflipr;   tensorr   r   reshaper   r   r6   r   stackwhere)rN   r   r   r   r   r   r   r   
keypoints2devhw1_hw2_ori0ori1
input_dictpredr   mscores0validmatchesrF   rF   rG   rT     sN   

	
zLightGlueMatcher.forward)r   N)NN)rR   rU   rV   rW   r   r   r   rZ   __annotations__r   r   rL   r   r   rX   rT   r[   rF   rF   rO   rG   r     s*   
  
r   )r)   T)Fr9   typingr   r   r   r   r   r;   kornia.colorr   kornia.constantsr   kornia.corer	   r
   r   r   r   kornia.core.checkr   kornia.geometry.subpixr   kornia.geometry.transformr   affine_shaper   hardnetr   keynetr   lafr   r   r   r   r   	lightgluer   matchingr   r   orientationr   r   r   rb   r    r!   r"   r#   scale_space_detectorr$   r%   r&   r'   siftdescr(   rX   rY   rH   rI   r\   rf   rv   r   r   r   r   r   r   rF   rF   rF   rG   <module>   sV   
#0&""w