a
    d                     @   s   d Z ddlmZ ddlZddlm  mZ ddlm	Z	 ddl
mZ dd Zedfejejejd	d
dZdejeejdddZdejejeejdddZdejejeeef edddZdS )zImplementation of "differentiable spatial to numerical" (soft-argmax) operations, as described in the paper
"Numerical Coordinate Regression with Convolutional Neural Networks" by Nibali et al.    )TupleN)check_is_tensor)create_meshgridc                 C   s*   t |  t| jdks&td| j d S )N   z-Invalid input shape, we expect BxCxHxW. Got: )r   lenshape
ValueError)tensor r
   d/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/geometry/subpix/dsnt.py$_validate_batched_image_tensor_input   s    r   g      ?)inputtemperaturereturnc                 C   sX   t |  | j\}}}}|j| j| jd}| ||d}tj|| dd}|||||S )a1  Apply the Softmax function over features in each image channel.

    Note that this function behaves differently to :py:class:`torch.nn.Softmax2d`, which
    instead applies Softmax over features at each spatial location.

    Args:
        input: the input tensor with shape :math:`(B, N, H, W)`.
        temperature: factor to apply to input, adjusting the "smoothness" of the output distribution.

    Returns:
       a 2D probability distribution per image channel with shape :math:`(B, N, H, W)`.

    Examples:
        >>> heatmaps = torch.tensor([[[
        ... [0., 0., 0.],
        ... [0., 0., 0.],
        ... [0., 1., 2.]]]])
        >>> spatial_softmax2d(heatmaps)
        tensor([[[[0.0585, 0.0585, 0.0585],
                  [0.0585, 0.0585, 0.0585],
                  [0.0585, 0.1589, 0.4319]]]])
    )devicedtype)Zdim)r   r   tor   r   viewFZsoftmax)r   r   
batch_sizechannelsheightwidthxZx_softr
   r
   r   spatial_softmax2d   s    r   T)r   normalized_coordinatesr   c                 C   s   t |  | j\}}}}t|||| j}|| j}|d d}|d d}| ||d}	tj	||	 ddd}
tj	||	 ddd}t
||
gd}|||dS )a  Compute the expectation of coordinate values using spatial probabilities.

    The input heatmap is assumed to represent a valid spatial probability distribution,
    which can be achieved using :func:`~kornia.geometry.subpixel.spatial_softmax2d`.

    Args:
        input: the input tensor representing dense spatial probabilities with shape :math:`(B, N, H, W)`.
        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:
       expected value of the 2D coordinates with shape :math:`(B, N, 2)`. Output order of the coordinates is (x, y).

    Examples:
        >>> heatmaps = torch.tensor([[[
        ... [0., 0., 0.],
        ... [0., 0., 0.],
        ... [0., 1., 0.]]]])
        >>> spatial_expectation2d(heatmaps, False)
        tensor([[[1., 2.]]])
    .r   r   .   TZkeepdim   )r   r   r   r   r   r   Zreshaper   torchsumcat)r   r   r   r   r   r   gridpos_xpos_yZ
input_flatZ
expected_yZ
expected_xoutputr
   r
   r   spatial_expectation2d5   s    r)   3#I9)	numeratordenominatorepsr   c                 C   s   | t j||d S )N)min)r"   clamp)r+   r,   r-   r
   r
   r   _safe_zero_divisiona   s    r0   )meanstdsizer   c                 C   s   |j | j kr|j| jks td|\}}t|||| j}|| j }|d ||}|d ||}|| d  d }	|| d  d }
dt|d  }dt|d  }t|	| }t|
| }|| }|j	dd	d
j	dd	d
}t
||}|S )a  Render the PDF of a 2D Gaussian distribution.

    Args:
        mean: the mean location of the Gaussian to render, :math:`(\mu_x, \mu_y)`. Shape: :math:`(*, 2)`.
        std: the standard deviation of the Gaussian to render, :math:`(\sigma_x, \sigma_y)`.
          Shape :math:`(*, 2)`. Should be able to be broadcast with `mean`.
        size: the (height, width) of the output image.
        normalized_coordinates: whether ``mean`` and ``std`` are assumed to use coordinates normalized
          in the range of :math:`[-1, 1]`. Otherwise, coordinates are assumed to be in the range of the output shape.

    Returns:
        tensor including rendered points with shape :math:`(*, H, W)`.
    z1Expected inputs to have the same dtype and devicer   r   ).r   NNr!   ).r   NNg      Tr    r   )r   r   	TypeErrorr   r   r   r"   Z
reciprocalexpr#   r0   )r1   r2   r3   r   r   r   r%   r&   r'   Zdist_xZdist_yZk_xZk_yZexps_xZexps_ygaussZval_sumr
   r
   r   render_gaussian2de   s"    
r8   )T)r*   )T)__doc__typingr   r"   Ztorch.nn.functionalnnZ
functionalr   Zkornia.testingr   Zkornia.utils.gridr   r   r	   ZTensorr   boolr)   floatr0   intr8   r
   r
   r
   r   <module>   s   "", 