open-mmlab/mmdetection · warning

The `in_channels` of SOLOv2MaskFeatHead and SOLOv2Head shoul

Error message

The `in_channels` of SOLOv2MaskFeatHead and SOLOv2Head should be same, changing mask_feature_head.in_channels to {self.in_channels}

What it means

SOLOv2Head warns that the in_channels of its mask_feature_head differs from the head's own in_channels, and force-overwrites mask_feature_head.in_channels to match. SOLOv2 requires both to agree so the mask feature branch aligns with the kernel prediction branch.

Source

Thrown at mmdet/models/dense_heads/solov2_head.py:214

                         bias_prob=0.01,
                         override=dict(name='conv_cls'))
                 ],
                 **kwargs) -> None:
        assert dcn_cfg is None or isinstance(dcn_cfg, dict)
        self.dcn_cfg = dcn_cfg
        self.with_dcn = dcn_cfg is not None
        self.dcn_apply_to_all_conv = dcn_apply_to_all_conv
        self.dynamic_conv_size = dynamic_conv_size
        mask_out_channels = mask_feature_head.get('out_channels')
        self.kernel_out_channels = \
            mask_out_channels * self.dynamic_conv_size * self.dynamic_conv_size

        super().__init__(*args, init_cfg=init_cfg, **kwargs)

        # update the in_channels of mask_feature_head
        if mask_feature_head.get('in_channels', None) is not None:
            if mask_feature_head.in_channels != self.in_channels:
                warnings.warn('The `in_channels` of SOLOv2MaskFeatHead and '
                              'SOLOv2Head should be same, changing '
                              'mask_feature_head.in_channels to '
                              f'{self.in_channels}')
                mask_feature_head.update(in_channels=self.in_channels)
        else:
            mask_feature_head.update(in_channels=self.in_channels)

        self.mask_feature_head = MaskFeatModule(**mask_feature_head)
        self.mask_stride = self.mask_feature_head.mask_stride
        self.fp16_enabled = False

    def _init_layers(self) -> None:
        """Initialize layers of the head."""
        self.cls_convs = nn.ModuleList()
        self.kernel_convs = nn.ModuleList()
        conv_cfg = None
        for i in range(self.stacked_convs):
            if self.with_dcn:

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Set mask_feature_head.in_channels equal to the head's in_channels in the config
  2. Verify the neck's out_channels matches both values

Example fix

# before
mask_head=dict(type='SOLOv2Head', in_channels=256, mask_feature_head=dict(in_channels=128, ...))
# after
mask_head=dict(type='SOLOv2Head', in_channels=256, mask_feature_head=dict(in_channels=256, ...))
Defensive patterns

Strategy: validation

Validate before calling

head_cfg = cfg['model']['roi_head']['bbox_head']
mfh = head_cfg.get('mask_feature_head', {})
if mfh.get('in_channels') is not None:
    assert mfh['in_channels'] == head_cfg['in_channels'], 'SOLOv2 in_channels mismatch'

Prevention

When it happens

Trigger: Configuring SOLOv2 with mask_feat_head=dict(in_channels=X, ...) where X != the head's in_channels=Y.

Common situations: Copying a SOLOv2 config and changing one in_channels (e.g. backbone output channels) but not the mask_feature_head's; custom backbone necks producing different channel counts.

Related errors


AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27). Data as JSON: /api/errors/2d9cc946a3649f31. Report an issue: GitHub.