open-mmlab/mmdetection · error · NotImplementedError

Albu only supports horizontal boxes now

Error message

Albu only supports horizontal boxes now

What it means

Albu's preprocessing requires results['bboxes'] to be an mmdet HorizontalBoxes instance (new data structure in mmdet 3.x). Legacy list/ndarray box formats raise NotImplementedError.

Source

Thrown at mmdet/datasets/transforms/transforms.py:1713

        # TODO: gt_seg_map is not currently supported
        # dict to albumentations format
        results = self.mapper(results, self.keymap_to_albu)
        results, ori_masks = self._preprocess_results(results)
        results = self.aug(**results)
        results = self._postprocess_results(results, ori_masks)
        if results is None:
            return None
        # back to the original format
        results = self.mapper(results, self.keymap_back)
        results['img_shape'] = results['img'].shape[:2]
        return results

    def _preprocess_results(self, results: dict) -> tuple:
        """Pre-processing results to facilitate the use of Albu."""
        if 'bboxes' in results:
            # to list of boxes
            if not isinstance(results['bboxes'], HorizontalBoxes):
                raise NotImplementedError(
                    'Albu only supports horizontal boxes now')
            bboxes = results['bboxes'].numpy()
            results['bboxes'] = [x for x in bboxes]
            # add pseudo-field for filtration
            if self.filter_lost_elements:
                results['idx_mapper'] = np.arange(len(results['bboxes']))

        # TODO: Support mask structure in albu
        ori_masks = None
        if 'masks' in results:
            if isinstance(results['masks'], PolygonMasks):
                raise NotImplementedError(
                    'Albu only supports BitMap masks now')
            ori_masks = results['masks']
            if albumentations.__version__ < '0.5':
                results['masks'] = results['masks'].masks
            else:
                results['masks'] = [mask for mask in results['masks'].masks]

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Ensure Albu comes after LoadAnnotations and the standard box conversion so 'bboxes' is a HorizontalBoxes
  2. Wrap boxes manually: HorizontalBoxes(np.array(bboxes, dtype=np.float32))
  3. Use mmdet 3.x-native pipeline order from official configs

Example fix

# before
results['bboxes'] = np.array([[0,0,10,10]], dtype=np.float32)
albu.transform(results)  # raises
# after
from mmdet.structures.bbox import HorizontalBoxes
results['bboxes'] = HorizontalBoxes(np.array([[0,0,10,10]], dtype=np.float32))
Defensive patterns

Strategy: type-guard

Validate before calling

from mmdet.structures.bbox import HorizontalBoxes
assert isinstance(results.get('bboxes'), HorizontalBoxes), 'need HorizontalBoxes'

Type guard

from mmdet.structures.bbox import HorizontalBoxes
def has_horizontal_boxes(results):
    return isinstance(results.get('bboxes'), HorizontalBoxes)

Prevention

When it happens

Trigger: Calling Albu.transform on a results dict whose 'bboxes' is a plain list or np.ndarray instead of HorizontalBoxes — e.g. calling the transform manually or in a custom pipeline that skipped LoadAnnotations/pack structure conversion.

Common situations: Migrating 2.x pipelines, custom pipelines inserting Albu before boxes are converted to HorizontalBoxes, or unit tests calling transforms directly with raw dicts.

Related errors


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