dataset_wrappers.py 2.78 KB
Newer Older
dingchang's avatar
dingchang committed
1
# Copyright (c) OpenMMLab. All rights reserved.
yinchimaoliang's avatar
yinchimaoliang committed
2
3
import numpy as np

4
from mmdet3d.registry import DATASETS
yinchimaoliang's avatar
yinchimaoliang committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


@DATASETS.register_module()
class CBGSDataset(object):
    """A wrapper of class sampled dataset with ann_file path. Implementation of
    paper `Class-balanced Grouping and Sampling for Point Cloud 3D Object
    Detection <https://arxiv.org/abs/1908.09492.>`_.

    Balance the number of scenes under different classes.

    Args:
        dataset (:obj:`CustomDataset`): The dataset to be class sampled.
    """

    def __init__(self, dataset):
20
        self.dataset = DATASETS.build(dataset)
21
22
        self.metainfo = self.dataset.metainfo
        self.CLASSES = self.metainfo['CLASSES']
23
        self.cat2id = {name: i for i, name in enumerate(self.CLASSES)}
yinchimaoliang's avatar
yinchimaoliang committed
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
        self.sample_indices = self._get_sample_indices()
        # self.dataset.data_infos = self.data_infos
        if hasattr(self.dataset, 'flag'):
            self.flag = np.array(
                [self.dataset.flag[ind] for ind in self.sample_indices],
                dtype=np.uint8)

    def _get_sample_indices(self):
        """Load annotations from ann_file.

        Args:
            ann_file (str): Path of the annotation file.

        Returns:
            list[dict]: List of annotations after class sampling.
        """
40
        class_sample_idxs = {cat_id: [] for cat_id in self.cat2id.values()}
yinchimaoliang's avatar
yinchimaoliang committed
41
        for idx in range(len(self.dataset)):
42
43
            sample_cat_ids = self.dataset.get_cat_ids(idx)
            for cat_id in sample_cat_ids:
44
45
46
47
                if cat_id != -1:
                    # Filter categories that do not need to care.
                    # -1 indicate dontcare in MMDet3d.
                    class_sample_idxs[cat_id].append(idx)
48
49
        duplicated_samples = sum(
            [len(v) for _, v in class_sample_idxs.items()])
yinchimaoliang's avatar
yinchimaoliang committed
50
51
        class_distribution = {
            k: len(v) / duplicated_samples
52
            for k, v in class_sample_idxs.items()
yinchimaoliang's avatar
yinchimaoliang committed
53
54
55
56
57
58
        }

        sample_indices = []

        frac = 1.0 / len(self.CLASSES)
        ratios = [frac / v for v in class_distribution.values()]
59
        for cls_inds, ratio in zip(list(class_sample_idxs.values()), ratios):
yinchimaoliang's avatar
yinchimaoliang committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
            sample_indices += np.random.choice(cls_inds,
                                               int(len(cls_inds) *
                                                   ratio)).tolist()
        return sample_indices

    def __getitem__(self, idx):
        """Get item from infos according to the given index.

        Returns:
            dict: Data dictionary of the corresponding index.
        """
        ori_idx = self.sample_indices[idx]
        return self.dataset[ori_idx]

    def __len__(self):
        """Return the length of data infos.

        Returns:
            int: Length of data infos.
        """
        return len(self.sample_indices)