class_docstr: More general bbox head, with shared conv and fc layers and two optional
  separated branches.
  
  .. code-block:: none
  
                                  /-> cls convs -> cls fcs -> cls
      shared convs -> shared fcs
                                  \-> reg convs -> reg fcs -> reg
class_docstr_tok: ["More","general","bbox","head",",","with","shared","conv","and","fc","layers","and","two","optional","separated","branches",".","..","code-block",":",":","none","\/-",">","cls","convs","-",">","cls","fcs","-",">","cls","shared","convs","-",">","shared","fcs","\\-",">","reg","convs","-",">","reg","fcs","-",">","reg"]
code: def __init__(
      self,
      num_shared_convs: int = 0,
      num_shared_fcs: int = 0,
      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,
      conv_cfg: Optional[Union[dict, ConfigDict]] = None,
      norm_cfg: Optional[Union[dict, ConfigDict]] = None,
      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
      )
      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_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.conv_cfg = conv_cfg
      self.norm_cfg = norm_cfg
  
      # 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
  
      # add cls specific branch
      (
          self.cls_convs,
          self.cls_fcs,
          self.cls_last_dim,
      ) = self._add_conv_fc_branch(
          self.num_cls_convs, self.num_cls_fcs, self.shared_out_channels
      )
  
      # add reg specific branch
      (
          self.reg_convs,
          self.reg_fcs,
          self.reg_last_dim,
      ) = self._add_conv_fc_branch(
          self.num_reg_convs, self.num_reg_fcs, self.shared_out_channels
      )
  
      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
  
      self.relu = nn.ReLU(inplace=True)
      # reconstruct fc_cls and fc_reg since input channels are changed
      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()
          cls_predictor_cfg_.update(
              in_features=self.cls_last_dim, out_features=cls_channels
          )
          self.fc_cls = MODELS.build(cls_predictor_cfg_)
      if self.with_reg:
          box_dim = self.bbox_coder.encode_size
          out_dim_reg = (
              box_dim
              if self.reg_class_agnostic
              else box_dim * self.num_classes
          )
          reg_predictor_cfg_ = self.reg_predictor_cfg.copy()
          if isinstance(reg_predictor_cfg_, (dict, ConfigDict)):
              reg_predictor_cfg_.update(
                  in_features=self.reg_last_dim,
                  out_features=out_dim_reg,
              )
          self.fc_reg = 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"),
                  ],
              )
          ]
  
file_path: mmdetection/mmdet/models/roi_heads/bbox_heads/convfc_bbox_head.py
imports: from typing import Optional, Tuple, Union
  import torch.nn
  from mmcv.cnn import ConvModule
  from mmengine.config import ConfigDict
  from torch import Tensor
  from mmdet.registry import MODELS
  from .bbox_head import BBoxHead
label_desc: Use image node_id 1 to create a new ConvFCBBoxHead object from inherited base classes: BBoxHead with example: obj = ConvFCBBoxHead(num_shared_convs, num_shared_fcs, num_cls_convs, num_cls_fcs, num_reg_convs, num_reg_fcs, conv_out_channels, fc_out_channels, conv_cfg, norm_cfg, init_cfg)