class_docstr: 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:
      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
code: def __init__(
      self,
      num_ang_bins: int = 8,
      num_spatial_bins: int = 4,
      spatial_bin_size: int = 4,
      rootsift: bool = True,
      clipval: float = 0.2,
      stride: int = 1,
      padding: int = 1,
  ) -> None:
      super().__init__()
      self.eps = 1e-10
      self.num_ang_bins = num_ang_bins
      self.num_spatial_bins = num_spatial_bins
      self.spatial_bin_size = spatial_bin_size
      self.clipval = clipval
      self.rootsift = rootsift
      self.stride = stride
      self.pad = padding
      nw = get_sift_pooling_kernel(ksize=self.spatial_bin_size).float()
      self.bin_pooling_kernel = nn.Conv2d(
          1,
          1,
          kernel_size=(nw.size(0), nw.size(1)),
          stride=(1, 1),
          bias=False,
          padding=(nw.size(0) // 2, nw.size(1) // 2),
      )
      self.bin_pooling_kernel.weight.data.copy_(
          nw.reshape(1, 1, nw.size(0), nw.size(1))
      )
      self.PoolingConv = nn.Conv2d(
          num_ang_bins,
          num_ang_bins * num_spatial_bins**2,
          kernel_size=(num_spatial_bins, num_spatial_bins),
          stride=(self.stride, self.stride),
          bias=False,
          padding=(self.pad, self.pad),
      )
      self.PoolingConv.weight.data.copy_(
          _get_reshape_kernel(
              num_ang_bins, num_spatial_bins, num_spatial_bins
          ).float()
      )
  
imports: import math
  from typing import Tuple
  import torch
  from torch import nn
  from kornia.core import Module, Tensor, concatenate, eye, normalize
  from kornia.core.check import KORNIA_CHECK_SHAPE
  from kornia.filters import get_gaussian_kernel2d, spatial_gradient
  from kornia.geometry.conversions import pi
label_desc: Use image node_id 2 to create a new DenseSIFTDescriptor object from inherited base classes: Module with example: obj = DenseSIFTDescriptor(num_ang_bins, num_spatial_bins, spatial_bin_size, rootsift, clipval, stride, padding)