indoor_augment.py 6.76 KB
Newer Older
liyinhao's avatar
liyinhao committed
1
2
import numpy as np

3
from mmdet.datasets.builder import PIPELINES
liyinhao's avatar
liyinhao committed
4
5


6
@PIPELINES.register_module()
7
class IndoorFlipData(object):
liyinhao's avatar
liyinhao committed
8
    """Indoor flip data.
9

liyinhao's avatar
liyinhao committed
10
    Flip point cloud and ground truth boxes.
liyinhao's avatar
liyinhao committed
11
    The point cloud will be flipped along the yz plane
liyinhao's avatar
liyinhao committed
12
    and the xz plane with a certain probability.
13
14

    Args:
liyinhao's avatar
liyinhao committed
15
16
17
        flip_ratio_yz (float): Probability of being flipped along yz plane.
            Default: 0.5.
        flip_ratio_xz (float): Probability of being flipped along xz plane.
liyinhao's avatar
liyinhao committed
18
            Default: 0.5.
19
20
    """

liyinhao's avatar
liyinhao committed
21
22
23
    def __init__(self, flip_ratio_yz=0.5, flip_ratio_xz=0.5):
        self.flip_ratio_yz = flip_ratio_yz
        self.flip_ratio_xz = flip_ratio_xz
24
25

    def __call__(self, results):
26
27
        points = results['points']
        gt_bboxes_3d = results['gt_bboxes_3d']
liyinhao's avatar
liyinhao committed
28
29
        results['flip_yz'] = False
        results['flip_xz'] = False
liyinhao's avatar
liyinhao committed
30
        if np.random.random() < self.flip_ratio_yz:
31
            # Flipping along the YZ plane
liyinhao's avatar
liyinhao committed
32
            points[:, 0] = -1 * points[:, 0]
wuyuefeng's avatar
wuyuefeng committed
33
            gt_bboxes_3d.flip('horizontal')
liyinhao's avatar
liyinhao committed
34
            results['flip_yz'] = True
35

wuyuefeng's avatar
wuyuefeng committed
36
37
        if not gt_bboxes_3d.with_yaw and np.random.random(
        ) < self.flip_ratio_xz:
38
            # Flipping along the XZ plane
liyinhao's avatar
liyinhao committed
39
            points[:, 1] = -1 * points[:, 1]
wuyuefeng's avatar
wuyuefeng committed
40
            gt_bboxes_3d.flip('vertical')
liyinhao's avatar
liyinhao committed
41
            results['flip_xz'] = True
42

liyinhao's avatar
liyinhao committed
43
44
        results['points'] = points
        results['gt_bboxes_3d'] = gt_bboxes_3d
45
46
47
48
        return results

    def __repr__(self):
        repr_str = self.__class__.__name__
liyinhao's avatar
liyinhao committed
49
50
        repr_str += '(flip_ratio_yz={})'.format(self.flip_ratio_yz)
        repr_str += '(flip_ratio_xz={})'.format(self.flip_ratio_xz)
51
52
53
        return repr_str


liyinhao's avatar
liyinhao committed
54
@PIPELINES.register_module()
liyinhao's avatar
liyinhao committed
55
class IndoorPointsColorJitter(object):
liyinhao's avatar
liyinhao committed
56
    """Indoor points color jitter.
liyinhao's avatar
liyinhao committed
57

liyinhao's avatar
liyinhao committed
58
59
    Randomly change the brightness and color of the point cloud, and
    drop out the points' colors with a certain range and probability.
liyinhao's avatar
liyinhao committed
60
61

    Args:
liyinhao's avatar
liyinhao committed
62
        color_mean (list[float]): Mean color of the point cloud.
liyinhao's avatar
liyinhao committed
63
            Default: [0.5, 0.5, 0.5].
liyinhao's avatar
liyinhao committed
64
        bright_range (list[float]): Range of brightness.
liyinhao's avatar
liyinhao committed
65
            Default: [0.8, 1.2].
liyinhao's avatar
liyinhao committed
66
        color_shift_range (list[float]): Range of color shift.
liyinhao's avatar
liyinhao committed
67
            Default: [0.95, 1.05].
liyinhao's avatar
liyinhao committed
68
        jitter_range (list[float]): Range of jittering.
liyinhao's avatar
liyinhao committed
69
            Default: [-0.025, 0.025].
70
        drop_prob (float): Probability to drop out points' color.
liyinhao's avatar
liyinhao committed
71
72
73
74
75
76
77
78
            Default: 0.3
    """

    def __init__(self,
                 color_mean=[0.5, 0.5, 0.5],
                 bright_range=[0.8, 1.2],
                 color_shift_range=[0.95, 1.05],
                 jitter_range=[-0.025, 0.025],
79
                 drop_prob=0.3):
liyinhao's avatar
liyinhao committed
80
81
82
83
        self.color_mean = color_mean
        self.bright_range = bright_range
        self.color_shift_range = color_shift_range
        self.jitter_range = jitter_range
84
        self.drop_prob = drop_prob
liyinhao's avatar
liyinhao committed
85
86

    def __call__(self, results):
87
        points = results['points']
liyinhao's avatar
liyinhao committed
88
89
        assert points.shape[1] >= 6, \
            f'Expect points have channel >=6, got {points.shape[1]}.'
liyinhao's avatar
liyinhao committed
90
91
92
93
94
95
96
97
98
99
100
101
102
        rgb_color = points[:, 3:6] + self.color_mean
        # brightness change for each channel
        rgb_color *= np.random.uniform(self.bright_range[0],
                                       self.bright_range[1], 3)
        # color shift for each channel
        rgb_color += np.random.uniform(self.color_shift_range[0],
                                       self.color_shift_range[1], 3)
        # jittering on each pixel
        rgb_color += np.expand_dims(
            np.random.uniform(self.jitter_range[0], self.jitter_range[1]), -1)
        rgb_color = np.clip(rgb_color, 0, 1)
        # randomly drop out points' colors
        rgb_color *= np.expand_dims(
103
            np.random.random(points.shape[0]) > self.drop_prob, -1)
liyinhao's avatar
liyinhao committed
104
105
106
107
108
109
110
111
112
113
        points[:, 3:6] = rgb_color - self.color_mean
        results['points'] = points
        return results

    def __repr__(self):
        repr_str = self.__class__.__name__
        repr_str += '(color_mean={})'.format(self.color_mean)
        repr_str += '(bright_range={})'.format(self.bright_range)
        repr_str += '(color_shift_range={})'.format(self.color_shift_range)
        repr_str += '(jitter_range={})'.format(self.jitter_range)
114
        repr_str += '(drop_prob={})'.format(self.drop_prob)
liyinhao's avatar
liyinhao committed
115
116


117
118
119
120
# TODO: merge outdoor indoor transform.
# TODO: try transform noise.
@PIPELINES.register_module()
class IndoorGlobalRotScale(object):
liyinhao's avatar
liyinhao committed
121
    """Indoor global rotate and scale.
122
123

    Augment sunrgbd and scannet data with global rotating and scaling.
124
125

    Args:
zhangwenwei's avatar
zhangwenwei committed
126
        shift_height (bool): Whether to use height.
liyinhao's avatar
liyinhao committed
127
            Default: True.
liyinhao's avatar
liyinhao committed
128
        rot_range (list[float]): Range of rotation.
liyinhao's avatar
liyinhao committed
129
            Default: None.
liyinhao's avatar
liyinhao committed
130
        scale_range (list[float]): Range of scale.
liyinhao's avatar
liyinhao committed
131
            Default: None.
132
133
    """

zhangwenwei's avatar
zhangwenwei committed
134
135
    def __init__(self, shift_height=True, rot_range=None, scale_range=None):
        self.shift_height = shift_height
liyinhao's avatar
liyinhao committed
136
        self.rot_range = np.pi * np.array(rot_range)
liyinhao's avatar
liyinhao committed
137
138
        self.scale_range = scale_range

liyinhao's avatar
liyinhao committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
    def _rotz(self, 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

155
    def __call__(self, results):
156
157
        points = results['points']
        gt_bboxes_3d = results['gt_bboxes_3d']
liyinhao's avatar
liyinhao committed
158

liyinhao's avatar
liyinhao committed
159
        if self.rot_range is not None:
liyinhao's avatar
liyinhao committed
160
            assert len(self.rot_range) == 2, \
liyinhao's avatar
liyinhao committed
161
                f'Expect length of rot range =2, ' \
liyinhao's avatar
liyinhao committed
162
                f'got {len(self.rot_range)}.'
liyinhao's avatar
liyinhao committed
163
            rot_angle = np.random.uniform(self.rot_range[0], self.rot_range[1])
wuyuefeng's avatar
wuyuefeng committed
164
165
166
            if gt_bboxes_3d.tensor.shape[0] != 0:
                gt_bboxes_3d.rotate(rot_angle)
            points[:, :3] = np.dot(points[:, :3], self._rotz(rot_angle).T)
liyinhao's avatar
liyinhao committed
167
            results['rot_angle'] = rot_angle
liyinhao's avatar
liyinhao committed
168

liyinhao's avatar
liyinhao committed
169
        if self.scale_range is not None:
liyinhao's avatar
liyinhao committed
170
            assert len(self.scale_range) == 2, \
liyinhao's avatar
liyinhao committed
171
                f'Expect length of scale range =2, ' \
liyinhao's avatar
liyinhao committed
172
                f'got {len(self.scale_range)}.'
liyinhao's avatar
liyinhao committed
173
            # Augment point cloud scale
liyinhao's avatar
liyinhao committed
174
175
            scale_ratio = np.random.uniform(self.scale_range[0],
                                            self.scale_range[1])
176

liyinhao's avatar
liyinhao committed
177
            points[:, :3] *= scale_ratio
wuyuefeng's avatar
wuyuefeng committed
178
            gt_bboxes_3d.scale(scale_ratio)
zhangwenwei's avatar
zhangwenwei committed
179
            if self.shift_height:
180
                points[:, -1] *= scale_ratio
liyinhao's avatar
liyinhao committed
181

liyinhao's avatar
liyinhao committed
182
183
            results['scale_ratio'] = scale_ratio

liyinhao's avatar
liyinhao committed
184
        results['points'] = points
wuyuefeng's avatar
wuyuefeng committed
185
        results['gt_bboxes_3d'] = gt_bboxes_3d
186
187
188
189
        return results

    def __repr__(self):
        repr_str = self.__class__.__name__
zhangwenwei's avatar
zhangwenwei committed
190
        repr_str += '(shift_height={})'.format(self.shift_height)
liyinhao's avatar
liyinhao committed
191
192
        repr_str += '(rot_range={})'.format(self.rot_range)
        repr_str += '(scale_range={})'.format(self.scale_range)
193
        return repr_str