Exemplo n.º 1
0
def rbbox2d_to_near_bbox(rbboxes):
    """convert rotated bbox to nearest 'standing' or 'lying' bbox.
    Args:
        rbboxes: [N, 5(x, y, xdim, ydim, rad)] rotated bboxes
    Returns:
        bboxes: [N, 4(xmin, ymin, xmax, ymax)] bboxes
    """
    rots = rbboxes[..., -1]
    rots_0_pi_div_2 = np.abs(common_utils.limit_period(rots, 0.5, np.pi))
    cond = (rots_0_pi_div_2 > np.pi / 4)[..., np.newaxis]
    bboxes_center = np.where(cond, rbboxes[:, [0, 1, 3, 2]], rbboxes[:, :4])
    bboxes = center_to_minmax_2d(bboxes_center[:, :2], bboxes_center[:, 2:])
    return bboxes
Exemplo n.º 2
0
def boxes3d_lidar_to_aligned_bev_boxes(boxes3d):
    """
    Args:
        boxes3d: (N, 7 + C) [x, y, z, dx, dy, dz, heading] in lidar coordinate

    Returns:
        aligned_bev_boxes: (N, 4) [x1, y1, x2, y2] in the above lidar coordinate
    """
    rot_angle = common_utils.limit_period(boxes3d[:, 6],
                                          offset=0.5,
                                          period=np.pi).abs()  #角度先转化为(0~pi/2)
    choose_dims = torch.where(rot_angle[:, None] < np.pi / 4,
                              boxes3d[:, [3, 4]], boxes3d[:, [4, 3]])
    aligned_bev_boxes = torch.cat(
        (boxes3d[:, 0:2] - choose_dims / 2, boxes3d[:, 0:2] + choose_dims / 2),
        dim=1)
    return aligned_bev_boxes
Exemplo n.º 3
0
    def get_dir_target(self,dir_offset,num_bins,one_hot=True):
        box_reg_targets = self.forward_ret_dict['box_reg_targets']
        batch_size = box_reg_targets.shape[0]
        batch_anchors = torch.cat([anchor for anchor in self.anchors],dim=-3)
        batch_anchors = batch_anchors.reshape(1,-1,self.box_code_size).repeat(batch_size,1,1)
        rot_angle = box_reg_targets[...,6]+batch_anchors[...,6]

        dir_cls_target = common_utils.limit_period(rot_angle-dir_offset,0,2*np.pi)
        dir_cls_target = torch.floor(dir_cls_target / (2*np.pi/num_bins)).long()
        dir_cls_target_np = dir_cls_target.cpu().numpy()

        dir_cls_target = torch.clamp(dir_cls_target, min=0, max=num_bins - 1)
        if one_hot:
            one_hot_dir_targets = torch.zeros(*dir_cls_target.shape,num_bins,
                                              dtype=dir_cls_target.dtype,
                                              device=dir_cls_target.device)
            one_hot_dir_targets.scatter_(-1,dir_cls_target.unsqueeze(dim=-1),1.0)
        return one_hot_dir_targets if one_hot else dir_cls_target
Exemplo n.º 4
0
    def predict_box(self):
        rpn_cls_preds = self.forward_ret_dict["cls_preds"]
        batch_size = rpn_cls_preds.shape[0]
        rpn_box_preds_src = self.forward_ret_dict["box_preds"].reshape(batch_size,-1,self.box_code_size)
        rpn_cls_preds = rpn_cls_preds.reshape(batch_size,-1,self.num_class)
        #角度处理
        num_dir_bins = cfg.MODEL.RPN.RPN_HEAD.ARGS["num_direction_bins"]
        dir_offset = cfg.MODEL.RPN.RPN_HEAD.ARGS["dir_offset"]
        dir_limit_offset = cfg.MODEL.RPN.RPN_HEAD.ARGS["dir_limit_offset"]
        dir_period = 2*np.pi/num_dir_bins
        dir_preds = self.forward_ret_dict["dir_preds"].permute(0,2,3,1).reshape(batch_size,-1,num_dir_bins)
        dir_cls_preds = torch.argmax(dir_preds,dim=-1)
        #box解码
        batch_anchors = torch.cat([anchor for anchor in self.anchors],dim=-3).reshape(1,-1,self.box_code_size).repeat(batch_size,1,1)
        rpn_box_preds = self.box_coder.decode_torch(rpn_box_preds_src,batch_anchors)
        rot_angle_preds = common_utils.limit_period(rpn_box_preds[...,6]-dir_offset,
                                                    offset=dir_limit_offset,period=dir_period)

        rot_angle_preds_final = rot_angle_preds+dir_offset+dir_period*dir_cls_preds.to(rpn_box_preds.dtype)
        # for_test = rot_angle_preds_final>2*np.pi
        # for_test = for_test.sum()
        rpn_box_preds[...,6] = rot_angle_preds_final % (np.pi*2)

        return rpn_cls_preds,rpn_box_preds
Exemplo n.º 5
0
    def prepare_data(self, input_dict, has_label=True):
        """
        :param input_dict:
            sample_idx: string
            calib: object, calibration related
            points: (N, 3 + C1)
            gt_boxes_lidar: optional, (N, 7) [x, y, z, w, l, h, rz] in LiDAR coordinate, z is the bottom center
            gt_names: optional, (N), string
        :param has_label: bool
        :return:
            voxels: (N, max_points_of_each_voxel, 3 + C2), float
            num_points: (N), int
            coordinates: (N, 3), [idx_z, idx_y, idx_x]
            num_voxels: (N)
            voxel_centers: (N, 3)
            calib: object
            gt_boxes: (N, 8), [x, y, z, w, l, h, rz, gt_classes] in LiDAR coordinate, z is the bottom center
            points: (M, 3 + C)
        """
        sample_idx = input_dict['sample_idx']
        points = input_dict['points']
        calib = input_dict['calib']

        if has_label:
            gt_boxes = input_dict['gt_boxes_lidar'].copy()
            gt_names = input_dict['gt_names'].copy()

        if self.training:
            selected = common_utils.drop_arrays_by_name(gt_names, ['DontCare', 'Sign'])
            gt_boxes = gt_boxes[selected]
            gt_names = gt_names[selected]
            gt_boxes_mask = np.array([n in self.class_names for n in gt_names], dtype=np.bool_)

            if self.db_sampler is not None:
                road_planes = self.get_road_plane(sample_idx) \
                    if cfg.DATA_CONFIG.AUGMENTATION.DB_SAMPLER.USE_ROAD_PLANE else None
                sampled_dict = self.db_sampler.sample_all(
                    self.root_path, gt_boxes, gt_names, road_planes=road_planes,
                    num_point_features=cfg.DATA_CONFIG.NUM_POINT_FEATURES['total'], calib=calib
                )

                if sampled_dict is not None:
                    sampled_gt_names = sampled_dict['gt_names']
                    sampled_gt_boxes = sampled_dict['gt_boxes']
                    sampled_points = sampled_dict['points']
                    sampled_gt_masks = sampled_dict['gt_masks']

                    gt_names = np.concatenate([gt_names, sampled_gt_names], axis=0)
                    gt_boxes = np.concatenate([gt_boxes, sampled_gt_boxes])
                    gt_boxes_mask = np.concatenate([gt_boxes_mask, sampled_gt_masks], axis=0)

                    points = box_utils.remove_points_in_boxes3d_v0(points, sampled_gt_boxes)
                    points = np.concatenate([sampled_points, points], axis=0)

            noise_per_object_cfg = cfg.DATA_CONFIG.AUGMENTATION.NOISE_PER_OBJECT
            if noise_per_object_cfg.ENABLED:
                gt_boxes, points = \
                    augmentation_utils.noise_per_object_v3_(
                    gt_boxes,
                    points,
                    gt_boxes_mask,
                    rotation_perturb=noise_per_object_cfg.GT_ROT_UNIFORM_NOISE,
                    center_noise_std=noise_per_object_cfg.GT_LOC_NOISE_STD,
                    num_try=100
                )

            gt_boxes = gt_boxes[gt_boxes_mask]
            gt_names = gt_names[gt_boxes_mask]

            gt_classes = np.array([self.class_names.index(n) + 1 for n in gt_names], dtype=np.int32)

            noise_global_scene = cfg.DATA_CONFIG.AUGMENTATION.NOISE_GLOBAL_SCENE
            if noise_global_scene.ENABLED:
                gt_boxes, points = augmentation_utils.random_flip(gt_boxes, points)
                gt_boxes, points = augmentation_utils.global_rotation(
                    gt_boxes, points, rotation=noise_global_scene.GLOBAL_ROT_UNIFORM_NOISE
                )
                gt_boxes, points = augmentation_utils.global_scaling(
                    gt_boxes, points, *noise_global_scene.GLOBAL_SCALING_UNIFORM_NOISE
                )

            pc_range = self.voxel_generator.point_cloud_range
            mask = box_utils.mask_boxes_outside_range(gt_boxes, pc_range)
            gt_boxes = gt_boxes[mask]
            gt_classes = gt_classes[mask]
            gt_names = gt_names[mask]

            # limit rad to [-pi, pi]
            gt_boxes[:, 6] = common_utils.limit_period(gt_boxes[:, 6], offset=0.5, period=2 * np.pi)

        points = points[:, :cfg.DATA_CONFIG.NUM_POINT_FEATURES['use']]
        if cfg.DATA_CONFIG[self.mode].SHUFFLE_POINTS:
            np.random.shuffle(points)

        voxel_grid = self.voxel_generator.generate(points)

        # Support spconv 1.0 and 1.1
        try:
            voxels, coordinates, num_points = voxel_grid
        except:
            voxels = voxel_grid["voxels"]
            coordinates = voxel_grid["coordinates"]
            num_points = voxel_grid["num_points_per_voxel"]

        voxel_centers = (coordinates[:, ::-1] + 0.5) * self.voxel_generator.voxel_size \
                        + self.voxel_generator.point_cloud_range[0:3]

        if cfg.DATA_CONFIG.MASK_POINTS_BY_RANGE:
            points = common_utils.mask_points_by_range(points, cfg.DATA_CONFIG.POINT_CLOUD_RANGE)

        example = {}
        if has_label:
            if not self.training:
                # for eval_utils
                selected = common_utils.keep_arrays_by_name(gt_names, self.class_names)
                gt_boxes = gt_boxes[selected]
                gt_names = gt_names[selected]
                gt_classes = np.array([self.class_names.index(n) + 1 for n in gt_names], dtype=np.int32)


            gt_boxes = np.concatenate((gt_boxes, gt_classes.reshape(-1, 1).astype(np.float32)), axis=1)

            example.update({
                'gt_boxes': gt_boxes
            })

        example.update({
            'voxels': voxels,
            'num_points': num_points,
            'coordinates': coordinates,
            'voxel_centers': voxel_centers,
            'calib': input_dict['calib'],
            'points': points
        })

        return example