a
    d/                  
   @   sH  U 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	  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ddddde dddiZi Zeeef ed< ded< G dd de	jZG dd de	jZG dd de	j Z!d#e"e"e"e"e"e"dddZ#G dd  d e	jZ$G d!d" d"e	jZ%dS )$    N)CallableDictListOptionalTuple)Tensor)SpatialGradient)NonMaximaSuppression2d)pyrdown   )laf_from_center_scale_ori)PassLAFKeyNet_default_config                     )num_filters
num_levelskernel_sizenms_sizepyramid_levels	up_levelsscale_factor_levelss_multurlszXhttps://github.com/axelBarroso/Key.Net-Pytorch/raw/main/model/weights/keynet_pytorch.pthkeynetc                       s0   e Zd ZdZ fddZeedddZ  ZS )_FeatureExtractorzVHelper class for KeyNet.

    It loads both, the handcrafted and learnable blocks
    c                    s   t    t | _t | _d S N)super__init___HandcraftedBlockhc_block_LearnableBlocklb_blockself	__class__ ^/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/feature/keynet.pyr#   )   s    
z_FeatureExtractor.__init__xreturnc                 C   s   |  |}| |}|S r!   )r%   r'   )r)   r/   Zx_hcZx_lbr,   r,   r-   forward/   s    

z_FeatureExtractor.forward__name__
__module____qualname____doc__r#   r   r1   __classcell__r,   r,   r*   r-   r    #   s   r    c                       s0   e Zd ZdZ fddZeedddZ  ZS )r$   zaHelper class for KeyNet, it defines the handcrafted filters within the Key.Net handcrafted block.c                    s   t    tdd| _d S )Nsobelr   )r"   r#   r   spatial_gradientr(   r*   r,   r-   r#   8   s    
z_HandcraftedBlock.__init__r.   c                 C   s  |  |}|d d 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 f |d d d d dd d d d f  }}|  |}|d d d d dd d d d f }	tj|||d |d || ||d ||	||	 g
dd}
|
S )Nr   r   g       @dim)r9   torchcat)r)   r/   r8   ZdxZdyZsobel_dxZdxxZdxyZsobel_dyZdyyZhc_featsr,   r,   r-   r1   <   s    
F
F
"6z_HandcraftedBlock.forwardr2   r,   r,   r*   r-   r$   5   s   r$   c                       s8   e Zd ZdZd	ed fddZeedddZ  ZS )
r&   zUHelper class for KeyNet.

    It defines the learnable blocks within the Key.Net
    
   )in_channelsc                    s(   t    t|| _t | _t | _d S r!   )r"   r#   _KeyNetConvBlockconv0conv1conv2)r)   r?   r*   r,   r-   r#   R   s    

z_LearnableBlock.__init__r.   c                 C   s   |  | | |}|S r!   )rC   rB   rA   )r)   r/   r,   r,   r-   r1   Y   s    z_LearnableBlock.forward)r>   )	r3   r4   r5   r6   intr#   r   r1   r7   r,   r,   r*   r-   r&   L   s   r&   r?   out_channelsr   ZstridepaddingZdilationc              
   C   s,   t t | |||||t |t jddS )zWHelper function for KeyNet.

    Default learnable convolutional block for KeyNet.
    TZinplace)nn
SequentialConv2dZBatchNorm2dReLUrE   r,   r,   r-   r@   ^   s
    
r@   c                       sB   e Zd ZdZded feed fddZeeddd	Z	  Z
S )
KeyNeta7  Key.Net model definition -- local feature detector (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:
        pretrained: Download and set pretrained weights to the model.
        keynet_conf: Dict with initiliazation parameters. Do not pass it, unless you know what you are doing`.

    Returns:
        KeyNet response score.

    Shape:
        - Input: :math:`(B, 1, H, W)`
        - Output: :math:`(B, 1, H, W)`
    Fr   )
pretrainedkeynet_confc                    s   t    |d }|d | _|d }|d }t | _ttj|| j d||dtjdd| _	|rd	d
 }t
jjtd |d}| j|d dd |   d S )Nr   r   r   r   r   )r?   rF   r   rG   TrH   c                 S   s   | S r!   r,   )Zstoragelocr,   r,   r-   <lambda>       z!KeyNet.__init__.<locals>.<lambda>r   )Zmap_locationZ
state_dict)strict)r"   r#   r   r    feature_extractorrI   rJ   rK   rL   	last_convr<   ZhubZload_state_dict_from_urlr   Zload_state_dicteval)r)   rN   rO   r   r   rG   Zstorage_fcnZpretrained_dictr*   r,   r-   r#      s"    


zKeyNet.__init__r.   c                 C   sx   |j }| |g}td| jD ]@}t|dd}| |}tj||d |d fdd}|| q| t	j
|dd}|S )	z!
        x - input image
        r   g333333?factorr   r   bilinear)sizemoder:   )shaperT   ranger   r
   FinterpolateappendrU   r<   r=   )r)   r/   Zshape_imZfeatsiZfeats_iscoresr,   r,   r-   r1      s    
zKeyNet.forward)r3   r4   r5   r6   keynet_configboolr   r#   r   r1   r7   r,   r,   r*   r-   rM   q   s   rM   c                       s   e Zd ZdZdded e e feeee	j
e	j
d fddZded	d
dZeeeeef eeef dddZdeee eeef dddZdeee eeef dddZ  ZS )KeyNetDetectoraZ  Multi-scale feature detector based on KeyNet.

    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:
        pretrained: Download and set pretrained weights to the model.
        num_features: Number of features to detect.
        keynet_conf: Dict with initiliazation 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.
    Fi   r   )rN   num_featuresrO   
ori_module
aff_modulec                    sp   t    t||| _|d | _|d | _|d | _|d | _|d | _t	| j| jf| _
|| _|| _|| _d S )Nr   r   r   r   r   )r"   r#   rM   modelnum_pyramid_levelsnum_upscale_levelsr   mr_sizer   r	   nmsrf   oriaff)r)   rN   rf   rO   rg   rh   r*   r,   r-   r#      s    





zKeyNetDetector.__init__r   )bordersc                 C   s6   t |}d|dddd|| || f< || S )zGIt removes the borders of the image to avoid detections on the corners.r   N)r<   Z
zeros_like)r)   Z	score_maprp   maskr,   r,   r-   remove_borders   s    
$zKeyNetDetector.remove_borders)	level_imgnum_kprX   r0   c              
   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j|||d }d|d |d   }|| j tjd|dd||d }t||tjd|d||d}|	d | |fS )	Nr   r   r   T)Z
descending        )devicedtypeg      ?)rm   rr   ri   rv   rw   Znonzerotr<   sortwherelenviewZflipZtensorrl   Zonesr   zeros)r)   rs   rt   rX   Zdet_maprv   rw   Zyxrb   Zscores_sortedindicesZcurrent_kp_numZxy_projectedZscale_factorZscalelafsr,   r,   r-   detect_features_on_single_level   s     $ z.KeyNetDetector.detect_features_on_single_levelN)imgrq   r0   c              
      s  g  d| j d }| j| j d }t|D ]<}|d|| j   7 | j|d|| j    } | q*ttfdd  |j\}}}}	|}
|}g }g }t| jD ]} t	 | j d |d   }t
|}| j d|  }t
|| t
|	|  }}t|	t| t|t| f}tj|
||fddd	}
| |
||\}}||dd || qt| jd D ]}|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 || qltj|dd}tj|dd}|jd | jkrtj|| jdd\}}t|d|dddddd}||fS )Nru   r   r   c                    s   t |   S r!   )rD   )r/   )tmpr,   r-   rQ      rR   z'KeyNetDetector.detect.<locals>.<lambda>rY   F)r[   Zalign_cornersr   rW   )      ?r   c                    s   g | ]} | qS r,   r,   ).0a)num_features_per_levelr,   r-   
<listcomp>  rR   z)KeyNetDetector.detect.<locals>.<listcomp>r:   )kr;   r   )r   rj   rk   r]   rf   r`   listmapr\   r{   rD   floatr^   r_   r   r|   r
   r   sumitemr<   r=   ZtopkZgatherZ	unsqueezerepeat)r)   r   rq   Zfactor_pointslevelsZ	idx_levelnf_hwZimg_upZcur_imgZall_responsesZall_lafsZnum_points_levelZ	up_factorZnhnwZup_factor_kptsZ
cur_scoresZcur_lafsrX   Znf2Z
res_points	responsesr   Zidxsr,   )r   r   r-   detect   sX    
 
""&zKeyNetDetector.detectc                 C   sF   |j d dkrt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
        r   r   z'KeyNet supports only single-image input)r\   
ValueErrorr   ro   rn   )r)   r   rq   r   r   r,   r,   r-   r1   %  s    zKeyNetDetector.forward)r   )N)N)r3   r4   r5   r6   rc   r   rd   rD   r   rI   Moduler#   rr   r   r   r   r   r   r   r1   r7   r,   r,   r*   r-   re      s6   
 
= 
re   )r   r   r   r   r   r   )&mathtypingr   r   r   r   r   r<   Ztorch.nnrI   Ztorch.nn.functionalZ
functionalr^   r   Zkornia.filtersr   Zkornia.geometry.subpixr	   Zkornia.geometry.transformr
   Zlafr   Zorientationr   sqrtrc   r   str__annotations__r   r    r$   rJ   r&   rD   r@   rM   re   r,   r,   r,   r-   <module>   sT   
      6