class_docstr: BFP (Balanced Feature Pyrmamids)
  
  BFP takes multi-level features as inputs and gather them into a single one,
  then refine the gathered feature and scatter the refined results to
  multi-level features. This module is used in Libra R-CNN (CVPR 2019), see
  the paper `Libra R-CNN: Towards Balanced Learning for Object Detection
  <https://arxiv.org/abs/1904.02701>`_ for details.
  
  Args:
      in_channels (int): Number of input channels (feature maps of all levels
          should have the same channels).
      num_levels (int): Number of input feature levels.
      conv_cfg (dict): The config dict for convolution layers.
      norm_cfg (dict): The config dict for normalization layers.
      refine_level (int): Index of integration and refine level of BSF in
          multi-level features from bottom to top.
      refine_type (str): Type of the refine op, currently support
          [None, 'conv', 'non_local'].
docstr: Forward function.
docstr_tok: ["Forward","function","."]
code: def forward(self, inputs):
      """Forward function."""
      assert len(inputs) == self.num_levels
  
      # step 1: gather multi-level features by resize and average
      feats = []
      gather_size = inputs[self.refine_level].size()[2:]
      for i in range(self.num_levels):
          if i < self.refine_level:
              gathered = F.adaptive_max_pool2d(
                  inputs[i], output_size=gather_size
              )
          else:
              gathered = F.interpolate(
                  inputs[i], size=gather_size, mode="nearest"
              )
          feats.append(gathered)
  
      bsf = np.mean(feats)
  
      # step 2: refine gathered features
      if self.refine_type is not None:
          bsf = self.refine(bsf)
  
      # step 3: scatter refined features to multi-levels by a residual path
      outs = []
      for i in range(self.num_levels):
          out_size = inputs[i].size()[2:]
          if i < self.refine_level:
              residual = F.interpolate(
                  bsf, size=out_size, mode="nearest"
              )
          else:
              residual = F.adaptive_max_pool2d(
                  bsf, output_size=out_size
              )
          outs.append(residual + inputs[i])
  
      return tuple(outs)
  
file_path: insightface/detection/scrfd/mmdet/models/necks/bfp.py
imports: import torch.nn
  import torch.nn.functional
  from mmcv.cnn import ConvModule, xavier_init
  from mmcv.cnn.bricks import NonLocal2d
  import numpy
  from ..builder import NECKS
label_desc: Use image node_id 3 for calling the BFP obj's underlying member method code with example usage: obj.forward(inputs) and returns: tuple