class_docstr: The basic implementation for object context block
  Input:
      N X C X H X W
  Parameters:
      in_channels       : the dimension of the input feature map
      key_channels      : the dimension after the key/query transform
      scale             : choose the scale to downsample the input feature maps (save memory cost)
      bn_type           : specify the bn type
  Return:
      N X C X H X W
code: def __init__(
      self,
      in_channels,
      key_channels,
      scale=1,
      norm_layer=nn.BatchNorm2d,
      align_corners=True,
  ):
      super(ObjectAttentionBlock2D, self).__init__()
      self.scale = scale
      self.in_channels = in_channels
      self.key_channels = key_channels
      self.align_corners = align_corners
  
      self.pool = nn.MaxPool2d(kernel_size=(scale, scale))
      self.f_pixel = nn.Sequential(
          nn.Conv2d(
              in_channels=self.in_channels,
              out_channels=self.key_channels,
              kernel_size=1,
              stride=1,
              padding=0,
              bias=False,
          ),
          nn.Sequential(
              norm_layer(self.key_channels), nn.ReLU(inplace=True)
          ),
          nn.Conv2d(
              in_channels=self.key_channels,
              out_channels=self.key_channels,
              kernel_size=1,
              stride=1,
              padding=0,
              bias=False,
          ),
          nn.Sequential(
              norm_layer(self.key_channels), nn.ReLU(inplace=True)
          ),
      )
      self.f_object = nn.Sequential(
          nn.Conv2d(
              in_channels=self.in_channels,
              out_channels=self.key_channels,
              kernel_size=1,
              stride=1,
              padding=0,
              bias=False,
          ),
          nn.Sequential(
              norm_layer(self.key_channels), nn.ReLU(inplace=True)
          ),
          nn.Conv2d(
              in_channels=self.key_channels,
              out_channels=self.key_channels,
              kernel_size=1,
              stride=1,
              padding=0,
              bias=False,
          ),
          nn.Sequential(
              norm_layer(self.key_channels), nn.ReLU(inplace=True)
          ),
      )
      self.f_down = nn.Sequential(
          nn.Conv2d(
              in_channels=self.in_channels,
              out_channels=self.key_channels,
              kernel_size=1,
              stride=1,
              padding=0,
              bias=False,
          ),
          nn.Sequential(
              norm_layer(self.key_channels), nn.ReLU(inplace=True)
          ),
      )
      self.f_up = nn.Sequential(
          nn.Conv2d(
              in_channels=self.key_channels,
              out_channels=self.in_channels,
              kernel_size=1,
              stride=1,
              padding=0,
              bias=False,
          ),
          nn.Sequential(
              norm_layer(self.in_channels), nn.ReLU(inplace=True)
          ),
      )
  
file_path: carefree-learn/cflearn/api/cv/third_party/iharm/model/modeling/ocr.py
imports: import torch
  import torch._utils
  import torch.nn
  import torch.nn.functional
label_desc: Use image node_id 1 to create a new ObjectAttentionBlock2D object from inherited base classes: nn with example: obj = ObjectAttentionBlock2D(in_channels, key_channels, scale, norm_layer, align_corners)