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 forward(self, x, proxy):
      batch_size, h, w = x.size(0), x.size(2), x.size(3)
      if self.scale > 1:
          x = self.pool(x)
  
      query = self.f_pixel(x).view(batch_size, self.key_channels, -1)
      query = query.permute(0, 2, 1)
      key = self.f_object(proxy).view(batch_size, self.key_channels, -1)
      value = self.f_down(proxy).view(batch_size, self.key_channels, -1)
      value = value.permute(0, 2, 1)
  
      sim_map = torch.matmul(query, key)
      sim_map = (self.key_channels**-0.5) * sim_map
      sim_map = F.softmax(sim_map, dim=-1)
  
      # add bg context ...
      context = torch.matmul(sim_map, value)
      context = context.permute(0, 2, 1).contiguous()
      context = context.view(
          batch_size, self.key_channels, *x.size()[2:]
      )
      context = self.f_up(context)
      if self.scale > 1:
          context = F.interpolate(
              input=context,
              size=(h, w),
              mode="bilinear",
              align_corners=self.align_corners,
          )
  
      return context
  
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 2 for calling the ObjectAttentionBlock2D obj's underlying member method code with example usage: obj.forward(x, proxy) and returns: context