indoor_augment.py 3.79 KB
Newer Older
liyinhao's avatar
liyinhao committed
1
2
3
4
5
import numpy as np

from mmdet.datasets.registry import PIPELINES


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def _rotz(t):
    """Rotate About Z.

    Rotation about the z-axis.

    Args:
        t (float): Angle of rotation.

    Returns:
        rot_mat (ndarray): Matrix of rotation.
    """
    c = np.cos(t)
    s = np.sin(t)
    rot_mat = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
    return rot_mat


def _rotate_aligned_boxes(input_boxes, rot_mat):
    centers, lengths = input_boxes[:, 0:3], input_boxes[:, 3:6]
    new_centers = np.dot(centers, np.transpose(rot_mat))

    dx, dy = lengths[:, 0] / 2.0, lengths[:, 1] / 2.0
    new_x = np.zeros((dx.shape[0], 4))
    new_y = np.zeros((dx.shape[0], 4))

    for i, crnr in enumerate([(-1, -1), (1, -1), (1, 1), (-1, 1)]):
        crnrs = np.zeros((dx.shape[0], 3))
        crnrs[:, 0] = crnr[0] * dx
        crnrs[:, 1] = crnr[1] * dy
        crnrs = np.dot(crnrs, np.transpose(rot_mat))
        new_x[:, i] = crnrs[:, 0]
        new_y[:, i] = crnrs[:, 1]

    new_dx = 2.0 * np.max(new_x, 1)
    new_dy = 2.0 * np.max(new_y, 1)
    new_lengths = np.stack((new_dx, new_dy, lengths[:, 2]), axis=1)

    return np.concatenate([new_centers, new_lengths], axis=1)


liyinhao's avatar
liyinhao committed
46
47
48
49
@PIPELINES.register_module()
class IndoorFlipData(object):
    """Indoor Flip Data

50
    Flip points and groundtruth boxes.
liyinhao's avatar
liyinhao committed
51
52
53
54
55
56
57
58
59
60

    Args:
        name (str): name of the dataset.
    """

    def __init__(self, name):
        assert name in ['scannet', 'sunrgbd']
        self.name = name

    def __call__(self, results):
61
        points = results.get('points', None)
liyinhao's avatar
liyinhao committed
62
63
64
        gt_boxes = results.get('gt_boxes', None)
        if np.random.random() > 0.5:
            # Flipping along the YZ plane
65
            points[:, 0] = -1 * points[:, 0]
liyinhao's avatar
liyinhao committed
66
67
68
69
70
71
            gt_boxes[:, 0] = -1 * gt_boxes[:, 0]
            if self.name == 'sunrgbd':
                gt_boxes[:, 6] = np.pi - gt_boxes[:, 6]
            results['gt_boxes'] = gt_boxes
        if self.name == 'scannet' and np.random.random() > 0.5:
            # Flipping along the XZ plane
72
            points[:, 1] = -1 * points[:, 1]
liyinhao's avatar
liyinhao committed
73
74
            gt_boxes[:, 1] = -1 * gt_boxes[:, 1]
            results['gt_boxes'] = gt_boxes
75
        results['points'] = points
liyinhao's avatar
liyinhao committed
76
77
78
79
80
81
82

        return results

    def __repr__(self):
        repr_str = self.__class__.__name__
        repr_str += '(dataset_name={})'.format(self.name)
        return repr_str
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139


@PIPELINES.register_module()
class IndoorRotateData(object):
    """Indoor Rotate Data

    Rotate points and groundtruth boxes.

    Args:
        name (str): name of the dataset.
    """

    def __init__(self, name):
        assert name in ['scannet', 'sunrgbd']
        self.name = name

    def __call__(self, results):
        points = results.get('points', None)
        gt_boxes = results.get('gt_boxes', None)
        rot_angle = (np.random.random() * np.pi /
                     3) - np.pi / 6  # -30 ~ +30 degree
        rot_mat = _rotz(rot_angle)
        points[:, 0:3] = np.dot(points[:, 0:3], np.transpose(rot_mat))
        if self.name == 'scannet':
            gt_boxes = _rotate_aligned_boxes(gt_boxes, rot_mat)
        else:
            gt_boxes[:, 0:3] = np.dot(gt_boxes[:, 0:3], np.transpose(rot_mat))
            gt_boxes[:, 6] -= rot_angle
        results['points'] = points
        results['gt_boxes'] = gt_boxes
        return results

    def __repr__(self):
        repr_str = self.__class__.__name__
        repr_str += '(dataset_name={})'.format(self.name)
        return repr_str


@PIPELINES.register_module()
class IndoorShuffleData(object):
    """Indoor Shuffle Data

    Shuffle points.
    """

    def __init__(self):
        pass

    def __call__(self, results):
        points = results.get('points')
        np.random.shuffle(points)
        results['points'] = points
        return results

    def __repr__(self):
        repr_str = self.__class__.__name__
        return repr_str