indoor_augment.py 3.8 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
        gt_boxes = results.get('gt_boxes', None)
liyinhao's avatar
liyinhao committed
63

liyinhao's avatar
liyinhao committed
64
65
        if np.random.random() > 0.5:
            # Flipping along the YZ plane
66
            points[:, 0] = -1 * points[:, 0]
liyinhao's avatar
liyinhao committed
67
68
69
70
            gt_boxes[:, 0] = -1 * gt_boxes[:, 0]
            if self.name == 'sunrgbd':
                gt_boxes[:, 6] = np.pi - gt_boxes[:, 6]
            results['gt_boxes'] = gt_boxes
liyinhao's avatar
liyinhao committed
71

liyinhao's avatar
liyinhao committed
72
73
        if self.name == 'scannet' and np.random.random() > 0.5:
            # Flipping along the XZ plane
74
            points[:, 1] = -1 * points[:, 1]
liyinhao's avatar
liyinhao committed
75
76
            gt_boxes[:, 1] = -1 * gt_boxes[:, 1]
            results['gt_boxes'] = gt_boxes
77
        results['points'] = points
liyinhao's avatar
liyinhao committed
78
79
80
81
82
83
84

        return results

    def __repr__(self):
        repr_str = self.__class__.__name__
        repr_str += '(dataset_name={})'.format(self.name)
        return repr_str
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107


@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))
liyinhao's avatar
liyinhao committed
108

109
110
111
112
113
        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
liyinhao's avatar
liyinhao committed
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
140
141
142
143
        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