o
    oi/                     @   s  d dl Z d dlmZ d dl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 ded	ed
edefddZd%dedefddZdededeeeef fddZG dd deZ					d&dededededed edefd!d"ZG d#d$ d$eZdS )'    N)Tuple)nn)ModuleTensorconcatenateeye	normalize)KORNIA_CHECK_SHAPE)get_gaussian_kernel2dspatial_gradient)pikdkykxreturnc                 C   st   | | | }d}||kr0t tdsi t_tj}||}|du r(t|}|||< ||| ||S t||| ||S )z"Return neigh2channels conv kernel.i   
_eye_cacheN)hasattr_get_reshape_kernelr   getr   view)r   r   r   numel_MAX_CACHEDcacheres r   K/home/ubuntu/.local/lib/python3.10/site-packages/kornia/feature/siftdesc.pyr      s   

r      ksizec                 C   sB   t | d }|t|   d |   }t|||d  }|S )zReturn a weighted pooling kernel for SIFT descriptor.

    Args:
        ksize: kernel_size.

    Returns:
        the pooling kernel with shape :math:`(ksize, ksize)`.

           @g      ?   )floattorcharangeabsger)r   ks_2xc2kernelr   r   r   get_sift_pooling_kernel5   s   
r(   
patch_sizenum_spatial_binsc                 C   sl   dt | |d   }| | }|d }| d|  |d  d | d }||kr1td|  d| d|||fS )zReturn a tuple with SIFT parameters.

    Args:
        patch_size: the given patch size.
        num_spatial_bins: the ggiven number of spatial bins.

    Returns:
        ksize, stride, pad.

    r         zPatch size zC is incompatible with             requested number of spatial bins z{             for SIFT descriptor. Usually it happens when patch size is too small            for num_spatial_bins specified)int
ValueError)r)   r*   r   stridepadout_sizer   r   r   get_sift_bin_ksize_stride_padE   s    
r2   c                       s   e Zd ZdZdefddZ						dd
edededededdf fddZ	de
fddZde
fddZde
de
fddZ  ZS )SIFTDescriptoru  Module which computes SIFT descriptors of given patches.

    Args:
        patch_size: Input patch size in pixels.
        num_ang_bins: Number of angular bins.
        num_spatial_bins: Number of spatial bins.
        clipval: clipping value to reduce single-bin dominance
        rootsift: if ``True``, RootSIFT (Arandjelović et. al, 2012) is computed.

    Returns:
        SIFT descriptor of the patches with shape.

    Shape:
        - Input: :math:`(B, 1, \text{num_spatial_bins}, \text{num_spatial_bins})`
        - Output: :math:`(B, \text{num_ang_bins * num_spatial_bins ** 2})`

    Example:
        >>> input = torch.rand(23, 1, 32, 32)
        >>> SIFT = SIFTDescriptor(32, 8, 4)
        >>> descs = SIFT(input) # 23x128

    r   c                 C   s6   | j j d| j d| j d| j d| j d| j dS )N(num_ang_bins=, num_spatial_bins=z, patch_size=, rootsift=
, clipval=))	__class____name__num_ang_binsr*   r)   rootsiftclipvalselfr   r   r   __repr__u   s   
zSIFTDescriptor.__repr__)      r,   T皙?r)   r;   r*   r<   r=   Nc           	   
      s   t    d| _|| _|| _|| _|| _|| _| j}t|t	
d }t||f||fd| _t||\| _| _| _t| jd }tjdd|d|df| j| jf| j| jfdd| _| jjj|dd|d|d d S )	N绽|=r   Tr   r+   r   F)kernel_sizer/   paddingbias)super__init__epsr;   r*   r=   r<   r)   r    mathsqrtr
   gkr2   	bin_ksize
bin_strider0   r(   r   Conv2dsizepkweightdatacopy_reshape)	r?   r)   r;   r*   r<   r=   kssigmanwr9   r   r   rJ      s*   


,zSIFTDescriptor.__init__c                 C   s   | j j S N)rS   rT   detachr>   r   r   r   get_pooling_kernel   s   z!SIFTDescriptor.get_pooling_kernelc                 C   s
   | j  S r\   )rN   r]   r>   r   r   r   get_weighting_kernel   s   
z#SIFTDescriptor.get_weighting_kernelinputc                    s  t ddj j g jd }jjj_td}|d d d d df }|d d d d df }t	|| ||  j
 }t||j
 dt  }|j|||j }tj| dt  }t|}	||	 }
|	j   d j d|
 | |
| t fdd	tdjD d}||d
}t|dd}t|dtj}t|dd}jrt	t|ddj
 }|S )NB1r   diffr+   r         ?c                    :   g | ]}  |kj |kj  qS r   )rS   todtype.0ibo0_bigbo1_bigr`   r?   wo0_bigwo1_bigr   r   
<listcomp>   s    ,z*SIFTDescriptor.forward.<locals>.<listcomp>r   pg        )r	   r)   shaperS   rf   rg   devicer   r!   rM   rK   atan2r   rN   	expand_astype_asr    r;   floorr   ranger   r   clampr=   r<   )r?   r`   ra   gradsgxgymagorio_bigbo0_big_wo1_big_ang_binsr   rk   r   forward   s:   




zSIFTDescriptor.forwardrA   rB   r,   TrC   )r:   
__module____qualname____doc__strr@   r-   boolr    rJ   r   r^   r_   r   __classcell__r   r   r[   r   r3   ]   s0    !r3   rA   rB   r,   TrC   r`   r;   r<   r=   c                 C   s   t |||||| S )zdCompute the sift descriptor.

    See
    :class: `~kornia.feature.SIFTDescriptor` for details.
    )r3   )r`   r)   r;   r*   r<   r=   r   r   r   sift_describe   s   r   c                       s   e Zd ZdZdefddZ									dd
edededededededdf fddZ	de
fddZde
de
fddZ  ZS )DenseSIFTDescriptoru  Module, which computes SIFT descriptor densely over the image.

    Args:
        num_ang_bins: Number of angular bins. (8 is default)
        num_spatial_bins: Number of spatial bins per descriptor (4 is default).
    You might want to set odd number and relevant padding to keep feature map size
        spatial_bin_size: Size of a spatial bin in pixels (4 is default)
        clipval: clipping value to reduce single-bin dominance
        rootsift: (bool) if True, RootSIFT (Arandjelović et. al, 2012) is computed
        stride: default 1
        padding: default 0

    Returns:
        Tensor: DenseSIFT descriptor of the image

    Shape:
        - Input: (B, 1, H, W)
        - Output: (B, num_ang_bins * num_spatial_bins ** 2, (H+padding)/stride, (W+padding)/stride)

    Examples::
        >>> input =  torch.rand(2, 1, 200, 300)
        >>> SIFT = DenseSIFTDescriptor()
        >>> descs = SIFT(input) # 2x128x194x294

    r   c                 C   s>   | j j d| j d| j d| j d| j d| j d| j dS )Nr4   r5   z, spatial_bin_size=r6   z	, stride=r7   r8   )r9   r:   r;   r*   spatial_bin_sizer<   r/   r=   r>   r   r   r   r@      s   
zDenseSIFTDescriptor.__repr__rB   r,   TrC   r+   r;   r*   r   r<   r=   r/   rG   Nc                    s6  t    d| _|| _|| _|| _|| _|| _|| _|| _	t
| jd }| d|dd|d|d tjdd|d|dfdd|dd |dd fd	}	|	jj| j |	| _t||| }
| d
|
 tj|||d  ||f| j| jfd| j	| j	fd	}|jj| j || _| j | _d S )NrD   rE   _bin_pooling_kernel_weightr+   r   )r+   r+   Fr   )rF   r/   rH   rG   _poolingconv_weight)rI   rJ   rK   r;   r*   r   r=   r<   r/   r0   r(   r    register_bufferrW   rR   r   rQ   rT   rU   rV   r   bin_pooling_kernelr   r   PoolingConvr]   _pooling_kernel)r?   r;   r*   r   r<   r=   r/   rG   rZ   r   Pwr   r[   r   r   rJ     sD   

$


zDenseSIFTDescriptor.__init__c                 C   s   | j S r\   )r   r>   r   r   r   r^   4  s   z&DenseSIFTDescriptor.get_pooling_kernelr`   c                    s  t g d  \}}}}jjj_jjj_td}|d d d d df }|d d d d df }t	|| ||  j
 }	t||j
 dt  }
tj|
 dt  }t|}|| }|j   d j d| |	 ||	 t fddtdjD d}|}t|dd	d
dtj}t|dd	d
}jrt	t|ddj
 }|S )N)ra   rb   HWrc   r   r+   r   rd   c                    re   r   )r   rf   rg   rh   rk   r   r   rp   M  s    &z/DenseSIFTDescriptor.forward.<locals>.<listcomp>r   )dimrs   rr   )r	   rR   r   rf   rg   ru   r   r   r!   rM   rK   rv   r   r    r;   ry   r   rz   r   clamp_r=   r<   )r?   r`   _B_CH_W_Hr|   r}   r~   r   r   r   r   r   r   out_no_normoutr   rk   r   r   8  s8   





zDenseSIFTDescriptor.forward)rB   r,   r,   TrC   r+   r+   )r:   r   r   r   r   r@   r-   r   r    rJ   r   r^   r   r   r   r   r[   r   r      s:    	2r   )r   r   )rL   typingr   r!   r   kornia.corer   r   r   r   r   kornia.core.checkr	   kornia.filtersr
   r   kornia.geometry.conversionsr   r-   r   r(   r2   r3   r   r    r   r   r   r   r   r   <module>   sB    q
