Ejemplo n.º 1
0
def get_boxes_3D(path, class_to_group):
    # Load labels from txt file
    df = pd.read_csv(path,
                     names=KITTI_COLUMN_NAMES,
                     header=None,
                     delim_whitespace=True)

    # Convert label to list of Box3D
    gt_boxes_3D = []
    for _, row in df.iterrows():
        if row['Type'] in class_to_group:
            gt_boxes_3D += [
                Box3D(row['3D_H'],
                      row['3D_W'],
                      row['3D_L'],
                      row['3D_X'],
                      row['3D_Y'],
                      row['3D_Z'],
                      row['Rot_Y'],
                      cls=class_to_group[row['Type']])
            ]
    return gt_boxes_3D
Ejemplo n.º 2
0
box_limits = []
all_limits = []
rand_num = 30
random_cars_dir = 'data_utils/aug_utils/annotations/cars/'
random_cars = os.listdir(random_cars_dir)
np.random.seed(0)
random_cars = np.random.choice(random_cars, size=rand_num)

sampled_cars = []
for random_car in random_cars:
    sampled_car = dd.io.load(os.path.join(random_cars_dir, random_car))
    sampled_pts = sampled_car['pts'].T
    sampled_box = Box3D(h=sampled_car['box_h'],
                        w=sampled_car['box_w'],
                        l=sampled_car['box_l'],
                        x=sampled_car['box_x'],
                        y=sampled_car['box_y'],
                        z=sampled_car['box_z'],
                        yaw=sampled_car['box_yaw'],
                        cls=sampled_car['box_cls'])
    data = {
        'pts': sampled_pts,
        'num_pts': sampled_pts.shape[1],
        'box': sampled_box,
        'bev_corners': sampled_box.get_bev_box().T,
        'bev_center': sampled_box.get_bev_center(),
    }
    sampled_cars.append(data)

sampled_cars = sorted(sampled_cars, key=itemgetter('num_pts'), reverse=False)

Ejemplo n.º 3
0
    def decode(self, target, confidence_thresh):
        boxes_3D = []
        cls_map = np.rot90(target[..., 0], -1)
        cls_map_flat = cls_map.flatten()
        geometry_map = np.rot90(target[..., 1:], -1)
        for positive_pt in self.feature_map_pts[
                cls_map_flat > confidence_thresh]:
            # Denormalize
            # geometry_map[positive_pt[1], positive_pt[0]] *= self.target_stds
            # geometry_map[positive_pt[1], positive_pt[0]] += self.target_means

            # Offset
            z = positive_pt[0] / self.qf[0]  # Convert to physical space
            x = positive_pt[1] / self.qf[
                1] - self.P_HEIGHT / 2  # Convert to physical space and move reference frame from top to middle
            z -= self.__denormalize(
                'dz', geometry_map[positive_pt[1], positive_pt[0], 2])
            x -= self.__denormalize(
                'dx', geometry_map[positive_pt[1], positive_pt[0], 3])
            y = self.__denormalize(
                'alt', geometry_map[positive_pt[1], positive_pt[0], 4])

            # # # Size
            # # scaling ratio experiment
            # w1 = np.exp(geometry_map[positive_pt[1], positive_pt[0], 8] * self.stats['mean']['log_w'])
            # l1 = np.exp(geometry_map[positive_pt[1], positive_pt[0], 9] * self.stats['mean']['log_l'])
            # h1 = np.exp(geometry_map[positive_pt[1], positive_pt[0], 10] * self.stats['mean']['log_h'])

            # ap = np.log(w1) * np.log(l1)
            # at = self.stats['mean']['log_w'] * self.stats['mean']['log_l']
            # if ap < at / 3:
            #     continue

            # # # Size
            # # # w, l = np.exp(geometry_map[positive_pt[1], positive_pt[0], (4, 5)])
            w = np.exp(
                self.__denormalize(
                    'log_w', geometry_map[positive_pt[1], positive_pt[0], 5]))
            l = np.exp(
                self.__denormalize(
                    'log_l', geometry_map[positive_pt[1], positive_pt[0], 6]))
            h = np.exp(
                self.__denormalize(
                    'log_h', geometry_map[positive_pt[1], positive_pt[0], 7]))

            # w = np.mean([w1, w])#w1#
            # l = np.mean([l1, l])#l1#
            # h = np.mean([h1, h])#h1#

            yaw_dir = geometry_map[positive_pt[1], positive_pt[0], 8]
            if yaw_dir > 0:
                yaw_dir = 1
            else:
                yaw_dir = -1
            # Angle
            yaw = np.arctan2(
                self.__denormalize(
                    'sin', geometry_map[positive_pt[1], positive_pt[0], 1]),
                self.__denormalize(
                    'cos', geometry_map[positive_pt[1], positive_pt[0],
                                        0])) * yaw_dir

            decoded_box = Box3D(h=h,
                                w=w,
                                l=l,
                                x=x,
                                y=y,
                                z=z,
                                yaw=yaw,
                                confidence=cls_map[positive_pt[1],
                                                   positive_pt[0]],
                                cls='Car')
            boxes_3D.append(decoded_box)
        return boxes_3D
Ejemplo n.º 4
0
    def __generate_map(self, target_box):
        inner_box = Box3D(h=target_box.h,
                          w=target_box.w * self.subsampling_factor[0],
                          l=target_box.l * self.subsampling_factor[0],
                          x=target_box.x,
                          y=target_box.y,
                          z=target_box.z,
                          yaw=target_box.yaw,
                          cls=target_box.cls)

        outer_box = Box3D(h=target_box.h,
                          w=target_box.w * self.subsampling_factor[1],
                          l=target_box.l * self.subsampling_factor[1],
                          x=target_box.x,
                          y=target_box.y,
                          z=target_box.z,
                          yaw=target_box.yaw,
                          cls=target_box.cls)

        # Obj mask - (0 - ignore, 1 - consider in loss)
        inner_mask = self.__get_positive_pts_mask(inner_box)
        outer_mask = self.__get_positive_pts_mask(outer_box)
        obj_mask = np.logical_not(np.logical_xor(inner_mask, outer_mask))

        # Generate corresponding geometry map for pts in rectangle
        # cos, sin, z, x, width, length, y, h
        # y, h - are not regressed in original paper

        # Geo mask (0 - ignore, 1 - positive)
        geo_mask = self.__get_positive_pts_mask(target_box)

        geometry_map = np.zeros(shape=(self.target_height, self.target_width,
                                       self.num_channels),
                                dtype=np.float32)
        # Generate corresponding geometry map for pts in rectangle
        for positive_pt in self.feature_map_pts[geo_mask]:
            # Angle
            # replacing (theta) -> (2 * theta) as proposed by BoxNet paper
            if target_box.yaw > 0:
                yaw_dir = 1
            else:
                yaw_dir = -1
            # should be values between [-1, 1]
            # geometry_map[positive_pt[1], positive_pt[0], (0, 1)] = (np.cos(box_3D.yaw), np.sin(box_3D.yaw))
            geometry_map[positive_pt[1], positive_pt[0],
                         (0, 1)] = (self.__normalize(
                             'cos', np.cos(target_box.yaw * yaw_dir)),
                                    self.__normalize(
                                        'sin',
                                        np.sin(target_box.yaw * yaw_dir)))

            # Offset from center
            physical_z = positive_pt[0] / self.qf[
                0]  # Convert to physical space
            physical_x = positive_pt[1] / self.qf[
                1] - 40  # Convert to physical space and move RF from top to middle
            # geometry_map[positive_pt[1], positive_pt[0], (2, 3)] = ((physical_z - box_3D.z), (physical_x - box_3D.x))
            geometry_map[positive_pt[1], positive_pt[0],
                         (2, 3,
                          4)] = (self.__normalize('dz',
                                                  physical_z - target_box.z),
                                 self.__normalize('dx',
                                                  physical_x - target_box.x),
                                 self.__normalize('alt', target_box.y))

            # # Width and Length
            # # geometry_map[positive_pt[1], positive_pt[0], (4, 5)] = (np.log(box_3D.w), np.log(box_3D.l))
            geometry_map[positive_pt[1], positive_pt[0],
                         (5,
                          6, 7)] = (self.__normalize('log_w',
                                                     np.log(target_box.w)),
                                    self.__normalize('log_l',
                                                     np.log(target_box.l)),
                                    self.__normalize('log_h',
                                                     np.log(target_box.h)))

            geometry_map[positive_pt[1], positive_pt[0], 8] = yaw_dir

            # # scaling ratio experiment
            # geometry_map[positive_pt[1], positive_pt[0], (8, 9,  10)] = (np.log(target_box.w) / self.stats['mean']['log_w'],
            #                                                             np.log(target_box.l) / self.stats['mean']['log_l'],
            #                                                             np.log(target_box.h) / self.stats['mean']['log_h'],)

            # # Normalize
            # geometry_map[positive_pt[1], positive_pt[0]] -= self.target_means
            # geometry_map[positive_pt[1], positive_pt[0]] /= self.target_stds

        # Reshape flat masks into 2D array
        obj_map = inner_mask.astype(np.float32).reshape(
            self.target_height, self.target_width)
        obj_mask = obj_mask.astype(np.float32).reshape(self.target_height,
                                                       self.target_width)
        geo_mask = geo_mask.astype(np.float32).reshape(self.target_height,
                                                       self.target_width)

        return obj_map, obj_mask, geometry_map, geo_mask
Ejemplo n.º 5
0
def add_random_sample(
        num_samples=30,
        sort=False,
        sort_desc=False,
        filter_wall_thresh=150,
        random_samples_dir='data_utils/aug_utils/annotations/cars/'):

    random_samples = os.listdir(random_samples_dir)
    random_samples = np.random.choice(random_samples, size=num_samples)

    samples = []

    for random_sample in random_samples:
        sample = dd.io.load(os.path.join(random_samples_dir, random_sample))
        sample_pts = sample['pts'].T
        sample_box = Box3D(h=sample['box_h'],
                           w=sample['box_w'],
                           l=sample['box_l'],
                           x=sample['box_x'],
                           y=sample['box_y'],
                           z=sample['box_z'],
                           yaw=sample['box_yaw'],
                           cls=sample['box_cls'])

        samples.append({
            'frame_id': sample['frame_id'],
            'pts': sample_pts,
            'num_pts': sample_pts.shape[1],
            'box': sample_box,
        })

    if sort:
        samples = sorted(samples, key=itemgetter('num_pts'), reverse=sort_desc)

    lidar_src = (0, 0)
    lidar_src_3d = (0, 0, 0)
    border_start = (70, 40)
    border_end = (70, -40)

    def _get_box_limits(box, name=None):
        diag1, diag2 = box.get_bev_diags()
        diag1_3d, diag2_3d = box.get_3d_diag()

        angle1 = get_angle_between_vectors(lidar_src, diag1[0], diag1[1])
        angle2 = get_angle_between_vectors(lidar_src, diag2[0], diag2[1])

        if angle1 > angle2:
            ref_diag = diag1
            diag_3d = diag1_3d
        else:
            ref_diag = diag2
            diag_3d = diag2_3d

        inter1_x, inter1_y, _, _, _ = find_intersection_point(
            border_start, border_end, lidar_src,
            (ref_diag[0][0], ref_diag[0][1]))

        inter2_x, inter2_y, _, _, _ = find_intersection_point(
            border_start, border_end, lidar_src,
            (ref_diag[1][0], ref_diag[1][1]))

        min_h = diag_3d[0][0][-1]
        max_h = diag_3d[1][0][-1]

        # if name is not None:
        #     all_limits.append(np.array([[inter1_y, 0, inter1_x],
        #                                 [0,0,0]]))

        #     all_limits.append(np.array([[inter2_y, 0, inter2_x],
        #                                 [0,0,0]]))

        # all_limits.append(np.array([[ref_diag[0][1], min_z, ref_diag[0][0]],
        #                             [0,0,0]]))

        # all_limits.append(np.array([[ref_diag[1][1], min_z, ref_diag[1][0]],
        #                             [0,0,0]]))

        return {
            'inter1': (inter1_x, inter1_y),
            'inter2': (inter2_x, inter2_y),
            'ref_diag': ref_diag,
            'max_h': max_h,
            'min_h': min_h,
        }

    def _add_random_sample(gt_boxes, pts, ref=None):

        if pts.shape[0] != 3:
            pts = pts.T

        ys = sorted([box.y for box in gt_boxes], reverse=False)
        median_y = np.median(ys)

        box_limits = []

        for box in gt_boxes:
            limit_dict = _get_box_limits(box)
            box_limits.append(limit_dict)

        valid_samples = []
        valid_samples_limits = {}
        for sample in samples:
            valid = True
            valid_samples_limits[sample['frame_id']] = []

            for limit in box_limits:
                (x1, y1) = limit['inter1']
                (x2, y2) = limit['inter2']
                box_bev = sample['box'].get_bev_box().T

                limit_p = Polygon([lidar_src, (x1, y1), (x2, y2)])
                box_p = Polygon([(box_bev[0][0], box_bev[0][1]),
                                 (box_bev[1][0], box_bev[1][1]),
                                 (box_bev[2][0], box_bev[2][1]),
                                 (box_bev[3][0], box_bev[3][1])])

                if limit_p.intersection(box_p).area > 0:
                    valid = False

                del limit_p, box_p

            if valid:
                y_diff = median_y - sample['box'].y

                new_pts, new_boxes, _ = PointCloudAugmenter.rotate_translate(
                    rotation=0, translation=[[0, y_diff,
                                              0]])(gt_boxes_3d=[sample['box']],
                                                   pts=sample['pts'].T)
                new_box = new_boxes[0]
                new_box = Box3D(h=new_box.h,
                                w=new_box.w,
                                l=new_box.l,
                                x=new_box.x,
                                y=new_box.y,
                                z=new_box.z,
                                yaw=new_box.yaw,
                                cls=new_box.cls)

                sample['box'] = new_box
                sample['pts'] = new_pts.T

                new_limit = _get_box_limits(sample['box'])
                box_limits.append(new_limit)
                valid_samples_limits[sample['frame_id']].append(new_limit)
                valid_samples.append(sample)

        new_pts = []
        final_samples = []
        for sample in valid_samples:
            for limit in valid_samples_limits[sample['frame_id']]:
                (y1, x1) = limit['inter1']
                (y2, x2) = limit['inter2']
                max_h, min_h = limit['max_h'], limit['min_h']
                ref_diag = limit['ref_diag']

                side1_a, side1_b = lidar_src, (x2, y2
                                               )  # left  of frustum (line)
                side2_a, side2_b = lidar_src, (x1, y1
                                               )  # right of frustum (line)

                side4_a, side4_b, side4_c = lidar_src_3d, (
                    ref_diag[0][0], min_h,
                    ref_diag[0][1]), (ref_diag[1][0], min_h, ref_diag[1][1]
                                      )  # bottom diag (plane)
                side5_a, side5_b, side5_c = lidar_src_3d, (
                    ref_diag[0][0], max_h,
                    ref_diag[0][1]), (ref_diag[1][0], max_h, ref_diag[1][1]
                                      )  # top    diag (plane)

                # check the side of all points using the left line of the frustum
                d_l = check_point_side_2d(side1_a[1], side1_a[0], side1_b[1],
                                          side1_b[0], pts[2, :], pts[0, :])
                # check the side of all points using the right line of the frustum
                d_r = check_point_side_2d(side2_a[1], side2_a[0], side2_b[1],
                                          side2_b[0], pts[2, :], pts[0, :])
                # check the side of all points using the plane from lidar source to the coordinates of the bottom diagonal
                d_b = check_point_side_3d(side4_a, side4_b, side4_c,
                                          pts[(2, 1, 0), :])
                # check the side of all points using the plane from lidar source to the coordinates of the top diagonal
                d_t = check_point_side_3d(side5_a, side5_b, side5_c,
                                          pts[(2, 1, 0), :])
                # check the side of all points using a line between the diagonal coordinates (find pts in_front/behind the car using its diagonal as reference)
                d_d = check_point_side_2d(ref_diag[0][0], ref_diag[0][1],
                                          ref_diag[1][0], ref_diag[1][1],
                                          pts[2, :], pts[0, :])

                inds_d1 = np.where((d_l == 1) & (d_r == -1) & (d_b == 1))[0]
                inds_d2 = np.where((d_l == -1) & (d_r == 1) & (d_b == -1))[0]

                # cur_del are the points that are going to be deleted from the original PC to add the new sample
                if len(inds_d1) is not 0:
                    cur_del_ids = np.where((d_l == 1) & (d_r == -1)
                                           & (d_b == 1) & (d_d == -1))[0]
                    cur_del = pts[:, cur_del_ids]
                elif len(inds_d2) is not 0:
                    cur_del_ids = np.where((d_l == -1) & (d_r == 1)
                                           & (d_b == -1) & (d_d == 1))[0]
                    cur_del = pts[:, cur_del_ids]

                # keep the points that are above the top diagonals of the new sampled box (possible buildings behind the box)
                keep_ids1 = np.where((d_l == 1) & (d_r == -1) & (d_t == 1)
                                     & (d_d == 1))[0]
                keep_ids2 = np.where((d_l == -1) & (d_r == 1) & (d_t == -1)
                                     & (d_d == -1))[0]

                pts_keep = None
                if len(keep_ids1) is not 0:
                    pts_keep = pts[:, keep_ids1]
                    pts_keep = np.concatenate((pts_keep, pts[:, keep_ids2]),
                                              axis=1)
                elif len(keep_ids2) is not 0:
                    pts_keep = pts[:, keep_ids2]

                if pts_keep is not None:
                    # get the points that are above the car (on top) to be removed
                    bev_box = sample['box'].get_bev_box().T
                    l1 = check_point_side_2d(bev_box[0][0], bev_box[0][1],
                                             bev_box[1][0], bev_box[1][1],
                                             pts_keep[2, :], pts_keep[0, :])
                    l2 = check_point_side_2d(bev_box[1][0], bev_box[1][1],
                                             bev_box[2][0], bev_box[2][1],
                                             pts_keep[2, :], pts_keep[0, :])
                    l3 = check_point_side_2d(bev_box[2][0], bev_box[2][1],
                                             bev_box[3][0], bev_box[3][1],
                                             pts_keep[2, :], pts_keep[0, :])
                    l4 = check_point_side_2d(bev_box[3][0], bev_box[3][1],
                                             bev_box[0][0], bev_box[0][1],
                                             pts_keep[2, :], pts_keep[0, :])

                    d_t2 = check_point_side_3d(side5_a, side5_b, side5_c,
                                               pts_keep[(2, 1, 0), :])
                    rem_top = np.where((l1 == 1) & (l3 == 1) & (l2 == 1)
                                       & (l4 == 1) & (d_t2 == 1))[0]

                    if len(rem_top) > 0:
                        mask = np.ones((pts_keep.shape[1]), dtype=bool)
                        mask[rem_top] = False
                        pts_keep = pts_keep[:, mask]

                    if cur_del is not None:
                        if cur_del.shape[1] <= filter_wall_thresh:
                            mask = np.ones((pts.shape[1]), dtype=bool)
                            mask[inds_d1] = False
                            mask[inds_d2] = False
                            pts = pts[:, mask]
                            final_samples.append(sample['box'])
                            pts = np.concatenate((pts, sample['pts']), axis=1)
                            pts = np.concatenate((pts, pts_keep), axis=1)
                            # _get_box_limits(sample['box'], '')

        # print('added {0} new boxes in the scene'.format(len(final_samples)))

        gt_boxes.extend(final_samples)
        return pts, gt_boxes, ref

    return _add_random_sample
Ejemplo n.º 6
0
    def _add_random_sample(gt_boxes, pts, ref=None):

        if pts.shape[0] != 3:
            pts = pts.T

        ys = sorted([box.y for box in gt_boxes], reverse=False)
        median_y = np.median(ys)

        box_limits = []

        for box in gt_boxes:
            limit_dict = _get_box_limits(box)
            box_limits.append(limit_dict)

        valid_samples = []
        valid_samples_limits = {}
        for sample in samples:
            valid = True
            valid_samples_limits[sample['frame_id']] = []

            for limit in box_limits:
                (x1, y1) = limit['inter1']
                (x2, y2) = limit['inter2']
                box_bev = sample['box'].get_bev_box().T

                limit_p = Polygon([lidar_src, (x1, y1), (x2, y2)])
                box_p = Polygon([(box_bev[0][0], box_bev[0][1]),
                                 (box_bev[1][0], box_bev[1][1]),
                                 (box_bev[2][0], box_bev[2][1]),
                                 (box_bev[3][0], box_bev[3][1])])

                if limit_p.intersection(box_p).area > 0:
                    valid = False

                del limit_p, box_p

            if valid:
                y_diff = median_y - sample['box'].y

                new_pts, new_boxes, _ = PointCloudAugmenter.rotate_translate(
                    rotation=0, translation=[[0, y_diff,
                                              0]])(gt_boxes_3d=[sample['box']],
                                                   pts=sample['pts'].T)
                new_box = new_boxes[0]
                new_box = Box3D(h=new_box.h,
                                w=new_box.w,
                                l=new_box.l,
                                x=new_box.x,
                                y=new_box.y,
                                z=new_box.z,
                                yaw=new_box.yaw,
                                cls=new_box.cls)

                sample['box'] = new_box
                sample['pts'] = new_pts.T

                new_limit = _get_box_limits(sample['box'])
                box_limits.append(new_limit)
                valid_samples_limits[sample['frame_id']].append(new_limit)
                valid_samples.append(sample)

        new_pts = []
        final_samples = []
        for sample in valid_samples:
            for limit in valid_samples_limits[sample['frame_id']]:
                (y1, x1) = limit['inter1']
                (y2, x2) = limit['inter2']
                max_h, min_h = limit['max_h'], limit['min_h']
                ref_diag = limit['ref_diag']

                side1_a, side1_b = lidar_src, (x2, y2
                                               )  # left  of frustum (line)
                side2_a, side2_b = lidar_src, (x1, y1
                                               )  # right of frustum (line)

                side4_a, side4_b, side4_c = lidar_src_3d, (
                    ref_diag[0][0], min_h,
                    ref_diag[0][1]), (ref_diag[1][0], min_h, ref_diag[1][1]
                                      )  # bottom diag (plane)
                side5_a, side5_b, side5_c = lidar_src_3d, (
                    ref_diag[0][0], max_h,
                    ref_diag[0][1]), (ref_diag[1][0], max_h, ref_diag[1][1]
                                      )  # top    diag (plane)

                # check the side of all points using the left line of the frustum
                d_l = check_point_side_2d(side1_a[1], side1_a[0], side1_b[1],
                                          side1_b[0], pts[2, :], pts[0, :])
                # check the side of all points using the right line of the frustum
                d_r = check_point_side_2d(side2_a[1], side2_a[0], side2_b[1],
                                          side2_b[0], pts[2, :], pts[0, :])
                # check the side of all points using the plane from lidar source to the coordinates of the bottom diagonal
                d_b = check_point_side_3d(side4_a, side4_b, side4_c,
                                          pts[(2, 1, 0), :])
                # check the side of all points using the plane from lidar source to the coordinates of the top diagonal
                d_t = check_point_side_3d(side5_a, side5_b, side5_c,
                                          pts[(2, 1, 0), :])
                # check the side of all points using a line between the diagonal coordinates (find pts in_front/behind the car using its diagonal as reference)
                d_d = check_point_side_2d(ref_diag[0][0], ref_diag[0][1],
                                          ref_diag[1][0], ref_diag[1][1],
                                          pts[2, :], pts[0, :])

                inds_d1 = np.where((d_l == 1) & (d_r == -1) & (d_b == 1))[0]
                inds_d2 = np.where((d_l == -1) & (d_r == 1) & (d_b == -1))[0]

                # cur_del are the points that are going to be deleted from the original PC to add the new sample
                if len(inds_d1) is not 0:
                    cur_del_ids = np.where((d_l == 1) & (d_r == -1)
                                           & (d_b == 1) & (d_d == -1))[0]
                    cur_del = pts[:, cur_del_ids]
                elif len(inds_d2) is not 0:
                    cur_del_ids = np.where((d_l == -1) & (d_r == 1)
                                           & (d_b == -1) & (d_d == 1))[0]
                    cur_del = pts[:, cur_del_ids]

                # keep the points that are above the top diagonals of the new sampled box (possible buildings behind the box)
                keep_ids1 = np.where((d_l == 1) & (d_r == -1) & (d_t == 1)
                                     & (d_d == 1))[0]
                keep_ids2 = np.where((d_l == -1) & (d_r == 1) & (d_t == -1)
                                     & (d_d == -1))[0]

                pts_keep = None
                if len(keep_ids1) is not 0:
                    pts_keep = pts[:, keep_ids1]
                    pts_keep = np.concatenate((pts_keep, pts[:, keep_ids2]),
                                              axis=1)
                elif len(keep_ids2) is not 0:
                    pts_keep = pts[:, keep_ids2]

                if pts_keep is not None:
                    # get the points that are above the car (on top) to be removed
                    bev_box = sample['box'].get_bev_box().T
                    l1 = check_point_side_2d(bev_box[0][0], bev_box[0][1],
                                             bev_box[1][0], bev_box[1][1],
                                             pts_keep[2, :], pts_keep[0, :])
                    l2 = check_point_side_2d(bev_box[1][0], bev_box[1][1],
                                             bev_box[2][0], bev_box[2][1],
                                             pts_keep[2, :], pts_keep[0, :])
                    l3 = check_point_side_2d(bev_box[2][0], bev_box[2][1],
                                             bev_box[3][0], bev_box[3][1],
                                             pts_keep[2, :], pts_keep[0, :])
                    l4 = check_point_side_2d(bev_box[3][0], bev_box[3][1],
                                             bev_box[0][0], bev_box[0][1],
                                             pts_keep[2, :], pts_keep[0, :])

                    d_t2 = check_point_side_3d(side5_a, side5_b, side5_c,
                                               pts_keep[(2, 1, 0), :])
                    rem_top = np.where((l1 == 1) & (l3 == 1) & (l2 == 1)
                                       & (l4 == 1) & (d_t2 == 1))[0]

                    if len(rem_top) > 0:
                        mask = np.ones((pts_keep.shape[1]), dtype=bool)
                        mask[rem_top] = False
                        pts_keep = pts_keep[:, mask]

                    if cur_del is not None:
                        if cur_del.shape[1] <= filter_wall_thresh:
                            mask = np.ones((pts.shape[1]), dtype=bool)
                            mask[inds_d1] = False
                            mask[inds_d2] = False
                            pts = pts[:, mask]
                            final_samples.append(sample['box'])
                            pts = np.concatenate((pts, sample['pts']), axis=1)
                            pts = np.concatenate((pts, pts_keep), axis=1)
                            # _get_box_limits(sample['box'], '')

        # print('added {0} new boxes in the scene'.format(len(final_samples)))

        gt_boxes.extend(final_samples)
        return pts, gt_boxes, ref
    box_limits = []
    all_limits = []
    rand_num = 30
    random_cars_dir = 'data_utils/aug_utils/annotations/cars/'
    random_cars = os.listdir(random_cars_dir)
    np.random.seed(0)
    random_cars = np.random.choice(random_cars, size=rand_num)

    sampled_cars = []
    for random_car in random_cars:
        sampled_car = dd.io.load(os.path.join(random_cars_dir, random_car))
        sampled_pts = sampled_car['pts'].T
        sampled_box = Box3D(h=sampled_car['box_h'],
                            w=sampled_car['box_w'],
                            l=sampled_car['box_l'],
                            x=sampled_car['box_x'],
                            y=sampled_car['box_y'],
                            z=sampled_car['box_z'],
                            yaw=sampled_car['box_yaw'],
                            cls=sampled_car['box_cls'])
        data = {
            'frame_id': sampled_car['frame_id'],
            'pts': sampled_pts,
            'num_pts': sampled_pts.shape[1],
            'box': sampled_box,
            'bev_corners': sampled_box.get_bev_box().T,
            'bev_center': sampled_box.get_bev_center(),
        }
        sampled_cars.append(data)

    sampled_cars = sorted(sampled_cars,
                          key=itemgetter('num_pts'),