class_docstr: FPN-like fusion module in Real-time Scene Text Detection with
  Differentiable Binarization.
  
  This was partially adapted from https://github.com/MhLiao/DB and
  https://github.com/WenmuZhou/DBNet.pytorch.
  
  Args:
      in_channels (list[int]): A list of numbers of input channels.
      lateral_channels (int): Number of channels for lateral layers.
      out_channels (int): Number of output channels.
      bias_on_lateral (bool): Whether to use bias on lateral convolutional
          layers.
      bn_re_on_lateral (bool): Whether to use BatchNorm and ReLU
          on lateral convolutional layers.
      bias_on_smooth (bool): Whether to use bias on smoothing layer.
      bn_re_on_smooth (bool): Whether to use BatchNorm and ReLU on smoothing
          layer.
      asf_cfg (dict, optional): Adaptive Scale Fusion module configs. The
          attention_type can be 'ScaleChannelSpatial'.
      conv_after_concat (bool): Whether to add a convolution layer after
          the concatenation of predictions.
      init_cfg (dict or list[dict], optional): Initialization configs.
class_docstr_tok: ["FPN-like","fusion","module","in","Real-time","Scene","Text","Detection","with","Differentiable","Binarization",".","This","was","partially","adapted","from","https",":","\/\/github.com\/MhLiao\/DB","and","https",":","\/\/github.com\/WenmuZhou\/DBNet.pytorch",".","Args",":","in_channels","(","list","[","int","]",")",":","A","list","of","numbers","of","input","channels",".","lateral_channels","(","int",")",":","Number","of","channels","for","lateral","layers",".","out_channels","(","int",")",":","Number","of","output","channels",".","bias_on_lateral","(","bool",")",":","Whether","to","use","bias","on","lateral","convolutional","layers",".","bn_re_on_lateral","(","bool",")",":","Whether","to","use","BatchNorm","and","ReLU","on","lateral","convolutional","layers",".","bias_on_smooth","(","bool",")",":","Whether","to","use","bias","on","smoothing","layer",".","bn_re_on_smooth","(","bool",")",":","Whether","to","use","BatchNorm","and","ReLU","on","smoothing","layer",".","asf_cfg","(","dict",",","optional",")",":","Adaptive","Scale","Fusion","module","configs",".","The","attention_type","can","be","'ScaleChannelSpatial","'",".","conv_after_concat","(","bool",")",":","Whether","to","add","a","convolution","layer","after","the","concatenation","of","predictions",".","init_cfg","(","dict","or","list","[","dict","]",",","optional",")",":","Initialization","configs","."]
docstr: Args:
      inputs (list[Tensor]): Each tensor has the shape of
          :math:`(N, C_i, H_i, W_i)`. It usually expects 4 tensors
          (C2-C5 features) from ResNet.
  
  Returns:
      Tensor: A tensor of shape :math:`(N, C_{out}, H_0, W_0)` where
      :math:`C_{out}` is ``out_channels``.
docstr_tok: ["Args",":","inputs","(","list","[","Tensor","]",")",":","Each","tensor","has","the","shape","of",":","math",":","`","(","N",",","C_i",",","H_i",",","W_i",")","`",".","It","usually","expects","4","tensors","(","C2-C5","features",")","from","ResNet",".","Returns",":","Tensor",":","A","tensor","of","shape",":","math",":","`","(","N",",","C_","{","out","}",",","H_0",",","W_0",")","`","where",":","math",":","`","C_","{","out","}","`","is","``","out_channels","``","."]
code: def forward(self, inputs: List[torch.Tensor]) -> torch.Tensor:
      """
      Args:
          inputs (list[Tensor]): Each tensor has the shape of
              :math:`(N, C_i, H_i, W_i)`. It usually expects 4 tensors
              (C2-C5 features) from ResNet.
  
      Returns:
          Tensor: A tensor of shape :math:`(N, C_{out}, H_0, W_0)` where
          :math:`C_{out}` is ``out_channels``.
      """
      assert len(inputs) == len(self.in_channels)
      # build laterals
      laterals = [
          lateral_conv(inputs[i])
          for i, lateral_conv in enumerate(self.lateral_convs)
      ]
      used_backbone_levels = len(laterals)
      # build top-down path
      for i in range(used_backbone_levels - 1, 0, -1):
          prev_shape = laterals[i - 1].shape[2:]
          laterals[i - 1] = laterals[i - 1] + F.interpolate(
              laterals[i], size=prev_shape, mode="nearest"
          )
      # build outputs
      # part 1: from original levels
      outs = [
          self.smooth_convs[i](laterals[i])
          for i in range(used_backbone_levels)
      ]
  
      for i, out in enumerate(outs):
          outs[i] = F.interpolate(
              outs[i], size=outs[0].shape[2:], mode="nearest"
          )
  
      out = torch.cat(outs, dim=1)
      if self.asf_cfg is not None:
          asf_feature = self.asf_conv(out)
          attention = self.asf_attn(asf_feature)
          enhanced_feature = []
          for i, out in enumerate(outs):
              enhanced_feature.append(attention[:, i : i + 1] * outs[i])
          out = torch.cat(enhanced_feature, dim=1)
  
      if self.conv_after_concat:
          out = self.out_conv(out)
  
      return out
  
file_path: mmocr/mmocr/models/textdet/necks/fpn_cat.py
imports: from typing import Dict, List, Optional, Union
  import torch
  import torch.nn
  import torch.nn.functional
  from mmcv.cnn import ConvModule
  from mmengine.model import BaseModule, ModuleList, Sequential
  from mmocr.registry import MODELS
label_desc: Use image node_id 2 for calling the FPNC obj's underlying member method code with example usage: obj.forward(inputs) and returns: out