class_docstr: Bbox head used in CrowdDet.
  
  .. code-block:: none
  
                                    /-> cls convs_1 -> cls fcs_1 -> cls_1
                                 |--
                                 |  \-> reg convs_1 -> reg fcs_1 -> reg_1
                                 |
                                 |  /-> cls convs_2 -> cls fcs_2 -> cls_2
      shared convs -> shared fcs |--
                                 |  \-> reg convs_2 -> reg fcs_2 -> reg_2
                                 |
                                 |                     ...
                                 |
                                 |  /-> cls convs_k -> cls fcs_k -> cls_k
                                 |--
                                    \-> reg convs_k -> reg fcs_k -> reg_k
  
  
  Args:
      num_instance (int): The number of branches after shared fcs.
          Defaults to 2.
      with_refine (bool): Whether to use refine module. Defaults to False.
      num_shared_convs (int): The number of shared convs. Defaults to 0.
      num_shared_fcs (int): The number of shared fcs. Defaults to 2.
      num_cls_convs (int): The number of cls convs. Defaults to 0.
      num_cls_fcs (int): The number of cls fcs. Defaults to 0.
      num_reg_convs (int): The number of reg convs. Defaults to 0.
      num_reg_fcs (int): The number of reg fcs. Defaults to 0.
      conv_out_channels (int): The number of conv out channels.
          Defaults to 256.
      fc_out_channels (int): The number of fc out channels. Defaults to 1024.
      init_cfg (dict or list[dict], optional): Initialization config dict.
          Defaults to None.
code: def __init__(
      self,
      num_instance: int = 2,
      with_refine: bool = False,
      num_shared_convs: int = 0,
      num_shared_fcs: int = 2,
      num_cls_convs: int = 0,
      num_cls_fcs: int = 0,
      num_reg_convs: int = 0,
      num_reg_fcs: int = 0,
      conv_out_channels: int = 256,
      fc_out_channels: int = 1024,
      init_cfg: Optional[Union[dict, ConfigDict]] = None,
      *args,
      **kwargs,
  ) -> None:
      super().__init__(*args, init_cfg=init_cfg, **kwargs)
      assert (
          num_shared_convs
          + num_shared_fcs
          + num_cls_convs
          + num_cls_fcs
          + num_reg_convs
          + num_reg_fcs
          > 0
      )
      assert (
          num_instance == 2
      ), "Currently only 2 instances are supported"
      if num_cls_convs > 0 or num_reg_convs > 0:
          assert num_shared_fcs == 0
      if not self.with_cls:
          assert num_cls_convs == 0 and num_cls_fcs == 0
      if not self.with_reg:
          assert num_reg_convs == 0 and num_reg_fcs == 0
      self.num_instance = num_instance
      self.num_shared_convs = num_shared_convs
      self.num_shared_fcs = num_shared_fcs
      self.num_cls_convs = num_cls_convs
      self.num_cls_fcs = num_cls_fcs
      self.num_reg_convs = num_reg_convs
      self.num_reg_fcs = num_reg_fcs
      self.conv_out_channels = conv_out_channels
      self.fc_out_channels = fc_out_channels
      self.with_refine = with_refine
  
      # add shared convs and fcs
      (
          self.shared_convs,
          self.shared_fcs,
          last_layer_dim,
      ) = self._add_conv_fc_branch(
          self.num_shared_convs,
          self.num_shared_fcs,
          self.in_channels,
          True,
      )
      self.shared_out_channels = last_layer_dim
      self.relu = nn.ReLU(inplace=True)
  
      if self.with_refine:
          refine_model_cfg = {
              "type": "Linear",
              "in_features": self.shared_out_channels + 20,
              "out_features": self.shared_out_channels,
          }
          self.shared_fcs_ref = MODELS.build(refine_model_cfg)
          self.fc_cls_ref = nn.ModuleList()
          self.fc_reg_ref = nn.ModuleList()
  
      self.cls_convs = nn.ModuleList()
      self.cls_fcs = nn.ModuleList()
      self.reg_convs = nn.ModuleList()
      self.reg_fcs = nn.ModuleList()
      self.cls_last_dim = list()
      self.reg_last_dim = list()
      self.fc_cls = nn.ModuleList()
      self.fc_reg = nn.ModuleList()
      for k in range(self.num_instance):
          # add cls specific branch
          cls_convs, cls_fcs, cls_last_dim = self._add_conv_fc_branch(
              self.num_cls_convs,
              self.num_cls_fcs,
              self.shared_out_channels,
          )
          self.cls_convs.append(cls_convs)
          self.cls_fcs.append(cls_fcs)
          self.cls_last_dim.append(cls_last_dim)
  
          # add reg specific branch
          reg_convs, reg_fcs, reg_last_dim = self._add_conv_fc_branch(
              self.num_reg_convs,
              self.num_reg_fcs,
              self.shared_out_channels,
          )
          self.reg_convs.append(reg_convs)
          self.reg_fcs.append(reg_fcs)
          self.reg_last_dim.append(reg_last_dim)
  
          if self.num_shared_fcs == 0 and not self.with_avg_pool:
              if self.num_cls_fcs == 0:
                  self.cls_last_dim *= self.roi_feat_area
              if self.num_reg_fcs == 0:
                  self.reg_last_dim *= self.roi_feat_area
  
          if self.with_cls:
              if self.custom_cls_channels:
                  cls_channels = self.loss_cls.get_cls_channels(
                      self.num_classes
                  )
              else:
                  cls_channels = self.num_classes + 1
              cls_predictor_cfg_ = (
                  self.cls_predictor_cfg.copy()
              )  # deepcopy
              cls_predictor_cfg_.update(
                  in_features=self.cls_last_dim[k],
                  out_features=cls_channels,
              )
              self.fc_cls.append(MODELS.build(cls_predictor_cfg_))
              if self.with_refine:
                  self.fc_cls_ref.append(
                      MODELS.build(cls_predictor_cfg_)
                  )
  
          if self.with_reg:
              out_dim_reg = (
                  4 if self.reg_class_agnostic else 4 * self.num_classes
              )
              reg_predictor_cfg_ = self.reg_predictor_cfg.copy()
              reg_predictor_cfg_.update(
                  in_features=self.reg_last_dim[k],
                  out_features=out_dim_reg,
              )
              self.fc_reg.append(MODELS.build(reg_predictor_cfg_))
              if self.with_refine:
                  self.fc_reg_ref.append(
                      MODELS.build(reg_predictor_cfg_)
                  )
  
      if init_cfg is None:
          # when init_cfg is None,
          # It has been set to
          # [[dict(type='Normal', std=0.01, override=dict(name='fc_cls'))],
          #  [dict(type='Normal', std=0.001, override=dict(name='fc_reg'))]
          # after `super(ConvFCBBoxHead, self).__init__()`
          # we only need to append additional configuration
          # for `shared_fcs`, `cls_fcs` and `reg_fcs`
          self.init_cfg += [
              dict(
                  type="Xavier",
                  distribution="uniform",
                  override=[
                      dict(name="shared_fcs"),
                      dict(name="cls_fcs"),
                      dict(name="reg_fcs"),
                  ],
              )
          ]
  
imports: from typing import List, Optional, Tuple, Union
  import numpy
  import torch
  import torch.nn.functional
  from mmcv.cnn import ConvModule
  from mmengine.config import ConfigDict
  from mmengine.structures import InstanceData
  from torch import Tensor, nn
  from mmdet.models.roi_heads.bbox_heads.bbox_head import BBoxHead
  from mmdet.models.task_modules.samplers import SamplingResult
  from mmdet.models.utils import empty_instances
  from mmdet.registry import MODELS
  from mmdet.structures.bbox import bbox_overlaps
label_desc: Use image node_id 1 to create a new MultiInstanceBBoxHead object from inherited base classes: BBoxHead with example: obj = MultiInstanceBBoxHead(num_instance, with_refine, num_shared_convs, num_shared_fcs, num_cls_convs, num_cls_fcs, num_reg_convs, num_reg_fcs, conv_out_channels, fc_out_channels, init_cfg)