a
    d+                  	   @   s   d dl Z d dlmZ d dlZd dlmZ d dlm  mZ d dl	m
Z
mZ d dlmZ d dlmZ eeeejdddZdeejd
ddZeeedddZG dd dejZdejeeeeeejdddZG dd dejZdS )    N)Tuple)get_gaussian_kernel2dspatial_gradient)pi)KORNIA_CHECK_SHAPE)kdkykxreturnc                 C   s&   | | | }t |}||| ||S )z;Utility function, which returns neigh2channels conv kernel.)torchZeyeview)r   r   r	   Znumelweight r   `/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/feature/siftdesc.py_get_reshape_kernel   s    
r      )ksizer
   c                 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      ?   )floatr   ZarangeabsZger)r   Zks_2Zxc2kernelr   r   r   get_sift_pooling_kernel   s    	r   )
patch_sizenum_spatial_binsr
   c                 C   sl   dt | |d   }| | }|d }| d|  |d  d | d }||krbt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padZout_sizer   r   r   get_sift_bin_ksize_stride_pad#   s    
 r!   c                       sh   e Zd ZdZedddZdeeeeed
d fddZ	e
jdddZe
jdddZ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   sf   | j jd d t| j d d t| j d d t| j d d t| j d d t| j d S )	N(num_ang_bins=, num_spatial_bins=zpatch_size=	rootsift=clipval=))	__class____name__strnum_ang_binsr   r   rootsiftclipvalselfr   r   r   __repr__R   sD    	
zSIFTDescriptor.__repr__)      r   T皙?N)r   r.   r   r/   r0   r
   c           	   
      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   r0   r/   r   r   mathsqrtr   gkr!   Z	bin_ksizeZ
bin_strider    r   nnConv2dsizepkr   datacopy_reshape)	r2   r   r.   r   r/   r0   kssigmanwr+   r   r   r=   g   s,    


(zSIFTDescriptor.__init__c                 C   s   | j j S N)rE   r   detachr1   r   r   r   get_pooling_kernel   s    z!SIFTDescriptor.get_pooling_kernelc                 C   s
   | j  S rM   )rA   rN   r1   r   r   r   get_weighting_kernel   s    z#SIFTDescriptor.get_weighting_kernelc                 C   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|
 | }|
| }g }td| jD ]>}| ||k|j| ||k|j|  }|| q*tj|dd}||d	}tj|d
d}t|dt| j}tj|d
d}| jrt	tj|dd| j
 }|S )NB1r   diffr   r         ?dimr   pg        )r   r   shaperE   todtypedevicer   r   r@   r>   atan2r   rA   Z	expand_asZtype_asr   r.   floorrangeappendcatr   F	normalizeclampr0   r/   )r2   inputrQ   gradsgxgymagorio_bigbo0_big_wo1_big_bo0_bigbo1_bigwo0_bigwo1_bigang_binsioutr   r   r   forward   s8    



.zSIFTDescriptor.forward)r4   r5   r   Tr6   )r,   
__module____qualname____doc__r-   r3   r   boolr   r=   r   TensorrO   rP   rv   __classcell__r   r   rL   r   r"   ;   s$        "r"   r4   r5   r   Tr6   )rf   r   r.   r   r/   r0   r
   c                 C   s   t |||||| S )z`Computes the sift descriptor.

    See :class:`~kornia.feature.SIFTDescriptor` for details.
    )r"   )rf   r   r.   r   r/   r0   r   r   r   sift_describe   s    r}   c                
       s\   e Zd ZdZedddZdeeeeeeed
d fddZ	e
jdddZ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:
        torch.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   sx   | j jd d t| j d d t| j d d t| j d d t| j d d t| j d d t| j d	 S )
Nr$   r%   r&   r'   zspatial_bin_size=r(   zstride=r)   r*   )	r+   r,   r-   r.   r   spatial_bin_sizer/   r   r0   r1   r   r   r   r3      sP    	
zDenseSIFTDescriptor.__repr__r5   r   Tr6   r   N)r.   r   r   r/   r0   r   r:   r
   c           	   
      s  t    d| _|| _|| _|| _|| _|| _|| _|| _	t
| jd }tjdd|d|dfdd|dd |dd fd| _| jjj|dd|d|d tj|||d  ||f| j| jfd| j	| j	fd| _| jjjt|||  d S )	Nr7   r8   r   r   )r   r   Fr   )r9   r   r;   r:   )r<   r=   r>   r.   r   r   r0   r/   r   r    r   r   rB   rC   rD   bin_pooling_kernelr   rF   rG   rH   PoolingConvr   )	r2   r.   r   r   r/   r0   r   r:   rK   rL   r   r   r=      s>    

(



zDenseSIFTDescriptor.__init__c                 C   s   | j j S rM   )r   r   rN   r1   r   r   r   rO     s    z&DenseSIFTDescriptor.get_pooling_kernelc                 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| |	 }||	 }g }td| jD ]>}| ||k|j| ||k|j|  }|| qtj|dd}| |}tj|ddd	dt| j}tj|ddd	}| jrt	tj|dd
| j
 }|S )N)rQ   rR   HWrS   r   r   r   rT   rU   r   )rV   rY   rX   )r   rD   r   r[   r\   r]   r   r   r   r@   r>   r^   r   r   r.   r_   r`   ra   rb   rc   rd   Zclamp_r0   r/   )r2   rf   rQ   ZCHr   r   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   rq   rr   rs   rt   ru   Zout_no_normr   r   r   rv   !  s:    


&
zDenseSIFTDescriptor.forward)r5   r   r   Tr6   r   r   )r,   rw   rx   ry   r-   r3   r   rz   r   r=   r   r{   rO   rv   r|   r   r   rL   r   r~      s*          *r~   )r   )r4   r5   r   Tr6   )r?   typingr   r   Ztorch.nnrB   Ztorch.nn.functionalZ
functionalrc   Zkornia.filtersr   r   Zkornia.geometry.conversionsr   Zkornia.testingr   r   r{   r   r   r!   Moduler"   rz   r   r}   r~   r   r   r   r   <module>   s4   z     