def show_proj_det_result_meshlab(data, result, out_dir, score_thr=0.0, show=False, snapshot=False): """Show result of projecting 3D bbox to 2D image by meshlab.""" assert 'img' in data.keys(), 'image data is not provided for visualization' img_filename = data['img_metas'][0][0]['filename'] file_name = osp.split(img_filename)[-1].split('.')[0] # read from file because img in data_dict has undergone pipeline transform img = mmcv.imread(img_filename) if 'pts_bbox' in result[0].keys(): result[0] = result[0]['pts_bbox'] elif 'img_bbox' in result[0].keys(): result[0] = result[0]['img_bbox'] pred_bboxes = result[0]['boxes_3d'].tensor.numpy() pred_scores = result[0]['scores_3d'].numpy() # filter out low score bboxes for visualization if score_thr > 0: inds = pred_scores > score_thr pred_bboxes = pred_bboxes[inds] box_mode = data['img_metas'][0][0]['box_mode_3d'] if box_mode == Box3DMode.LIDAR: if 'lidar2img' not in data['img_metas'][0][0]: raise NotImplementedError( 'LiDAR to image transformation matrix is not provided') show_bboxes = LiDARInstance3DBoxes(pred_bboxes, origin=(0.5, 0.5, 0)) show_multi_modality_result(img, None, show_bboxes, data['img_metas'][0][0]['lidar2img'], out_dir, file_name, box_mode='lidar', show=show) elif box_mode == Box3DMode.DEPTH: show_bboxes = DepthInstance3DBoxes(pred_bboxes, origin=(0.5, 0.5, 0)) show_multi_modality_result(img, None, show_bboxes, None, out_dir, file_name, box_mode='depth', img_metas=data['img_metas'][0][0], show=show) elif box_mode == Box3DMode.CAM: if 'cam2img' not in data['img_metas'][0][0]: raise NotImplementedError( 'camera intrinsic matrix is not provided') show_bboxes = CameraInstance3DBoxes(pred_bboxes, box_dim=pred_bboxes.shape[-1], origin=(0.5, 1.0, 0.5)) show_multi_modality_result(img, None, show_bboxes, data['img_metas'][0][0]['cam2img'], out_dir, file_name, box_mode='camera', show=show) else: raise NotImplementedError( f'visualization of {box_mode} bbox is not supported') return file_name
def test_global_rot_scale_trans(): angle = 0.78539816 scale = [0.95, 1.05] trans_std = 1.0 # rot_range should be a number or seq of numbers with pytest.raises(AssertionError): global_rot_scale_trans = GlobalRotScaleTrans(rot_range='0.0') # scale_ratio_range should be seq of numbers with pytest.raises(AssertionError): global_rot_scale_trans = GlobalRotScaleTrans(scale_ratio_range=1.0) # translation_std should be a positive number or seq of positive numbers with pytest.raises(AssertionError): global_rot_scale_trans = GlobalRotScaleTrans(translation_std='0.0') with pytest.raises(AssertionError): global_rot_scale_trans = GlobalRotScaleTrans(translation_std=-1.0) global_rot_scale_trans = GlobalRotScaleTrans(rot_range=angle, scale_ratio_range=scale, translation_std=trans_std, shift_height=False) np.random.seed(0) points = np.fromfile('tests/data/scannet/points/scene0000_00.bin', np.float32).reshape(-1, 6) annos = mmcv.load('tests/data/scannet/scannet_infos.pkl') info = annos[0] gt_bboxes_3d = info['annos']['gt_boxes_upright_depth'] depth_points = DepthPoints(points.copy(), points_dim=6, attribute_dims=dict(color=[3, 4, 5])) gt_bboxes_3d = DepthInstance3DBoxes(gt_bboxes_3d.copy(), box_dim=gt_bboxes_3d.shape[-1], with_yaw=False, origin=(0.5, 0.5, 0.5)) input_dict = dict(points=depth_points.clone(), bbox3d_fields=['gt_bboxes_3d'], gt_bboxes_3d=gt_bboxes_3d.clone()) input_dict = global_rot_scale_trans(input_dict) trans_depth_points = input_dict['points'] trans_bboxes_3d = input_dict['gt_bboxes_3d'] noise_rot = 0.07667607233534723 scale_factor = 1.021518936637242 trans_factor = np.array([0.97873798, 2.2408932, 1.86755799]) true_depth_points = depth_points.clone() true_bboxes_3d = gt_bboxes_3d.clone() true_depth_points, noise_rot_mat_T = true_bboxes_3d.rotate( noise_rot, true_depth_points) true_bboxes_3d.scale(scale_factor) true_bboxes_3d.translate(trans_factor) true_depth_points.scale(scale_factor) true_depth_points.translate(trans_factor) assert torch.allclose(trans_depth_points.tensor, true_depth_points.tensor, atol=1e-6) assert torch.allclose(trans_bboxes_3d.tensor, true_bboxes_3d.tensor, atol=1e-6) assert input_dict['pcd_scale_factor'] == scale_factor assert torch.allclose(input_dict['pcd_rotation'], noise_rot_mat_T, atol=1e-6) assert np.allclose(input_dict['pcd_trans'], trans_factor) repr_str = repr(global_rot_scale_trans) expected_repr_str = f'GlobalRotScaleTrans(rot_range={[-angle, angle]},' \ f' scale_ratio_range={scale},' \ f' translation_std={[trans_std for _ in range(3)]},' \ f' shift_height=False)' assert repr_str == expected_repr_str # points with shift_height but no bbox global_rot_scale_trans = GlobalRotScaleTrans(rot_range=angle, scale_ratio_range=scale, translation_std=trans_std, shift_height=True) # points should have height attribute when shift_height=True with pytest.raises(AssertionError): input_dict = global_rot_scale_trans(input_dict) np.random.seed(0) shift_height = points[:, 2:3] * 0.99 points = np.concatenate([points, shift_height], axis=1) depth_points = DepthPoints(points.copy(), points_dim=7, attribute_dims=dict(color=[3, 4, 5], height=6)) input_dict = dict(points=depth_points.clone(), bbox3d_fields=[]) input_dict = global_rot_scale_trans(input_dict) trans_depth_points = input_dict['points'] true_shift_height = shift_height * scale_factor assert np.allclose( trans_depth_points.tensor.numpy(), np.concatenate([true_depth_points.tensor.numpy(), true_shift_height], axis=1), atol=1e-6)
def show_result_meshlab(data, result, out_dir, score_thr=0.0, show=False, snapshot=False): """Show result by meshlab. Args: data (dict): Contain data from pipeline. result (dict): Predicted result from model. out_dir (str): Directory to save visualized result. score_thr (float): Minimum score of bboxes to be shown. Default: 0.0 show (bool): Visualize the results online. Defaults to False. snapshot (bool): Whether to save the online results. Defaults to False. """ points = data['points'][0][0].cpu().numpy() pts_filename = data['img_metas'][0][0]['pts_filename'] file_name = osp.split(pts_filename)[-1].split('.')[0] assert out_dir is not None, 'Expect out_dir, got none.' if 'pts_bbox' in result[0].keys(): pred_bboxes = result[0]['pts_bbox']['boxes_3d'].tensor.numpy() pred_scores = result[0]['pts_bbox']['scores_3d'].numpy() else: pred_bboxes = result[0]['boxes_3d'].tensor.numpy() pred_scores = result[0]['scores_3d'].numpy() # filter out low score bboxes for visualization if score_thr > 0: inds = pred_scores > score_thr pred_bboxes = pred_bboxes[inds] # for now we convert points into depth mode box_mode = data['img_metas'][0][0]['box_mode_3d'] if box_mode != Box3DMode.DEPTH: points = points[..., [1, 0, 2]] points[..., 0] *= -1 show_bboxes = Box3DMode.convert(pred_bboxes, box_mode, Box3DMode.DEPTH) else: show_bboxes = deepcopy(pred_bboxes) show_result(points, None, show_bboxes, out_dir, file_name, show=show, snapshot=snapshot) if 'img' not in data.keys(): return out_dir, file_name # multi-modality visualization # project 3D bbox to 2D image plane if box_mode == Box3DMode.LIDAR: if 'lidar2img' not in data['img_metas'][0][0]: raise NotImplementedError( 'LiDAR to image transformation matrix is not provided') show_bboxes = LiDARInstance3DBoxes(pred_bboxes, origin=(0.5, 0.5, 0)) img = mmcv.imread(data['img_metas'][0][0]['filename']) show_multi_modality_result(img, None, show_bboxes, data['img_metas'][0][0]['lidar2img'], out_dir, file_name, show=show) elif box_mode == Box3DMode.DEPTH: if 'calib' not in data.keys(): raise NotImplementedError( 'camera calibration information is not provided') show_bboxes = DepthInstance3DBoxes(pred_bboxes, origin=(0.5, 0.5, 0)) img = mmcv.imread(data['img_metas'][0][0]['filename']) show_multi_modality_result(img, None, show_bboxes, data['calib'][0], out_dir, file_name, depth_bbox=True, img_metas=data['img_metas'][0][0], show=show) else: raise NotImplementedError( f'visualization of {box_mode} bbox is not supported') return out_dir, file_name