o
    oiJ                     @   sX  U d dl Z d dl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mZ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  dd
l!m"Z" ddl#m$Z$ dedede%defddZ&dedee% defddZ'G dd deZ(G dd deZ)de)fddZ*G dd deZ+ddde ,d d!d"Z-e)e.d#< dS )$    N)ListOptionalTuple)	TypedDict)DeviceModuleTensorconcatenateeyetensorwherezeros)KORNIA_CHECK_SHAPE)ConvSoftArgmax3dNonMaximaSuppression2d)ScalePyramidpyrdownresize   )laf_from_center_scale_orilaf_is_inside_image)PassLAF)BlobHessian
max_coordssigmas
num_levelsreturnc                 C   s|   | j \}}}| dddddf  dddd}t|d td|t| ||d | ddddddf gd}|S )ac  Auxiliary function for ScaleSpaceDetector.

    Converts scale level index from ConvSoftArgmax3d to the actual
    scale, using the sigmas from the ScalePyramid output.

    Args:
        max_coords: tensor [BxNx3].
        sigmas: tensor [BxNxD], D >= 1
        num_levels: number of levels in the scale index.

    Returns:
        tensor [BxNx3].

    Nr   r   )r   r   g       @   )shape
contiguousviewr	   torchpowfloat)r   r   r   BN_scale_coordsout r*   W/home/ubuntu/.local/lib/python3.10/site-packages/kornia/feature/scale_space_detector.py_scale_index_to_scale#   s   &@r,   maskoctave_shapec                 C   s(   |dd }t j| |ddd}|dS )z2Downsample a mask based on the given octave shape.NbilinearF)modealign_cornersr   )Finterpolate	unsqueeze)r-   r.   
mask_shapemask_octaver*   r*   r+   _create_octave_maskA   s   
r8   c                       s   e Zd ZdZ									ddededee d	ee d
ee dee dee dededdf fddZ	de
fddZddededee deeef fddZddedee deeef fddZ  ZS )ScaleSpaceDetectora  Module for differentiable local feature detection.

    As close as possible to classical local feature detectors
    like Harris, Hessian-Affine or SIFT (DoG).

    It has 5 modules inside: scale pyramid generator, response ("cornerness") function,
    soft nms function, affine shape estimator and patch orientation estimator.
    Each of those modules could be replaced with learned custom one, as long, as
    they respect output shape.

    Args:
        num_features: Number of features to detect. In order to keep everything batchable,
          output would always have num_features output, even for completely homogeneous images.
        mr_size: multiplier for local feature scale compared to the detection scale.
          6.0 is matching OpenCV 12.0 convention for SIFT.
        scale_pyr_module: generates scale pyramid. See :class:`~kornia.geometry.ScalePyramid` for details.
          Default: ScalePyramid(3, 1.6, 10).
        resp_module: calculates ``'cornerness'`` of the pixel.
        nms_module: outputs per-patch coordinates of the response maxima.
          See :class:`~kornia.geometry.ConvSoftArgmax3d` for details.
        ori_module: for local feature orientation estimation. Default:class:`~kornia.feature.PassLAF`,
           which does nothing. See :class:`~kornia.feature.LAFOrienter` for details.
        aff_module: for local feature affine shape estimation. Default: :class:`~kornia.feature.PassLAF`,
            which does nothing. See :class:`~kornia.feature.LAFAffineShapeEstimator` for details.
        minima_are_also_good: if True, then both response function minima and maxima are detected
            Useful for symmetric response functions like DoG or Hessian. Default is False

            @NFnum_featuresmr_sizescale_pyr_moduleresp_module
nms_module
ori_module
aff_moduleminima_are_also_goodscale_space_responser   c
           
         s   t    || _|| _|d u rtddd}|| _|d u rt }|| _|d u r/tdddddd}|| _	|d u r9t
 }|| _|d u rCt
 }|| _|| _|	| _d S )	N   g?   )rE   rE   rE   )r   r   r   FT)normalized_coordinatesoutput_value)super__init__r=   r<   r   	scale_pyrr   respr   nmsr   oriaffrC   rD   )
selfr<   r=   r>   r?   r@   rA   rB   rC   rD   	__class__r*   r+   rJ   f   s,   


zScaleSpaceDetector.__init__c                 C   sZ   | j j d| j d| j d| j  d| j  d| j  d| j  d| j	  dS )	Nz(num_features=z
, mr_size=z, scale_pyr=z, resp=z, nms=z, ori=z, aff=))
rR   __name__r<   r=   rK   __repr__rL   rM   rN   rO   )rP   r*   r*   r+   rU      s    
zScaleSpaceDetector.__repr__img	num_featsr-   c           '   
   C   s~  |j }|j}| |\}}}g }	g }
| jjrdnd}t|D ]t\}}|| }| \}}}}}| jr=| ||d}nD| |	ddddd
|| ||||d|||||}|	ddddd}t| jjtr| jjd dkr|d d d d d df }|d urt||j}|| }| |\}}| jr| | \}}||k|j}|| d| |  }||d d|d |  }||dd}||ddd	ddd}|d|krtj||dd	\}}t|d|dddd}n|}|}| \}} t| jjtrt| jj }!nt| jjtr$| jj}!ntd
t| jj t|||!}td||ddddd}"t| j |d d d d df || dd |" |d d d d ddf || ddgd}#t!|#|d d df }$||$|| }|#|9 }#|	"| |
"|# |d9 }qt|	d}%t|
d}&tj|%|dd	\}%}t|&d|dddddd}&|%|&fS )N      ?      ?r   r   r   r   rE      kdimzOExpected the scale pyramid module to have `n_levels` as a Tensor or int.Gotcha )dtypedevice)#r_   r^   rK   double_image	enumeratesizerD   rL   r!   permutereshape
isinstanceextra_levelsr   r8   r   rM   rC   tor5   r"   topkgatherrepeatn_levelsintitem	TypeErrortyper,   r
   r	   r=   r   append)'rP   rV   rW   r-   devr^   spr   r'   all_responsesall_lafspx_sizeoct_idxoctave
sigmas_octr%   CHLHWoct_respoct_mask	coord_maxresponse_max	coord_minresponse_mintake_min_maskresponses_flattenmax_coords_flattenresp_flat_bestidxsmax_coords_bestr&   r   rotmatcurrent_lafs	good_mask	responseslafsr*   r*   r+   detect   s|   0
  

*$	




&zScaleSpaceDetector.detectc                 C   s4   |  || j|\}}| ||}| ||}||fS )a6  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 to extract features with shape [BxCxHxW]
            mask: a mask with weights where to apply the response function. The shape must be the same as
              the input image.

        Returns:
            lafs: shape [BxNx2x3]. Detected local affine frames.
            responses: shape [BxNx1]. Response function values for corresponding lafs

        )r   r<   rO   rN   rP   rV   r-   r   r   r*   r*   r+   forward   s   zScaleSpaceDetector.forward)	r:   r;   NNNNNFFN)rT   
__module____qualname____doc__rl   r$   r   r   boolrJ   strrU   r   r   r   r   __classcell__r*   r*   rQ   r+   r9   H   sF    	
%(,\r9   c                   @   s6   e Zd ZU eed< eed< eed< eed< eed< dS )Detector_confignms_sizepyramid_levels	up_levelsscale_factor_levelss_multN)rT   r   r   rl   __annotations__r$   r*   r*   r*   r+   r   	  s   
 r   c                   C   s   t  S )zReturn default config.)_DEFAULT_DETECTOR_CONFIGcopyr*   r*   r*   r+   get_default_detector_config  s   r   c                       s   e Zd ZdZ				ddededee dee dee d	df fd
dZdde	ded	e	fddZ
de	dedeeef d	ee	e	f fddZdde	dee	 d	ee	e	f fddZdde	dee	 d	ee	e	f fddZ  ZS )MultiResolutionDetectora  Multi-scale feature detector, based on code from KeyNet. Can be used with any response function.

    This is based on the original code from paper
    "Key.Net: Keypoint Detection by Handcrafted and Learned CNN Filters".
    See :cite:`KeyNet2019` for more details.

    Args:
        model: response function, such as KeyNet or BlobHessian
        num_features: Number of features to detect.
        conf: Dict with initialization parameters. Do not pass it, unless you know what you are doing`.
        ori_module: for local feature orientation estimation. Default: :class:`~kornia.feature.PassLAF`,
           which does nothing. See :class:`~kornia.feature.LAFOrienter` for details.
        aff_module: for local feature affine shape estimation. Default: :class:`~kornia.feature.PassLAF`,
            which does nothing. See :class:`~kornia.feature.LAFAffineShapeEstimator` for details.

       Nmodelr<   configrA   rB   r   c                    s   t    || _|d u rt }|d | _|d | _|d | _|d | _|d | _t	| j| jf| _
|| _|d u r=t | _n|| _|d u rJt | _d S || _d S )Nr   r   r   r   r   )rI   rJ   r   r   num_pyramid_levelsnum_upscale_levelsr   r=   r   r   rM   r<   r   rN   rO   )rP   r   r<   r   rA   rB   rQ   r*   r+   rJ   )  s"   







z MultiResolutionDetector.__init__rF   	score_mapbordersc                 C   s6   t |}d|dddd|| || f< || S )zCRemove the borders of the image to avoid detections on the corners.r   N)r"   
zeros_like)rP   r   r   r-   r*   r*   r+   remove_bordersH  s   
$z&MultiResolutionDetector.remove_borders	level_imgnum_kpfactorc              
   C   s  |  | | |}|j}|j}| d d dd f  }|dd|d |d f }tj|dd\}	}
|
t	|	dk }
|d d |
d | f  }t
|}|d|ddt|||d }d|d |d   }|| j tjd|dd||d }t||td|d||d}|	d | |fS )	Nr   r   r   T)
descending        )r_   r^   rX   )rM   r   r   r_   r^   nonzerotr"   sortr   lenr!   flipr   r=   onesr   r   )rP   r   r   r   det_mapr_   r^   yxscoresscores_sortedindicescurrent_kp_numxy_projectedscale_factorscaler   r*   r*   r+   detect_features_on_single_levelN  s   " z7MultiResolutionDetector.detect_features_on_single_levelrV   r-   c              
      s  g  d| j d }| j| j d }t|D ]}|d|| j   7 | j|d|| j    } | qfdd D  |j\}}}}	|}
|}g }g }t| jD ]Z} t | j d |d   }t|}| j d|  }t|| t|	| }}t	|	t	| t	|t	| f}t
|
||fddd	}
| |
||\}}||dd || qQt| jd D ]k}|d
krt|| j d}|j\}}}}t	|	t	| t	|t	| f}nd}t | }|d
ks| jd
kr fddtd
|d | j D }t|  }t|}| |||\}}||dd || qt|d}t|d}|jd | jkrLtj|| jdd\}}t|d|d dddd}||fS )Nr   r   r   r   c                    s   g | ]}t |  qS r*   )rl   ).0x)tmpr*   r+   
<listcomp>l  s    z2MultiResolutionDetector.detect.<locals>.<listcomp>r0   F)interpolationr2   r   )r   )rY   rY   c                    s   g | ]} | qS r*   r*   )r   a)num_features_per_levelr*   r+   r     s    r[   ).NNrE   )r   r   r   ranger<   rp   r   r   rl   r$   r   r   r!   r   r   sumrm   r	   r"   rh   ri   expand)rP   rV   r-   factor_pointslevels	idx_levelnfr'   hwimg_upcur_imgrs   rt   num_points_level	up_factornhnwup_factor_kpts
cur_scorescur_lafsr   nf2
res_pointsr   r   r   r*   )r   r   r+   r   b  sX   
 ""

zMultiResolutionDetector.detectc                 C   s>   t |g d | ||\}}| ||}| ||}||f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 to extract features with shape [1xCxHxW]. KeyNetDetector does not support batch processing,
        because the number of detections is different on each image.
            mask: a mask with weights where to apply the response function. The shape must be the same as
              the input image.

        Returns:
            lafs: shape [1xNx2x3]. Detected local affine frames.
            responses: shape [1xNx1]. Response function values for corresponding lafs

        )1Cr{   r|   )r   r   rO   rN   r   r*   r*   r+   r     s
   zMultiResolutionDetector.forward)r   NNN)rF   r   )rT   r   r   r   r   rl   r   r   rJ   r   r   r   r$   r   r   r   r   r*   r*   rQ   r+   r     s>    


$,:r   rF   rZ   r   g      6@)r   r   r   r   r   r   )/mathtypingr   r   r   r"   torch.nn.functionalnn
functionalr3   typing_extensionsr   kornia.corer   r   r   r	   r
   r   r   r   kornia.core.checkr   kornia.geometry.subpixr   r   kornia.geometry.transformr   r   r   lafr   r   orientationr   r   r   rl   r,   r8   r9   r   r   r   sqrtr   r   r*   r*   r*   r+   <module>   s4   
( B  