o
    oiD(                     @   s   U d dl mZmZ d dlZd dlm  mZ d dl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 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 )    )DictOptionalN)nn)pi)KORNIA_CHECK_LAFKORNIA_CHECK_SHAPE)SpatialGradientget_gaussian_discrete_kernel1dget_gaussian_kernel2d)rad2deg   )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dejdejdejfddZdS )PassLAFzSDummy module to use instead of local feature orientation or affine shape estimator.lafimgreturnc                 C   s   |S )zRun forward.

        Args:
            laf: :math:`(B, N, 2, 3)`
            img: :math:`(B, 1, H, W)`

        Returns:
            LAF, unchanged :math:`(B, N, 2, 3)`

         )selfr   r   r   r   N/home/ubuntu/.local/lib/python3.10/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                	       sX   e Zd ZdZddedededd	f fd
dZdefddZde	j
de	j
f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epsr   Nc                    s   t    || _|| _tdd| _|| _tjddddddd| _	t
  tdd| j	jd d < W d    n1 s:w   Y  t| jd	 }t| j| jf||fd
| _d S )Nsobelr         Fcircular)kernel_sizepaddingbiaspadding_modeg?g      @T)super__init__r$   num_ang_binsr   gradientr&   r   Conv1dangular_smoothr   no_gradr	   weightfloatr
   	weighting)r   r$   r%   r&   sigma	__class__r   r   r0   @   s   

z)PatchDominantGradientOrientation.__init__c                 C   s&   | j j d| j d| j d| j dS )N(patch_size=z, num_ang_bins=z, eps=))r;   r   r$   r1   r&   r   r   r   r   __repr__L   s   $z)PatchDominantGradientOrientation.__repr__patchc                 C   s  t |g d | \}}}}|| jks|| jks|dkr.td| j d| j d|  | j|j|j| _| j|j|j| _| 	|}|dddddf }|dddddf }t
|| ||  | j | 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\}}| j| d | j }|d | j }t
|d|ddd}|}t
|d|ddd}d||  || d|   }dt ||j|  t| j t  }|S )Run forward.

        Args:
            patch: :math:`(B, 1, H, W)`

        Returns:
            angle in radians: :math:`(B)`

        )B1HWr   z#input shape should be must be [Bx1xxz]. Got Nr   g       @g      ?)r   r   g      ?)r   sizer$   	TypeErrorr8   todtypedevicer4   r2   r   sqrtr&   atan2r   r7   r1   floorrangeFadaptive_avg_pool2dappendcatviewmaxgatherreshape)r   r@   _CHrE   rD   gradsgxgymagorio_bigbo0_bigwo1_bigbo1_bigwo0_bigang_bins_listi
ang_bins_iang_binsvaluesindicesindices_leftindices_rightleftcenterrightc_subpixangler   r   r   r   Q   sJ   

"

((z(PatchDominantGradientOrientation.forward)r!   r"   r#   )r   r   r   r   intr7   r0   strr?   r   r   r   __classcell__r   r   r:   r   r    4   s
     r    c                       sf   e Zd ZdZddededdf fdd	Zeddej	dedej	fddZ
dej	dej	f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&   r   Nc                    sb  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| _
|| _|rtjjtd tdd}| j|d dd |   d S )Nr         F)r+   r,   r-   )affine)r+   strider,   r-   r!   r)   @   g      ?   Tr   cpu)map_location
state_dict)strict)r/   r0   r   
SequentialConv2dBatchNorm2dReLUDropoutTanhAdaptiveAvgPool2dfeaturesr&   r   hubload_state_dict_from_urlr   rL   load_state_dicteval)r   rv   r&   pretrained_dictr:   r   r   r0      s<   
zOriNet.__init__ư>rF   c                 C   s,   t j| ddd\}}| |  | |  S )z4Utility function that normalizes the input by batch.)rG   T)dimkeepdim)r   std_meandetach)rF   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 )rA   rG   r)   Nr   r#   r   )r   r   rU   r   rN   r&   )r   r@   xyrq   r   r   r   r      s   
.zOriNet.forward)Fr#   )r   )r   r   r   r   boolr7   r0   staticmethodr   r   r   r   rt   r   r   r:   r   ru      s    !ru   c                	       sf   e Zd ZdZ	ddededeej ddf fd	d
Zde	fddZ
dejdejdejf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"   Nr$   r%   angle_detectorr   c                    s@   t    || _|| _|  |d u rt| j| j| _d S || _d S )N)r/   r0   r$   r1   r    r   )r   r$   r%   r   r:   r   r   r0      s   

zLAFOrienter.__init__c                 C   s   | j j d| j d| j dS )Nr<   z, angle_detector=r=   )r;   r   r$   r   r>   r   r   r   r?      s   zLAFOrienter.__repr__r   r   c           	      C   s   t | t|g d |d|dkr%td|d d|d |jdd \}}t||| jdd| j| j}| |||}t	|
|}t|t|| }|S )	zRun forward.

        Args:
            laf: :math:`(B, N, 2, 3)`
            img: :math:`(B, 1, H, W)`

        Returns:
            LAF_out: :math:`(B, N, 2, 3)`

        )rB   CrD   rE   r   z2Batch size of laf and img should be the same. Got z, Nr)   rG   r   )r   r   rH   
ValueErrorshaper   r$   rU   r   r   view_asr   r   )	r   r   r   rB   Npatchesangles_radians
prev_anglelaf_outr   r   r   r      s    zLAFOrienter.forward)r!   r"   N)r   r   r   r   rr   r   r   Moduler0   rs   r?   r   r   r   rt   r   r   r:   r   r      s    $r   )typingr   r   r   torch.nn.functionalr   
functionalrQ   kornia.constantsr   kornia.core.checkr   r   kornia.filtersr   r	   r
   kornia.geometryr   r   r   r   r   r   rs   __annotations__r   r   r    ru   r   r   r   r   r   <module>   s   QR