a
    d%                     @   s   U d dl Z d dl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mZ d dlmZ d dlmZmZ ddlmZmZm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G dd dejZ dS )    N)CallableDictOptional)pi)SpatialGradientget_gaussian_kernel2d)rad2deg)KORNIA_CHECK_LAFKORNIA_CHECK_SHAPE   )extract_patches_from_pyramidget_laf_orientationset_laf_orientationurlszEhttps://github.com/ducha-aiki/affnet/raw/master/pretrained/OriNet.pthorinetc                   @   s(   e Zd ZdZejejejdddZdS )PassLAFzSDummy module to use instead of local feature orientation or affine shape estimator.lafimgreturnc                 C   s   |S )z
        Args:
            laf: 4d tensor.
            img: the input image tensor.

        Return:
            torch.Tensor: unchanged laf from the input. )selfr   r   r   r   c/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/feature/orientation.pyforward   s    zPassLAF.forwardN)__name__
__module____qualname____doc__torchTensorr   r   r   r   r   r      s   r   c                       sH   e Zd ZdZdeeed fddZdd	 Zej	ej	d
ddZ
  ZS ) PatchDominantGradientOrientationa'  Module, which estimates the dominant gradient orientation of the given patches, in radians.

    Zero angle points towards right.

    Args:
        patch_size: size of the (square) input patch.
        num_angular_bins: number of histogram bins.
        eps: for safe division, and arctan.
        $   :0yE>)
patch_sizenum_angular_binsepsc                    s   t    || _|| _tdd| _|| _tjddddddd| _	t
 . t
g dgg| j	jd d < W d    n1 s|0    Y  t| jtd }t| j| jf||fd	| _d S )
NZsobelr      FZcircular)kernel_sizepaddingbiasZpadding_mode)Q?g(\?r+          @T)super__init__r$   num_ang_binsr   gradientr&   nnZConv1dangular_smoothr   Zno_gradZtensorZweightfloatmathsqrtr   	weighting)r   r$   r%   r&   sigma	__class__r   r   r.   ,   s    

<z)PatchDominantGradientOrientation.__init__c                 C   s>   | j jd t| j d d t| j d d t| j d S )N(patch_size=, znum_ang_bins=zeps=))r9   r   strr$   r/   r&   r   r   r   r   __repr__8   s$    
	z)PatchDominantGradientOrientation.__repr__patchr   c                 C   s.  t |tjstdt| t|jdks<td|j | \}}}}|| j	ksh|| j	ksh|dkrtd
| j	| j	| | j|j|j| _| j|j|j| _| |}|dddddf }|dddddf }t|| ||  | j }	t||| j dt  }
t| j|
d	t   dt  }t|}|| }|| j }|d | j }d	| |	 }||	 }g }td| jD ]@}t||k|j| ||k|j|  d
}|| qt|ddd| j}| |}|d| jd\}}dt ||j t| j t  }|S )zcArgs:
            patch: shape [Bx1xHxW]
        Returns:
            torch.Tensor: angle shape [B]z&Input type is not a torch.Tensor. Got    z-Invalid input shape, we expect Bx1xHxW. Got: r   z1input shape should be must be [Bx1x{}x{}]. Got {}Nr   r,   g      ?)r   r   )
isinstancer   r   	TypeErrortypelenshape
ValueErrorsizer$   formatr6   toZdtypeZdevicer2   r0   r5   r&   atan2r   r3   r/   floorrangeFZadaptive_avg_pool2dappendcatviewmax)r   rA   _ZCHWHZgradsZgxgyZmagZoriZo_bigZbo0_bigZwo1_bigZbo1_bigZwo0_bigZang_bins_listiZ
ang_bins_iZang_binsvaluesindicesangler   r   r   r   F   sH    


(
$z(PatchDominantGradientOrientation.forward)r!   r"   r#   )r   r   r   r   intr3   r.   r?   r   r   r   __classcell__r   r   r8   r   r    !   s   
r    c                       sZ   e Zd ZdZdeed fddZedej	eej	dd	d
Z
ej	ej	dddZ  ZS )OriNeta  Network, which estimates the canonical orientation of the given 32x32 patches, in radians.

    Zero angle points towards right. This is based on the original code from paper
    "Repeatability Is Not Enough: Learning Discriminative Affine Regions via Discriminability"".
    See :cite:`AffNet2018` for more details.

    Args:
        pretrained: Download and set pretrained weights to the model.
        eps: to avoid division by zero in atan2.

    Returns:
        Angle in radians.

    Shape:
        - Input: (B, 1, 32, 32)
        - Output: (B)

    Examples:
        >>> input = torch.rand(16, 1, 32, 32)
        >>> orinet = OriNet()
        >>> angle = orinet(input) # 16
    Fr#   )
pretrainedr&   c                    sf  t    ttjddddddtjdddt tjdddddddtjdddt tjdddd	dddtjdddt tjdddddddtjdddt tjdd
dd	dddtjd
ddt tjd
d
dddddtjd
ddt tdtjd
d	dddddt t	d| _
|| _|rZdd }tjjtd |d}| j|d dd |   d S )Nr      r'   F)r(   r)   r*   )Zaffine)r(   Zstrider)   r*   r!      @   g      ?   Tc                 S   s   | S Nr   )Zstoragelocr   r   r   <lambda>       z!OriNet.__init__.<locals>.<lambda>r   )Zmap_locationZ
state_dict)strict)r-   r.   r1   Z
SequentialZConv2dZBatchNorm2dZReLUZDropoutZTanhZAdaptiveAvgPool2dfeaturesr&   r   ZhubZload_state_dict_from_urlr   Zload_state_dicteval)r   r`   r&   Zstorage_fcnZpretrained_dictr8   r   r   r.      s>    
zOriNet.__init__ư>)xr&   r   c                 C   s,   t j| ddd\}}| |  | |  S )z4Utility function that normalizes the input by batch.)rC   T)ZdimZkeepdim)r   Zstd_meandetach)rm   r&   spmpr   r   r   _normalize_input   s    zOriNet._normalize_inputr@   c                 C   sJ   |  | |dd}t|dddf d |dddf | j }|S )ztArgs:
            patch: (torch.Tensor) shape [Bx1xHxW]
        Returns:
            patch: (torch.Tensor) shape [B]rC   rb   Nr   r#   r   )rj   rs   rS   r   rM   r&   )r   rA   Zxyr\   r   r   r   r      s    .zOriNet.forward)Fr#   )rl   )r   r   r   r   boolr3   r.   staticmethodr   r   rs   r   r^   r   r   r8   r   r_   s   s
   "r_   c                       sR   e Zd ZdZdeeeej d fddZdd	 Z	e
je
je
jd
ddZ  ZS )LAFOrientera  Module, which extracts patches using input images and local affine frames (LAFs).

    Then runs :class:`~kornia.feature.PatchDominantGradientOrientation` or
    :class:`~kornia.feature.OriNet` on patches and then rotates the LAFs by the estimated angles

    Args:
        patch_size:
        num_angular_bins:
        angle_detector: Patch orientation estimator, e.g. :class:`~kornia.feature.PatchDominantGradientOrientation`
          or OriNet.
    r!   r"   N)r$   r%   angle_detectorc                    s>   t    || _|| _|  |d u r4t| j| j| _n|| _d S re   )r-   r.   r$   r/   r    rw   )r   r$   r%   rw   r8   r   r   r.      s    
zLAFOrienter.__init__c                 C   s,   | j jd t| j d d t| j d S )Nr:   r;   zangle_detector=r<   )r9   r   r=   r$   rw   r>   r   r   r   r?      s    
zLAFOrienter.__repr__r   c           	      C   s   t | t|g d |d|dkrJtd|d d|d |jdd \}}t||| jdd| j| j}| |||}t	|
|}t|t|| }|S )	z
        Args:
            laf: shape [BxNx2x3]
            img: shape [Bx1xHxW]

        Returns:
            laf_out, shape [BxNx2x3]
        )BCrW   rV   r   z2Batch size of laf and img should be the same. Got r;   Nrb   rC   r   )r	   r
   rJ   rI   rH   r   r$   rS   rw   r   Zview_asr   r   )	r   r   r   rx   NZpatchesZangles_radiansZ
prev_angleZlaf_outr   r   r   r      s    	 zLAFOrienter.forward)r!   r"   N)r   r   r   r   r]   r   r1   Moduler.   r?   r   r   r   r^   r   r   r8   r   rv      s   
rv   )!r4   typingr   r   r   r   Ztorch.nnr1   Ztorch.nn.functionalZ
functionalrP   Zkornia.constantsr   Zkornia.filtersr   r   Zkornia.geometryr   Zkornia.testingr	   r
   r   r   r   r   r   r=   __annotations__r{   r   r    r_   rv   r   r   r   r   <module>   s   
RM