class_docstr: HRFPN (High Resolution Feature Pyramids)
  Transforms outputs of HRNet backbone so they are suitable for the ROI_heads
  arXiv: https://arxiv.org/abs/1904.04514
  Adapted from https://github.com/open-mmlab/mmdetection/blob/master/mmdet/models/necks/hrfpn.py
  Args:
      bottom_up: (list) output of HRNet
      in_features (list): names of the input features (output of HRNet)
      in_channels (list): number of channels for each branch
      out_channels (int): output channels of feature pyramids
      n_out_features (int): number of output stages
      pooling (str): pooling for generating feature pyramids (from {MAX, AVG})
      share_conv (bool): Have one conv per output, or share one with all the outputs
class_docstr_tok: ["HRFPN","(","High","Resolution","Feature","Pyramids",")","Transforms","outputs","of","HRNet","backbone","so","they","are","suitable","for","the","ROI_heads","arXiv",":","https",":","\/\/arxiv.org\/abs\/1904.04514","Adapted","from","https",":","\/\/github.com\/open-mmlab\/mmdetection\/blob\/master\/mmdet\/models\/necks\/hrfpn.py","Args",":","bottom_up",":","(","list",")","output","of","HRNet","in_features","(","list",")",":","names","of","the","input","features","(","output","of","HRNet",")","in_channels","(","list",")",":","number","of","channels","for","each","branch","out_channels","(","int",")",":","output","channels","of","feature","pyramids","n_out_features","(","int",")",":","number","of","output","stages","pooling","(","str",")",":","pooling","for","generating","feature","pyramids","(","from","{","MAX",",","AVG","}",")","share_conv","(","bool",")",":","Have","one","conv","per","output",",","or","share","one","with","all","the","outputs"]
code: def __init__(
      self,
      bottom_up,
      in_features,
      n_out_features,
      in_channels,
      out_channels,
      pooling="AVG",
      share_conv=False,
  ):
      super(HRFPN, self).__init__()
      assert isinstance(in_channels, list)
      self.bottom_up = bottom_up
      self.in_features = in_features
      self.n_out_features = n_out_features
      self.in_channels = in_channels
      self.out_channels = out_channels
      self.num_ins = len(in_channels)
      self.share_conv = share_conv
  
      if self.share_conv:
          self.fpn_conv = nn.Conv2d(
              in_channels=out_channels,
              out_channels=out_channels,
              kernel_size=3,
              padding=1,
          )
      else:
          self.fpn_conv = nn.ModuleList()
          for _ in range(self.n_out_features):
              self.fpn_conv.append(
                  nn.Conv2d(
                      in_channels=out_channels,
                      out_channels=out_channels,
                      kernel_size=3,
                      padding=1,
                  )
              )
  
      # Custom change: Replaces a simple bilinear interpolation
      self.interp_conv = nn.ModuleList()
      for i in range(len(self.in_features)):
          self.interp_conv.append(
              nn.Sequential(
                  nn.ConvTranspose2d(
                      in_channels=in_channels[i],
                      out_channels=in_channels[i],
                      kernel_size=4,
                      stride=2**i,
                      padding=0,
                      output_padding=0,
                      bias=False,
                  ),
                  nn.BatchNorm2d(in_channels[i], momentum=0.1),
                  nn.ReLU(inplace=True),
              )
          )
  
      # Custom change: Replaces a couple (reduction conv + pooling) by one conv
      self.reduction_pooling_conv = nn.ModuleList()
      for i in range(self.n_out_features):
          self.reduction_pooling_conv.append(
              nn.Sequential(
                  nn.Conv2d(
                      sum(in_channels),
                      out_channels,
                      kernel_size=2**i,
                      stride=2**i,
                  ),
                  nn.BatchNorm2d(out_channels, momentum=0.1),
                  nn.ReLU(inplace=True),
              )
          )
  
      if pooling == "MAX":
          self.pooling = F.max_pool2d
      else:
          self.pooling = F.avg_pool2d
  
      self._out_features = []
      self._out_feature_channels = {}
      self._out_feature_strides = {}
  
      for i in range(self.n_out_features):
          self._out_features.append("p%d" % (i + 1))
          self._out_feature_channels.update(
              {self._out_features[-1]: self.out_channels}
          )
          self._out_feature_strides.update(
              {self._out_features[-1]: 2 ** (i + 2)}
          )
  
file_path: detectron2/projects/DensePose/densepose/modeling/hrfpn.py
imports: import torch
  import torch.nn
  import torch.nn.functional
  from detectron2.layers import ShapeSpec
  from detectron2.modeling.backbone import BACKBONE_REGISTRY
  from detectron2.modeling.backbone.backbone import Backbone
  from .hrnet import build_pose_hrnet_backbone
label_desc: Use image node_id 1 to create a new HRFPN object from inherited base classes: Backbone with example: obj = HRFPN(bottom_up, in_features, n_out_features, in_channels, out_channels, pooling, share_conv)