o
    oi`                     @  s  d dl mZ d dlmZ d dlZd dlm  mZ d dl	m
Z
mZmZmZ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mZ d dlmZ d d	lmZ d
dlm Z m!Z! d
dl"m#Z# dIdJddZ$dIdJddZ%dIdKddZ&dIdKddZ'G dd de
Z(G dd  d e
Z)	!	"	"	#	$	%	&dLdMd4d5Z*	6	7	7	#	&	%	$	8dNdOd;d<Z+	$dPdQd>d?Z,G d@dA dAe
Z-dRdSdEdFZ.G dGdH dHe
Z/dS )T    )annotations)OptionalN)	ModuleTensorconcatenaterandstacktensorwherezeros
zeros_like)spatial_gradient3d)normalize_pixel_coordinatesnormalize_pixel_coordinates3d)create_meshgridcreate_meshgrid3d)torch_version_ge)safe_solve_with_mask   )spatial_expectation2dspatial_softmax2d)nms3dhintwdeviceOptional[torch.device]returnr   c                 C  sB   |du r	t d}t| |d|d}t|| |}|dddd}|S )	zGenerate a kernel to with window coordinates, residual to window center.

    Args:
         h: kernel height.
         w: kernel width.
         device: device, on which generate.

    Returns:
        conv_kernel [2x1xhxw]

    NcpuFr      r   r      )torchr   r   r   permute)r   r   r   window_grid2dconv_kernel r&   ^/home/ubuntu/.local/lib/python3.10/site-packages/kornia/geometry/subpix/spatial_soft_argmax.py_get_window_grid_kernel2d$   s   
r(   c                 C  s   |du r	t d}tdd| ||d}| d dkr#| d }| d d }n| d d }| d d }|d dkr@|d }|d d }n|d d }|d d }dt|| ||   |dd||||f< |S )	zGenerate a kernel to return center coordinates, when applied with F.conv2d to 2d coordinates grid.

    Args:
        h: kernel height.
        w: kernel width.
        device: device, on which generate.

    Returns:
        conv_kernel [2x2xhxw].

    Nr   r!   r   r   r         ?)r   r   r"   r   r   float)r   r   r   center_kernelh_i1h_i2w_i1w_i2r&   r&   r'   _get_center_kernel2d8   s   
,r1   dc                 C  s  |du r	t d tdd| |||d}|d dkr$|d }|d d }n|d d }|d d }|d dkrA|d }|d d }n|d d }|d d }| d dkr^| d }	| d d }
n| d d }	| d d }
t|| ||  |
|	  }d| |d	d	|	|
||||f< |S )
a  Generate a kernel to return center coordinates, when applied with F.conv2d to 3d coordinates grid.

    Args:
        d: kernel depth.
        h: kernel height.
        w: kernel width.
        device: device, on which generate.

    Returns:
        conv_kernel [3x3xdxhxw].

    Nr   r    r   r!   r   r   r)   )r   r   r!   r*   )r2   r   r   r   r,   r-   r.   r/   r0   d_i1d_i2
center_numr&   r&   r'   _get_center_kernel3dY   s*   
"r6   c                 C  s   |du r	t d}t||d|d}| dkr%t jdd| |d| ddd}n	tdddd|d}t|d||d || dddgd}|	dddd	
d}|S )
zGenerate a kernel to return coordinates, residual to window center.

    Args:
        d: kernel depth.
        h: kernel height.
        w: kernel width.
        device: device, on which generate.

    Returns:
        conv_kernel [3x1xdxhxw]

    Nr   Tr   r   r    r   r!   )r"   r   r   linspaceviewr   r   repeat
contiguousr#   	unsqueeze)r2   r   r   r   grid2dzgrid3dr%   r&   r&   r'   _get_window_grid_kernel3d   s   
 *r@   c                      sF   e Zd ZdZ							dd  fddZd!ddZd"ddZ  ZS )#ConvSoftArgmax2dzModule that calculates soft argmax 2d per window.

    See
    :func: `~kornia.geometry.subpix.conv_soft_argmax2d` for details.
    r    r    r   r   r)   T:0yE>Fkernel_sizetuple[int, int]stridepaddingtemperatureTensor | floatnormalized_coordinatesboolepsr+   output_valuer   Nonec                   s8   t    || _|| _|| _|| _|| _|| _|| _d S N)	super__init__rE   rG   rH   rI   rK   rM   rN   )selfrE   rG   rH   rI   rK   rM   rN   	__class__r&   r'   rR      s   


zConvSoftArgmax2d.__init__strc                 C  sF   | j j d| j d| j d| j d| j d| j d| j d| j dS )	N(kernel_size=	, stride=
, padding=, temperature=, normalized_coordinates=, eps=, output_value=))	rU   __name__rE   rG   rH   rI   rK   rM   rN   rS   r&   r&   r'   __repr__   s    
zConvSoftArgmax2d.__repr__xr   Tensor | tuple[Tensor, Tensor]c              	   C  s$   t || j| j| j| j| j| j| jS rP   )conv_soft_argmax2drE   rG   rH   rI   rK   rM   rN   rS   rb   r&   r&   r'   forward   s   zConvSoftArgmax2d.forwardrB   rC   rC   r)   TrD   F)rE   rF   rG   rF   rH   rF   rI   rJ   rK   rL   rM   r+   rN   rL   r   rO   r   rV   rb   r   r   rc   r_   
__module____qualname____doc__rR   ra   rf   __classcell__r&   r&   rT   r'   rA      s    
rA   c                      sH   e Zd ZdZ								d!d" fddZd#ddZd$dd Z  ZS )%ConvSoftArgmax3dzModule that calculates soft argmax 3d per window.

    See
    :func: `~kornia.geometry.subpix.conv_soft_argmax3d` for details.
    r    r    r    r   r   r   r)   FrD   T        rE   tuple[int, int, int]rG   rH   rI   rJ   rK   rL   rM   r+   rN   strict_maxima_bonusr   rO   c	           	        s>   t    || _|| _|| _|| _|| _|| _|| _|| _	d S rP   )
rQ   rR   rE   rG   rH   rI   rK   rM   rN   rt   )	rS   rE   rG   rH   rI   rK   rM   rN   rt   rT   r&   r'   rR      s   

zConvSoftArgmax3d.__init__rV   c                 C  sN   | j j d| j d| j d| j d| j d| j d| j d| j d| j	 d	S )
NrW   rX   rY   rZ   r[   r\   z, strict_maxima_bonus=r]   r^   )
rU   r_   rE   rG   rH   rI   rK   rM   rt   rN   r`   r&   r&   r'   ra      s$   
zConvSoftArgmax3d.__repr__rb   r   rc   c              
   C  s(   t || j| j| j| j| j| j| j| j	S rP   )	conv_soft_argmax3drE   rG   rH   rI   rK   rM   rN   rt   re   r&   r&   r'   rf      s   zConvSoftArgmax3d.forwardrp   rq   rq   r)   FrD   Trr   )rE   rs   rG   rs   rH   rs   rI   rJ   rK   rL   rM   r+   rN   rL   rt   r+   r   rO   rh   ri   rj   r&   r&   rT   r'   ro      s    
ro   rB   rC   r)   TrD   FinputrE   rF   rG   rH   rI   rJ   rK   rL   rM   r+   rN   rc   c              	   C  s  t | stdt|  t| jdkstd| j |dkr(td| | j\}}	}
}|\}}| j}| j}| 	||	 d|
|} t
||||}t||||}t| d}| |  |  }t|| }|tj||||d | }|tj||  |||d | }|	||	|d	|d
}t|
|d||dd
dd	}tj||||d}tj||||d}||| }||| }|rt|dd	d
d|
|}|dd
dd	}|	||	d	|d	|d
}|r||fS |S )a  Compute the convolutional spatial Soft-Argmax 2D over the windows of a given heatmap.

    .. math::
        ij(X) = \frac{\sum{(i,j)} * exp(x / T)  \in X} {\sum{exp(x / T)  \in X}}

    .. math::
        val(X) = \frac{\sum{x * exp(x / T)  \in X}} {\sum{exp(x / T)  \in X}}

    where :math:`T` is temperature.

    Args:
        input: the given heatmap with shape :math:`(N, C, H_{in}, W_{in})`.
        kernel_size: the size of the window.
        stride: the stride of the window.
        padding: input zero padding.
        temperature: factor to apply to input.
        normalized_coordinates: whether to return the coordinates normalized in the range of :math:`[-1, 1]`.
            Otherwise, it will return the coordinates in the range of the input shape.
        eps: small value to avoid zero division.
        output_value: if True, val is output, if False, only ij.

    Returns:
        Function has two outputs - argmax coordinates and the softmaxpooled heatmap values themselves.
        On each window, the function computed returns with shapes :math:`(N, C, 2, H_{out},
        W_{out})`, :math:`(N, C, H_{out}, W_{out})`,

        where

         .. math::
             H_{out} = \left\lfloor\frac{H_{in}  + 2 \times \text{padding}[0] -
               (\text{kernel\_size}[0] - 1) - 1}{\text{stride}[0]} + 1\right\rfloor

         .. math::
             W_{out} = \left\lfloor\frac{W_{in}  + 2 \times \text{padding}[1] -
               (\text{kernel\_size}[1] - 1) - 1}{\text{stride}[1]} + 1\right\rfloor

    Examples:
        >>> input = torch.randn(20, 16, 50, 32)
        >>> nms_coords, nms_val = conv_soft_argmax2d(input, (3,3), (2,2), (1,1), output_value=True)

     Input type is not a Tensor. Got    z-Invalid input shape, we expect BxCxHxW. Got: r   5Temperature should be positive float or tensor. Got: r   rC   rG   rH   r!   r    F)r"   	is_tensor	TypeErrortypelenshape
ValueErrorr   dtyper9   r1   tor(   Fadaptive_max_pool2ddetachexpr+   
avg_pool2dsizer   r#   conv2d	expand_asr   )rw   rE   rG   rH   rI   rK   rM   rN   bcr   r   kykxr   r   r,   window_kernelx_maxx_exp	pool_coefdenx_softmaxpoolgrid_globalgrid_global_pooled
coords_maxr&   r&   r'   rd     s>   
3 rd   rp   rq   rr   rs   rt   c	           !   
   C  s  t | stdt|  t| jdkstd| j |dkr(td| | j\}	}
}}}|\}}}| j}| j}| 	|	|
 d|||} t
|||||}t|||||}t| d}| |  |  }t|| | }|tj|| |||d | }t|||d	|d
|ddddd}tj||||d}tj||||d}||| }||| }|rt|ddddd|||}|ddddd}|	|	|
d|d|d|d}|s|S |tj|	|  |  |||d | }|dkr0| d}|d}|| d }tt| |d|d} | dddd||| f } |d||   9 }|	|	|
|d|d|d}||fS )a&  Compute the convolutional spatial Soft-Argmax 3D over the windows of a given heatmap.

    .. math::
             ijk(X) = \frac{\sum{(i,j,k)} * exp(x / T)  \in X} {\sum{exp(x / T)  \in X}}

    .. math::
             val(X) = \frac{\sum{x * exp(x / T)  \in X}} {\sum{exp(x / T)  \in X}}

    where ``T`` is temperature.

    Args:
        input: the given heatmap with shape :math:`(N, C, D_{in}, H_{in}, W_{in})`.
        kernel_size:  size of the window.
        stride: stride of the window.
        padding: input zero padding.
        temperature: factor to apply to input.
        normalized_coordinates: whether to return the coordinates normalized in the range of :math:[-1, 1]`.
            Otherwise, it will return the coordinates in the range of the input shape.
        eps: small value to avoid zero division.
        output_value: if True, val is output, if False, only ij.
        strict_maxima_bonus: pixels, which are strict maxima will score (1 + strict_maxima_bonus) * value.
          This is needed for mimic behavior of strict NMS in classic local features

    Returns:
        Function has two outputs - argmax coordinates and the softmaxpooled heatmap values themselves.
        On each window, the function computed returns with shapes :math:`(N, C, 3, D_{out}, H_{out}, W_{out})`,
        :math:`(N, C, D_{out}, H_{out}, W_{out})`,

        where

         .. math::
             D_{out} = \left\lfloor\frac{D_{in}  + 2 \times \text{padding}[0] -
             (\text{kernel\_size}[0] - 1) - 1}{\text{stride}[0]} + 1\right\rfloor

         .. math::
             H_{out} = \left\lfloor\frac{H_{in}  + 2 \times \text{padding}[1] -
             (\text{kernel\_size}[1] - 1) - 1}{\text{stride}[1]} + 1\right\rfloor

         .. math::
             W_{out} = \left\lfloor\frac{W_{in}  + 2 \times \text{padding}[2] -
             (\text{kernel\_size}[2] - 1) - 1}{\text{stride}[2]} + 1\right\rfloor

    Examples:
        >>> input = torch.randn(20, 16, 3, 50, 32)
        >>> nms_coords, nms_val = conv_soft_argmax3d(input, (3, 3, 3), (1, 2, 2), (0, 1, 1))

    rx      /Invalid input shape, we expect BxCxDxHxW. Got: r   rz   r   rq   r{   Fr   ry   r!   r    Nr)   )r"   r|   r}   r~   r   r   r   r   r   r9   r6   r   r@   r   adaptive_max_pool3dr   r   r+   
avg_pool3dview_asr   r#   conv3dr   r   r   r   )!rw   rE   rG   rH   rI   rK   rM   rN   rt   r   r   r2   r   r   kzr   r   r   r   r,   r   r   r   r   r   r   r   r   r   	in_levels
out_levelsskip_levelsstrict_maximar&   r&   r'   ru   v  sN   
:
 &&&


$ru   Optional[Tensor]c                 C  s(   |du rt d}t| |}t||}|S )a  Compute the Spatial Soft-Argmax 2D of a given input heatmap.

    Args:
        input: the given heatmap with shape :math:`(B, N, H, W)`.
        temperature: factor to apply to input.
        normalized_coordinates: whether to return the coordinates normalized in the range of :math:`[-1, 1]`.
            Otherwise, it will return the coordinates in the range of the input shape.

    Returns:
        the index of the maximum 2d coordinates of the give map :math:`(B, N, 2)`.
        The output order is x-coord and y-coord.

    Examples:
        >>> input = torch.tensor([[[
        ... [0., 0., 0.],
        ... [0., 10., 0.],
        ... [0., 0., 0.]]]])
        >>> spatial_soft_argmax2d(input, normalized_coordinates=False)
        tensor([[[1.0000, 1.0000]]])

    Nr)   )r	   r   r   )rw   rI   rK   
input_softoutputr&   r&   r'   spatial_soft_argmax2d  s
   

r   c                      s8   e Zd ZdZdd fd
dZdddZdddZ  ZS )SpatialSoftArgmax2dzCompute the Spatial Soft-Argmax 2D of a given heatmap.

    See :func:`~kornia.geometry.subpix.spatial_soft_argmax2d` for details.
    NTrI   r   rK   rL   r   rO   c                   s*   t    |d u rtd}|| _|| _d S )Nr)   )rQ   rR   r	   rI   rK   )rS   rI   rK   rT   r&   r'   rR     s
   

zSpatialSoftArgmax2d.__init__rV   c                 C  s   | j j d| j d| j dS )Nztemperature=r[   r^   )rU   r_   rI   rK   r`   r&   r&   r'   ra   #  s   
zSpatialSoftArgmax2d.__repr__rw   r   c                 C     t || j| jS rP   )r   rI   rK   )rS   rw   r&   r&   r'   rf   *     zSpatialSoftArgmax2d.forwardNT)rI   r   rK   rL   r   rO   rh   )rw   r   r   r   rj   r&   r&   rT   r'   r     s
    
r         $@Hz>tuple[Tensor, Tensor]c              
   C  s  t | stdt|  t| jdkstd| j | j\}}}}}t|||d| jd	dddd	d
}|
| j}t| ddd}	|		ddd
ddd	dd
d}	t| d	dd}
|
	ddd
ddd	dd}
|
d }|
d }|
d }d|
d  }d|
d  }d|
d  }t|||||||||g	ddd
d
}tdds|t|d  |jd d | 7 }t| dd}t|	}t|	|d ||d \}}}|||}|| |t|dddd < | }| jdddd dk}|||d dt |		dd	d| }| |||||| }|dkr!|||
| j 7 }|d|||||d
	dddd	d
d}|dddddf |dddddf< ||ddddd}|| }||fS )aY  Compute the single iteration of quadratic interpolation of the extremum (max or min).

    Args:
        input: the given heatmap with shape :math:`(N, C, D_{in}, H_{in}, W_{in})`.
        strict_maxima_bonus: pixels, which are strict maxima will score (1 + strict_maxima_bonus) * value.
          This is needed for mimic behavior of strict NMS in classic local features
        eps: parameter to control the hessian matrix ill-condition number.

    Returns:
        the location and value per each 3x3x3 window which contains strict extremum, similar to one done is SIFT.
        :math:`(N, C, 3, D_{out}, H_{out}, W_{out})`, :math:`(N, C, D_{out}, H_{out}, W_{out})`,

        where

         .. math::
             D_{out} = \left\lfloor\frac{D_{in}  + 2 \times \text{padding}[0] -
             (\text{kernel\_size}[0] - 1) - 1}{\text{stride}[0]} + 1\right\rfloor

         .. math::
             H_{out} = \left\lfloor\frac{H_{in}  + 2 \times \text{padding}[1] -
             (\text{kernel\_size}[1] - 1) - 1}{\text{stride}[1]} + 1\right\rfloor

         .. math::
             W_{out} = \left\lfloor\frac{W_{in}  + 2 \times \text{padding}[2] -
             (\text{kernel\_size}[2] - 1) - 1}{\text{stride}[2]} + 1\right\rfloor

    Examples:
        >>> input = torch.randn(20, 16, 3, 50, 32)
        >>> nms_coords, nms_val = conv_quad_interp3d(input, 1.0)

    rx   r   r   Fr   r   ry   r   r!   r    diff)ordermoder7      ).r   ).r   ).r!   g      ?).r    ).ry   ).r   
   Nrp   T)dimkeepdimgffffff?g      ?)r!   r   )r   r!   ) r"   r|   r}   r~   r   r   r   r   r   r#   r   r   r   reshaper   r9   r   r   r   absr   r   r   masked_scatterr
   maxmasked_fill_r   bmmflipr:   r<   )rw   rt   rM   BCHDHWr   r   AdxxdyydssdxydysdxsHesnms_maskx_solvedx_solved_masked_solved_correctlynew_nms_maskdxmask1dyy_maxdx_resr   r&   r&   r'   conv_quad_interp3d.  sJ   
 "&
&$
*(r   c                      s8   e Zd ZdZdd fd	d
ZdddZdddZ  ZS )ConvQuadInterp3dzwCalculate soft argmax 3d per window.

    See
    :func: `~kornia.geometry.subpix.conv_quad_interp3d` for details.
    r   r   rt   r+   rM   r   rO   c                   s   t    || _|| _d S rP   )rQ   rR   rt   rM   )rS   rt   rM   rT   r&   r'   rR     s   

zConvQuadInterp3d.__init__rV   c                 C  s   | j j d| j dS )Nz(strict_maxima_bonus=r^   )rU   r_   rt   r`   r&   r&   r'   ra     s   zConvQuadInterp3d.__repr__rb   r   r   c                 C  r   rP   )r   rt   rM   re   r&   r&   r'   rf     r   zConvQuadInterp3d.forwardr   r   )rt   r+   rM   r+   r   rO   rh   )rb   r   r   r   rj   r&   r&   rT   r'   r     s
    
r   rP   )r   r   r   r   r   r   r   r   )
r2   r   r   r   r   r   r   r   r   r   rg   )rw   r   rE   rF   rG   rF   rH   rF   rI   rJ   rK   rL   rM   r+   rN   rL   r   rc   rv   )rw   r   rE   rs   rG   rs   rH   rs   rI   rJ   rK   rL   rM   r+   rN   rL   rt   r+   r   rc   r   )rw   r   rI   r   rK   rL   r   r   r   )rw   r   rt   r+   rM   r+   r   r   )0
__future__r   typingr   r"   torch.nn.functionalnn
functionalr   kornia.corer   r   r   r   r   r	   r
   r   r   kornia.filters.sobelr   kornia.geometry.conversionsr   r   kornia.utilsr   r   kornia.utils._compatr   kornia.utils.helpersr   dsntr   r   nmsr   r(   r1   r6   r@   rA   ro   rd   ru   r   r   r   r   r&   r&   r&   r'   <module>   sR   ,!(39t X