def test_voxel_net(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') _setup_seed(0) voxel_net_cfg = _get_detector_cfg( 'second/hv_second_secfpn_6x8_80e_kitti-3d-3class.py') self = build_detector(voxel_net_cfg).cuda() points_0 = torch.rand([2010, 4], device='cuda') points_1 = torch.rand([2020, 4], device='cuda') points = [points_0, points_1] gt_bbox_0 = LiDARInstance3DBoxes(torch.rand([10, 7], device='cuda')) gt_bbox_1 = LiDARInstance3DBoxes(torch.rand([10, 7], device='cuda')) gt_bboxes = [gt_bbox_0, gt_bbox_1] gt_labels_0 = torch.randint(0, 3, [10], device='cuda') gt_labels_1 = torch.randint(0, 3, [10], device='cuda') gt_labels = [gt_labels_0, gt_labels_1] img_meta_0 = dict(box_type_3d=LiDARInstance3DBoxes) img_meta_1 = dict(box_type_3d=LiDARInstance3DBoxes) img_metas = [img_meta_0, img_meta_1] # test forward_train losses = self.forward_train(points, img_metas, gt_bboxes, gt_labels) assert losses['loss_cls'][0] >= 0 assert losses['loss_bbox'][0] >= 0 assert losses['loss_dir'][0] >= 0 # test simple_test results = self.simple_test(points, img_metas) boxes_3d = results['boxes_3d'] scores_3d = results['scores_3d'] labels_3d = results['labels_3d'] assert boxes_3d.tensor.shape == (50, 7) assert scores_3d.shape == torch.Size([50]) assert labels_3d.shape == torch.Size([50])
def test_matcher_without_boxes(self): similarity_measure = Iou() matcher = GreedyMatcher(self.CLASSES) pred_boxes = torch.tensor([], dtype=torch.float) gt_boxes = torch.tensor([], dtype=torch.float) pred_boxes = LiDARInstance3DBoxes(pred_boxes) gt_boxes = LiDARInstance3DBoxes(gt_boxes) pred_labels = torch.tensor([], dtype=torch.float) gt_labels = torch.tensor([], dtype=torch.float) pred_scores = torch.tensor([], dtype=torch.float) similarity_scores = similarity_measure.calc_scores( gt_boxes, pred_boxes, gt_labels, pred_labels) matching_results = matcher.match( similarity_scores, gt_boxes, pred_boxes, gt_labels, pred_labels, pred_scores, data_id=0, ) # in the empty case a dict of classes -> empty list should be returned assert matching_results == {self.CLASSES[0]: [], self.CLASSES[1]: []}
def test_ssd3d_head(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') _setup_seed(0) ssd3d_head_cfg = _get_vote_head_cfg('3dssd/3dssd_4x4_kitti-3d-car.py') ssd3d_head_cfg.vote_module_cfg.num_points = 64 self = build_head(ssd3d_head_cfg).cuda() sa_xyz = [torch.rand([2, 128, 3], dtype=torch.float32).cuda()] sa_features = [torch.rand([2, 256, 128], dtype=torch.float32).cuda()] sa_indices = [torch.randint(0, 64, [2, 128]).cuda()] input_dict = dict( sa_xyz=sa_xyz, sa_features=sa_features, sa_indices=sa_indices) # test forward ret_dict = self(input_dict, 'spec') assert ret_dict['center'].shape == torch.Size([2, 64, 3]) assert ret_dict['obj_scores'].shape == torch.Size([2, 1, 64]) assert ret_dict['size'].shape == torch.Size([2, 64, 3]) assert ret_dict['dir_res'].shape == torch.Size([2, 64, 12]) # test loss points = [torch.rand([4000, 3], device='cuda') for i in range(2)] gt_bbox1 = LiDARInstance3DBoxes(torch.rand([5, 7], device='cuda')) gt_bbox2 = LiDARInstance3DBoxes(torch.rand([5, 7], device='cuda')) gt_bboxes = [gt_bbox1, gt_bbox2] gt_labels = [ torch.zeros([5], dtype=torch.long, device='cuda') for i in range(2) ] img_metas = [dict(box_type_3d=LiDARInstance3DBoxes) for i in range(2)] losses = self.loss( ret_dict, points, gt_bboxes, gt_labels, img_metas=img_metas) assert losses['centerness_loss'] >= 0 assert losses['center_loss'] >= 0 assert losses['dir_class_loss'] >= 0 assert losses['dir_res_loss'] >= 0 assert losses['size_res_loss'] >= 0 assert losses['corner_loss'] >= 0 assert losses['vote_loss'] >= 0 # test multiclass_nms_single sem_scores = ret_dict['obj_scores'].transpose(1, 2)[0] obj_scores = sem_scores.max(-1)[0] bbox = self.bbox_coder.decode(ret_dict)[0] input_meta = img_metas[0] bbox_selected, score_selected, labels = self.multiclass_nms_single( obj_scores, sem_scores, bbox, points[0], input_meta) assert bbox_selected.shape[0] >= 0 assert bbox_selected.shape[1] == 7 assert score_selected.shape[0] >= 0 assert labels.shape[0] >= 0 # test get_boxes points = torch.stack(points, 0) results = self.get_bboxes(points, ret_dict, img_metas) assert results[0][0].tensor.shape[0] >= 0 assert results[0][0].tensor.shape[1] == 7 assert results[0][1].shape[0] >= 0 assert results[0][2].shape[0] >= 0
def test_part_aggregation_ROI_head(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') _setup_seed(0) roi_head_cfg = _get_roi_head_cfg( 'parta2/hv_PartA2_secfpn_2x8_cyclic_80e_kitti-3d-3class.py') self = build_head(roi_head_cfg).cuda() spatial_features = torch.rand([1, 256, 200, 176], device='cuda') seg_features = torch.rand([32000, 16], device='cuda') neck_features = [torch.rand([1, 512, 200, 176], device='cuda')] feats_dict = dict( spatial_features=spatial_features, seg_features=seg_features, neck_features=neck_features) voxels = torch.rand([32000, 5, 4], device='cuda') num_points = torch.ones([32000], device='cuda') coors = torch.zeros([32000, 4], device='cuda') voxel_centers = torch.zeros([32000, 3], device='cuda') box_type_3d = LiDARInstance3DBoxes img_metas = [dict(box_type_3d=box_type_3d)] voxels_dict = dict( voxels=voxels, num_points=num_points, coors=coors, voxel_centers=voxel_centers) pred_bboxes = LiDARInstance3DBoxes(torch.rand([5, 7], device='cuda')) pred_scores = torch.rand([5], device='cuda') pred_labels = torch.randint(0, 3, [5], device='cuda') pred_clses = torch.rand([5, 3], device='cuda') proposal = dict( boxes_3d=pred_bboxes, scores_3d=pred_scores, labels_3d=pred_labels, cls_preds=pred_clses) proposal_list = [proposal] gt_bboxes_3d = [LiDARInstance3DBoxes(torch.rand([5, 7], device='cuda'))] gt_labels_3d = [torch.randint(0, 3, [5], device='cuda')] losses = self.forward_train(feats_dict, voxels_dict, {}, proposal_list, gt_bboxes_3d, gt_labels_3d) assert losses['loss_seg'] >= 0 assert losses['loss_part'] >= 0 assert losses['loss_cls'] >= 0 assert losses['loss_bbox'] >= 0 assert losses['loss_corner'] >= 0 bbox_results = self.simple_test(feats_dict, voxels_dict, img_metas, proposal_list) boxes_3d = bbox_results['boxes_3d'] scores_3d = bbox_results['scores_3d'] labels_3d = bbox_results['labels_3d'] assert boxes_3d.tensor.shape == (6, 7) assert scores_3d.shape == (6, ) assert labels_3d.shape == (6, )
def test_imvoxelnet(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') imvoxelnet_cfg = _get_detector_cfg('imvoxelnet/imvoxelnet_kitti-3d-car.py') self = build_detector(imvoxelnet_cfg).cuda() imgs = torch.rand([1, 3, 384, 1280], dtype=torch.float32).cuda() gt_bboxes_3d = [LiDARInstance3DBoxes(torch.rand([3, 7], device='cuda'))] gt_labels_3d = [torch.zeros([3], dtype=torch.long, device='cuda')] img_metas = [ dict(box_type_3d=LiDARInstance3DBoxes, lidar2img=np.array([[6.0e+02, -7.2e+02, -1.2e+00, -1.2e+02], [1.8e+02, 7.6e+00, -7.1e+02, -1.0e+02], [9.9e-01, 1.2e-04, 1.0e-02, -2.6e-01], [0.0e+00, 0.0e+00, 0.0e+00, 1.0e+00]], dtype=np.float32), img_shape=(384, 1272, 3)) ] # test forward_train losses = self.forward_train(imgs, img_metas, gt_bboxes_3d, gt_labels_3d) assert losses['loss_cls'][0] >= 0 assert losses['loss_bbox'][0] >= 0 assert losses['loss_dir'][0] >= 0 # test simple_test with torch.no_grad(): results = self.simple_test(imgs, img_metas) boxes_3d = results[0]['boxes_3d'] scores_3d = results[0]['scores_3d'] labels_3d = results[0]['labels_3d'] assert boxes_3d.tensor.shape[0] >= 0 assert boxes_3d.tensor.shape[1] == 7 assert scores_3d.shape[0] >= 0 assert labels_3d.shape[0] >= 0
def test_show(): import mmcv import tempfile from os import path as osp from mmdet3d.core.bbox import LiDARInstance3DBoxes temp_dir = tempfile.mkdtemp() data_root, ann_file, classes, pts_prefix,\ pipeline, modality, split = _generate_kitti_dataset_config() kitti_dataset = KittiDataset(data_root, ann_file, split=split, modality=modality, pipeline=pipeline) boxes_3d = LiDARInstance3DBoxes( torch.tensor( [[46.1218, -4.6496, -0.9275, 0.5316, 1.4442, 1.7450, 1.1749], [33.3189, 0.1981, 0.3136, 0.5656, 1.2301, 1.7985, 1.5723], [46.1366, -4.6404, -0.9510, 0.5162, 1.6501, 1.7540, 1.3778], [33.2646, 0.2297, 0.3446, 0.5746, 1.3365, 1.7947, 1.5430], [58.9079, 16.6272, -1.5829, 1.5656, 3.9313, 1.4899, 1.5505]])) scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780]) labels_3d = torch.tensor([0, 0, 1, 1, 2]) result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d) results = [result] kitti_dataset.show(results, temp_dir) pts_file_path = osp.join(temp_dir, '000000', '000000_points.obj') gt_file_path = osp.join(temp_dir, '000000', '000000_gt.ply') pred_file_path = osp.join(temp_dir, '000000', '000000_pred.ply') mmcv.check_file_exist(pts_file_path) mmcv.check_file_exist(gt_file_path) mmcv.check_file_exist(pred_file_path)
def test_show_result_meshlab(): pcd = 'tests/data/nuscenes/samples/LIDAR_TOP/n015-2018-08-02-17-16-37+' \ '0800__LIDAR_TOP__1533201470948018.pcd.bin' box_3d = LiDARInstance3DBoxes( torch.tensor( [[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]])) labels_3d = torch.tensor([0]) scores_3d = torch.tensor([0.5]) points = np.random.rand(100, 4) img_meta = dict( pts_filename=pcd, boxes_3d=box_3d, box_mode_3d=Box3DMode.LIDAR) data = dict(points=[[torch.tensor(points)]], img_metas=[[img_meta]]) result = [ dict( pts_bbox=dict( boxes_3d=box_3d, labels_3d=labels_3d, scores_3d=scores_3d)) ] temp_out_dir = tempfile.mkdtemp() out_dir, file_name = show_result_meshlab(data, result, temp_out_dir) expected_outfile_ply = file_name + '_pred.ply' expected_outfile_obj = file_name + '_points.obj' expected_outfile_ply_path = os.path.join(out_dir, file_name, expected_outfile_ply) expected_outfile_obj_path = os.path.join(out_dir, file_name, expected_outfile_obj) assert os.path.exists(expected_outfile_ply_path) assert os.path.exists(expected_outfile_obj_path) os.remove(expected_outfile_obj_path) os.remove(expected_outfile_ply_path) os.removedirs(os.path.join(temp_out_dir, file_name))
def test_free_anchor_3D_head(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') _setup_seed(0) pts_bbox_head_cfg = _get_pts_bbox_head_cfg( './free_anchor/hv_pointpillars_fpn_sbn-all_' 'free-anchor_4x8_2x_nus-3d.py') self = build_head(pts_bbox_head_cfg) cls_scores = [ torch.rand([4, 80, 200, 200], device='cuda') for i in range(3) ] bbox_preds = [ torch.rand([4, 72, 200, 200], device='cuda') for i in range(3) ] dir_cls_preds = [ torch.rand([4, 16, 200, 200], device='cuda') for i in range(3) ] gt_bboxes = [ LiDARInstance3DBoxes(torch.rand([8, 9], device='cuda'), box_dim=9) for i in range(4) ] gt_labels = [ torch.randint(0, 10, [8], device='cuda', dtype=torch.long) for i in range(4) ] input_metas = [0] losses = self.loss(cls_scores, bbox_preds, dir_cls_preds, gt_bboxes, gt_labels, input_metas, None) assert losses['positive_bag_loss'] >= 0 assert losses['negative_bag_loss'] >= 0
def test_show(): import mmcv import tempfile from os import path as osp from mmdet3d.core.bbox import LiDARInstance3DBoxes temp_dir = tempfile.mkdtemp() data_root = 'tests/data/kitti' ann_file = 'tests/data/kitti/kitti_infos_train.pkl' modality = {'use_lidar': True, 'use_camera': False} split = 'training' file_client_args = dict(backend='disk') point_cloud_range = [0, -40, -3, 70.4, 40, 1] class_names = ['Pedestrian', 'Cyclist', 'Car'] pipeline = [ dict(type='LoadPointsFromFile', load_dim=4, use_dim=4, file_client_args=file_client_args), dict(type='MultiScaleFlipAug3D', img_scale=(1333, 800), pts_scale_ratio=1, flip=False, transforms=[ dict(type='GlobalRotScaleTrans', rot_range=[0, 0], scale_ratio_range=[1., 1.], translation_std=[0, 0, 0]), dict(type='RandomFlip3D'), dict(type='PointsRangeFilter', point_cloud_range=point_cloud_range), dict(type='DefaultFormatBundle3D', class_names=class_names, with_label=False), dict(type='Collect3D', keys=['points']) ]) ] kitti_dataset = KittiDataset(data_root, ann_file, split=split, modality=modality, pipeline=pipeline) boxes_3d = LiDARInstance3DBoxes( torch.tensor( [[46.1218, -4.6496, -0.9275, 0.5316, 1.4442, 1.7450, 1.1749], [33.3189, 0.1981, 0.3136, 0.5656, 1.2301, 1.7985, 1.5723], [46.1366, -4.6404, -0.9510, 0.5162, 1.6501, 1.7540, 1.3778], [33.2646, 0.2297, 0.3446, 0.5746, 1.3365, 1.7947, 1.5430], [58.9079, 16.6272, -1.5829, 1.5656, 3.9313, 1.4899, 1.5505]])) scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780]) labels_3d = torch.tensor([0, 0, 1, 1, 2]) result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d) results = [result] kitti_dataset.show(results, temp_dir) pts_file_path = osp.join(temp_dir, '000000', '000000_points.obj') gt_file_path = osp.join(temp_dir, '000000', '000000_gt.ply') pred_file_path = osp.join(temp_dir, '000000', '000000_pred.ply') mmcv.check_file_exist(pts_file_path) mmcv.check_file_exist(gt_file_path) mmcv.check_file_exist(pred_file_path)
def test_bbox2result_kitti(): data_root, ann_file, classes, pts_prefix,\ pipeline, modality, split = _generate_kitti_dataset_config() self = KittiDataset(data_root, ann_file, split, pts_prefix, pipeline, classes, modality) boxes_3d = LiDARInstance3DBoxes( torch.tensor( [[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]])) labels_3d = torch.tensor([ 0, ]) scores_3d = torch.tensor([0.5]) result = dict(boxes_3d=boxes_3d, labels_3d=labels_3d, scores_3d=scores_3d) results = [result] temp_kitti_result_dir = tempfile.mkdtemp() det_annos = self.bbox2result_kitti(results, classes, submission_prefix=temp_kitti_result_dir) expected_file_path = os.path.join(temp_kitti_result_dir, '000000.txt') expected_name = np.array(['Pedestrian']) expected_dimensions = np.array([1.2000, 1.8900, 0.4800]) expected_rotation_y = np.array([0.0100]) - np.pi expected_score = np.array([0.5]) assert np.all(det_annos[0]['name'] == expected_name) assert np.allclose(det_annos[0]['rotation_y'], expected_rotation_y) assert np.allclose(det_annos[0]['score'], expected_score) assert np.allclose(det_annos[0]['dimensions'], expected_dimensions) assert os.path.exists(expected_file_path) os.remove(expected_file_path) os.removedirs(temp_kitti_result_dir) temp_kitti_result_dir = tempfile.mkdtemp() boxes_3d = LiDARInstance3DBoxes(torch.tensor([])) labels_3d = torch.tensor([]) scores_3d = torch.tensor([]) empty_result = dict(boxes_3d=boxes_3d, labels_3d=labels_3d, scores_3d=scores_3d) results = [empty_result] det_annos = self.bbox2result_kitti(results, classes, submission_prefix=temp_kitti_result_dir) expected_file_path = os.path.join(temp_kitti_result_dir, '000000.txt') assert os.path.exists(expected_file_path) os.remove(expected_file_path) os.removedirs(temp_kitti_result_dir)
def test_show(): import mmcv from os import path as osp from mmdet3d.core.bbox import LiDARInstance3DBoxes # Waymo shares show function with KITTI so I just copy it here tmp_dir = tempfile.TemporaryDirectory() temp_dir = tmp_dir.name data_root, ann_file, classes, pts_prefix, pipeline, \ modality, split = _generate_waymo_val_dataset_config() waymo_dataset = WaymoDataset(data_root, ann_file, split=split, modality=modality, pipeline=pipeline) boxes_3d = LiDARInstance3DBoxes( torch.tensor( [[46.1218, -4.6496, -0.9275, 0.5316, 1.4442, 1.7450, 1.1749], [33.3189, 0.1981, 0.3136, 0.5656, 1.2301, 1.7985, 1.5723], [46.1366, -4.6404, -0.9510, 0.5162, 1.6501, 1.7540, 1.3778], [33.2646, 0.2297, 0.3446, 0.5746, 1.3365, 1.7947, 1.5430], [58.9079, 16.6272, -1.5829, 1.5656, 3.9313, 1.4899, 1.5505]])) scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780]) labels_3d = torch.tensor([0, 0, 1, 1, 2]) result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d) results = [result] waymo_dataset.show(results, temp_dir, show=False) pts_file_path = osp.join(temp_dir, '1000000', '1000000_points.obj') gt_file_path = osp.join(temp_dir, '1000000', '1000000_gt.obj') pred_file_path = osp.join(temp_dir, '1000000', '1000000_pred.obj') mmcv.check_file_exist(pts_file_path) mmcv.check_file_exist(gt_file_path) mmcv.check_file_exist(pred_file_path) tmp_dir.cleanup() # test show with pipeline tmp_dir = tempfile.TemporaryDirectory() temp_dir = tmp_dir.name eval_pipeline = [ dict(type='LoadPointsFromFile', coord_type='LIDAR', load_dim=6, use_dim=5), dict(type='DefaultFormatBundle3D', class_names=classes, with_label=False), dict(type='Collect3D', keys=['points']) ] waymo_dataset.show(results, temp_dir, show=False, pipeline=eval_pipeline) pts_file_path = osp.join(temp_dir, '1000000', '1000000_points.obj') gt_file_path = osp.join(temp_dir, '1000000', '1000000_gt.obj') pred_file_path = osp.join(temp_dir, '1000000', '1000000_pred.obj') mmcv.check_file_exist(pts_file_path) mmcv.check_file_exist(gt_file_path) mmcv.check_file_exist(pred_file_path) tmp_dir.cleanup()
def test_centerpoint(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') centerpoint = _get_detector_cfg( 'centerpoint/centerpoint_02pillar_second_secfpn_4x8_cyclic_20e_nus.py') self = build_detector(centerpoint).cuda() points_0 = torch.rand([1000, 5], device='cuda') points_1 = torch.rand([1000, 5], device='cuda') points = [points_0, points_1] img_meta_0 = dict(box_type_3d=LiDARInstance3DBoxes) img_meta_1 = dict(box_type_3d=LiDARInstance3DBoxes) img_metas = [img_meta_0, img_meta_1] gt_bbox_0 = LiDARInstance3DBoxes(torch.rand([10, 9], device='cuda'), box_dim=9) gt_bbox_1 = LiDARInstance3DBoxes(torch.rand([10, 9], device='cuda'), box_dim=9) gt_bboxes = [gt_bbox_0, gt_bbox_1] gt_labels_0 = torch.randint(0, 3, [10], device='cuda') gt_labels_1 = torch.randint(0, 3, [10], device='cuda') gt_labels = [gt_labels_0, gt_labels_1] # test_forward_train losses = self.forward_train(points, img_metas, gt_bboxes, gt_labels) for key, value in losses.items(): assert value >= 0 # test_simple_test results = self.simple_test(points, img_metas) boxes_3d_0 = results[0]['pts_bbox']['boxes_3d'] scores_3d_0 = results[0]['pts_bbox']['scores_3d'] labels_3d_0 = results[0]['pts_bbox']['labels_3d'] assert boxes_3d_0.tensor.shape[0] >= 0 assert boxes_3d_0.tensor.shape[1] == 9 assert scores_3d_0.shape[0] >= 0 assert labels_3d_0.shape[0] >= 0 boxes_3d_1 = results[1]['pts_bbox']['boxes_3d'] scores_3d_1 = results[1]['pts_bbox']['scores_3d'] labels_3d_1 = results[1]['pts_bbox']['labels_3d'] assert boxes_3d_1.tensor.shape[0] >= 0 assert boxes_3d_1.tensor.shape[1] == 9 assert scores_3d_1.shape[0] >= 0 assert labels_3d_1.shape[0] >= 0
def test_parta2(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') _setup_seed(0) parta2 = _get_detector_cfg( 'parta2/hv_PartA2_secfpn_2x8_cyclic_80e_kitti-3d-3class.py') self = build_detector(parta2).cuda() points_0 = torch.rand([1000, 4], device='cuda') points_1 = torch.rand([1000, 4], device='cuda') points = [points_0, points_1] img_meta_0 = dict(box_type_3d=LiDARInstance3DBoxes) img_meta_1 = dict(box_type_3d=LiDARInstance3DBoxes) img_metas = [img_meta_0, img_meta_1] gt_bbox_0 = LiDARInstance3DBoxes(torch.rand([10, 7], device='cuda')) gt_bbox_1 = LiDARInstance3DBoxes(torch.rand([10, 7], device='cuda')) gt_bboxes = [gt_bbox_0, gt_bbox_1] gt_labels_0 = torch.randint(0, 3, [10], device='cuda') gt_labels_1 = torch.randint(0, 3, [10], device='cuda') gt_labels = [gt_labels_0, gt_labels_1] # test_forward_train losses = self.forward_train(points, img_metas, gt_bboxes, gt_labels) assert losses['loss_rpn_cls'][0] >= 0 assert losses['loss_rpn_bbox'][0] >= 0 assert losses['loss_rpn_dir'][0] >= 0 assert losses['loss_seg'] >= 0 assert losses['loss_part'] >= 0 assert losses['loss_cls'] >= 0 assert losses['loss_bbox'] >= 0 assert losses['loss_corner'] >= 0 # test_simple_test with torch.no_grad(): results = self.simple_test(points, img_metas) boxes_3d = results[0]['boxes_3d'] scores_3d = results[0]['scores_3d'] labels_3d = results[0]['labels_3d'] assert boxes_3d.tensor.shape[0] >= 0 assert boxes_3d.tensor.shape[1] == 7 assert scores_3d.shape[0] >= 0 assert labels_3d.shape[0] >= 0
def test_evaluate(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') from mmdet3d.core.bbox import LiDARInstance3DBoxes data_root, ann_file, classes, pts_prefix, pipeline, \ modality, split = _generate_waymo_val_dataset_config() waymo_dataset = WaymoDataset(data_root, ann_file, split, pts_prefix, pipeline, classes, modality) boxes_3d = LiDARInstance3DBoxes( torch.tensor([[ 6.9684e+01, 3.3335e+01, 4.1465e-02, 2.0100e+00, 4.3600e+00, 1.4600e+00, -9.0000e-02 ]])) labels_3d = torch.tensor([0]) scores_3d = torch.tensor([0.5]) result = dict(boxes_3d=boxes_3d, labels_3d=labels_3d, scores_3d=scores_3d) # kitti protocol metric = ['kitti'] ap_dict = waymo_dataset.evaluate([result], metric=metric) assert np.isclose(ap_dict['KITTI/Overall_3D_easy'], 3.0303030303030307) assert np.isclose(ap_dict['KITTI/Overall_3D_moderate'], 3.0303030303030307) assert np.isclose(ap_dict['KITTI/Overall_3D_hard'], 3.0303030303030307) # waymo protocol metric = ['waymo'] boxes_3d = LiDARInstance3DBoxes( torch.tensor([[ 6.9684e+01, 3.3335e+01, 4.1465e-02, 2.0100e+00, 4.3600e+00, 1.4600e+00, -9.0000e-02 ]])) labels_3d = torch.tensor([0]) scores_3d = torch.tensor([0.8]) result = dict(boxes_3d=boxes_3d, labels_3d=labels_3d, scores_3d=scores_3d) ap_dict = waymo_dataset.evaluate([result], metric=metric) assert np.isclose(ap_dict['Overall/L1 mAP'], 0.3333333333333333) assert np.isclose(ap_dict['Overall/L2 mAP'], 0.3333333333333333) assert np.isclose(ap_dict['Overall/L1 mAPH'], 0.3333333333333333) assert np.isclose(ap_dict['Overall/L2 mAPH'], 0.3333333333333333)
def test_matcher_with_pred_boxes_only(self): similarity_measure = Iou() matcher = GreedyMatcher(self.CLASSES) gt_boxes = torch.tensor([], dtype=torch.float) gt_boxes = LiDARInstance3DBoxes(gt_boxes) gt_labels = torch.tensor([], dtype=torch.float) pred_boxes, pred_labels, pred_scores = self.create_pred_boxes() similarity_scores = similarity_measure.calc_scores( gt_boxes, pred_boxes, gt_labels, pred_labels) data_id = 0 matching_results = matcher.match( similarity_scores, gt_boxes, pred_boxes, gt_labels, pred_labels, pred_scores, data_id=data_id, ) expected_results = {} for i in range(len(pred_boxes)): pred_box = pred_boxes[i] label = pred_labels[i].item() res = { 'pred_box': pred_box, 'gt_box': None, 'label': label, 'pred_score': pred_scores[i].item(), 'similarity_score': float("-inf"), 'data_id': data_id } if not label in expected_results: expected_results[label] = [] expected_results[label].append(res) assert expected_results.keys() == matching_results.keys() for k in expected_results.keys(): expected = expected_results[k] matching_res = matching_results[k] for exp, m in zip(expected, matching_res): e_box = exp.pop('pred_box') m_box = m.pop('pred_box') assert (torch.allclose(e_box.tensor, m_box.tensor)) assert (exp == m)
def create_gt_boxes(self): gt_box_matched_label = self.CLASSES[0] gt_box_unmatched_label = self.CLASSES[1] # box dims are x y z w l h yaw gt_box_matched = torch.tensor([0, 0, 0, 1, 1, 1, 0.0]) gt_box_unmatched = torch.tensor([5, 5, 5, 1, 1, 1, 0.0]) gt_boxes = torch.stack((gt_box_matched, gt_box_unmatched)) gt_boxes = LiDARInstance3DBoxes(gt_boxes) return gt_boxes, torch.tensor( [gt_box_matched_label, gt_box_unmatched_label])
def test_show(): import mmcv from os import path as osp from mmdet3d.core.bbox import LiDARInstance3DBoxes tmp_dir = tempfile.TemporaryDirectory() temp_dir = tmp_dir.name class_names = [ 'car', 'truck', 'trailer', 'bus', 'construction_vehicle', 'bicycle', 'motorcycle', 'pedestrian', 'traffic_cone', 'barrier' ] eval_pipeline = [ dict( type='LoadPointsFromFile', coord_type='LIDAR', load_dim=5, use_dim=5, file_client_args=dict(backend='disk')), dict( type='LoadPointsFromMultiSweeps', sweeps_num=10, file_client_args=dict(backend='disk')), dict( type='DefaultFormatBundle3D', class_names=class_names, with_label=False), dict(type='Collect3D', keys=['points']) ] nus_dataset = NuScenesDataset('tests/data/nuscenes/nus_info.pkl', None, 'tests/data/nuscenes') boxes_3d = LiDARInstance3DBoxes( torch.tensor( [[46.1218, -4.6496, -0.9275, 0.5316, 1.4442, 1.7450, 1.1749], [33.3189, 0.1981, 0.3136, 0.5656, 1.2301, 1.7985, 1.5723], [46.1366, -4.6404, -0.9510, 0.5162, 1.6501, 1.7540, 1.3778], [33.2646, 0.2297, 0.3446, 0.5746, 1.3365, 1.7947, 1.5430], [58.9079, 16.6272, -1.5829, 1.5656, 3.9313, 1.4899, 1.5505]])) scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780]) labels_3d = torch.tensor([0, 0, 1, 1, 2]) result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d) results = [dict(pts_bbox=result)] nus_dataset.show(results, temp_dir, show=False, pipeline=eval_pipeline) file_name = 'n015-2018-08-02-17-16-37+0800__LIDAR_TOP__1533201470948018' pts_file_path = osp.join(temp_dir, file_name, f'{file_name}_points.obj') gt_file_path = osp.join(temp_dir, file_name, f'{file_name}_gt.obj') pred_file_path = osp.join(temp_dir, file_name, f'{file_name}_pred.obj') mmcv.check_file_exist(pts_file_path) mmcv.check_file_exist(gt_file_path) mmcv.check_file_exist(pred_file_path) tmp_dir.cleanup()
def create_gt_boxes(self): gt_box1_label = self.CLASSES[0] gt_box2_label = self.CLASSES[1] gt_box_unmatched_label = self.CLASSES[0] # box dims are x y z w l h yaw gt_box_1 = torch.tensor([2, 2, 2, 1, 1, 1, np.deg2rad(20)]) gt_box_2 = torch.tensor([25, 25, 25, 1, 1, 1, np.deg2rad(-20)]) gt_box_unmatched = torch.tensor([50, 50, 50, 1, 1, 1, 0.0]) gt_boxes = torch.stack((gt_box_1, gt_box_2, gt_box_unmatched)) gt_boxes = LiDARInstance3DBoxes(gt_boxes) return gt_boxes, torch.tensor( [gt_box1_label, gt_box2_label, gt_box_unmatched_label])
def test_show(): import mmcv from os import path as osp from mmdet3d.core.bbox import LiDARInstance3DBoxes tmp_dir = tempfile.TemporaryDirectory() temp_dir = tmp_dir.name root_path = './tests/data/lyft' ann_file = './tests/data/lyft/lyft_infos.pkl' class_names = ('car', 'truck', 'bus', 'emergency_vehicle', 'other_vehicle', 'motorcycle', 'bicycle', 'pedestrian', 'animal') eval_pipeline = [ dict(type='LoadPointsFromFile', coord_type='LIDAR', load_dim=5, use_dim=5, file_client_args=dict(backend='disk')), dict(type='LoadPointsFromMultiSweeps', sweeps_num=10, file_client_args=dict(backend='disk')), dict(type='DefaultFormatBundle3D', class_names=class_names, with_label=False), dict(type='Collect3D', keys=['points']) ] kitti_dataset = LyftDataset(ann_file, None, root_path) boxes_3d = LiDARInstance3DBoxes( torch.tensor( [[46.1218, -4.6496, -0.9275, 0.5316, 1.4442, 1.7450, 1.1749], [33.3189, 0.1981, 0.3136, 0.5656, 1.2301, 1.7985, 1.5723], [46.1366, -4.6404, -0.9510, 0.5162, 1.6501, 1.7540, 1.3778], [33.2646, 0.2297, 0.3446, 0.5746, 1.3365, 1.7947, 1.5430], [58.9079, 16.6272, -1.5829, 1.5656, 3.9313, 1.4899, 1.5505]])) scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780]) labels_3d = torch.tensor([0, 0, 1, 1, 2]) result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d) results = [dict(pts_bbox=result)] kitti_dataset.show(results, temp_dir, show=False, pipeline=eval_pipeline) file_name = 'host-a017_lidar1_1236118886901125926' pts_file_path = osp.join(temp_dir, file_name, f'{file_name}_points.obj') gt_file_path = osp.join(temp_dir, file_name, f'{file_name}_gt.obj') pred_file_path = osp.join(temp_dir, file_name, f'{file_name}_pred.obj') mmcv.check_file_exist(pts_file_path) mmcv.check_file_exist(gt_file_path) mmcv.check_file_exist(pred_file_path) tmp_dir.cleanup()
def test_evaluate(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') data_root, ann_file, classes, pts_prefix,\ pipeline, modality, split = _generate_kitti_dataset_config() self = KittiDataset(data_root, ann_file, split, pts_prefix, pipeline, classes, modality) boxes_3d = LiDARInstance3DBoxes( torch.tensor( [[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]])) labels_3d = torch.tensor([ 0, ]) scores_3d = torch.tensor([0.5]) metric = ['mAP'] result = dict(boxes_3d=boxes_3d, labels_3d=labels_3d, scores_3d=scores_3d) ap_dict = self.evaluate([result], metric) assert np.isclose(ap_dict['KITTI/Overall_3D_easy'], 3.0303030303030307) assert np.isclose(ap_dict['KITTI/Overall_3D_moderate'], 3.0303030303030307) assert np.isclose(ap_dict['KITTI/Overall_3D_hard'], 3.0303030303030307)
def test_format_results(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') from mmdet3d.core.bbox import LiDARInstance3DBoxes data_root, ann_file, classes, pts_prefix, pipeline, \ modality, split = _generate_waymo_val_dataset_config() waymo_dataset = WaymoDataset(data_root, ann_file, split, pts_prefix, pipeline, classes, modality) boxes_3d = LiDARInstance3DBoxes( torch.tensor([[ 6.9684e+01, 3.3335e+01, 4.1465e-02, 2.0100e+00, 4.3600e+00, 1.4600e+00, -9.0000e-02 ]])) labels_3d = torch.tensor([0]) scores_3d = torch.tensor([0.5]) result = dict(boxes_3d=boxes_3d, labels_3d=labels_3d, scores_3d=scores_3d) result_files, tmp_dir = waymo_dataset.format_results([result], data_format='waymo') expected_name = np.array(['Car']) expected_truncated = np.array([0.]) expected_occluded = np.array([0]) expected_alpha = np.array([0.35619745]) expected_bbox = np.array([[0., 673.59814, 37.07779, 719.7537]]) expected_dimensions = np.array([[4.36, 1.46, 2.01]]) expected_location = np.array([[-33.000042, 2.4999967, 68.29972]]) expected_rotation_y = np.array([-0.09]) expected_score = np.array([0.5]) expected_sample_idx = np.array([1000000]) assert np.all(result_files[0]['name'] == expected_name) assert np.allclose(result_files[0]['truncated'], expected_truncated) assert np.all(result_files[0]['occluded'] == expected_occluded) assert np.allclose(result_files[0]['alpha'], expected_alpha) assert np.allclose(result_files[0]['bbox'], expected_bbox) assert np.allclose(result_files[0]['dimensions'], expected_dimensions) assert np.allclose(result_files[0]['location'], expected_location) assert np.allclose(result_files[0]['rotation_y'], expected_rotation_y) assert np.allclose(result_files[0]['score'], expected_score) assert np.allclose(result_files[0]['sample_idx'], expected_sample_idx) tmp_dir.cleanup()
def create_pred_boxes(self, ): pred_a_label = self.CLASSES[0] pred_b_label = self.CLASSES[1] pred_c_label = self.CLASSES[0] pred_labels = torch.tensor([pred_a_label, pred_b_label, pred_c_label]) pred_a_score = 1.0 pred_b_score = 0.5 pred_c_score = 0.1 pred_scores = torch.tensor([pred_a_score, pred_b_score, pred_c_score]) # box dims are x y z w l h yaw pred_box_a = torch.tensor([0.1, 0.0, 0, 1, 1, 1, 0.0]) pred_box_b = torch.tensor([42, 42, 42, 1, 1, 1, 0.0]) pred_box_c = torch.tensor([100, 100, 100, 1, 1, 1, 0.0]) pred_boxes = torch.stack((pred_box_a, pred_box_b, pred_box_c)) pred_boxes = LiDARInstance3DBoxes(pred_boxes) return pred_boxes, pred_labels, pred_scores
def test_format_results(): from mmdet3d.core.bbox import LiDARInstance3DBoxes data_root, ann_file, classes, pts_prefix, \ pipeline, modality, split = _generate_kitti_dataset_config() kitti_dataset = KittiDataset(data_root, ann_file, split, pts_prefix, pipeline, classes, modality) boxes_3d = LiDARInstance3DBoxes( torch.tensor( [[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]])) labels_3d = torch.tensor([ 0, ]) scores_3d = torch.tensor([0.5]) result = dict(boxes_3d=boxes_3d, labels_3d=labels_3d, scores_3d=scores_3d) results = [result] result_files, tmp_dir = kitti_dataset.format_results(results) expected_name = np.array(['Pedestrian']) expected_truncated = np.array([0.]) expected_occluded = np.array([0]) expected_alpha = np.array([-3.3410306]) expected_bbox = np.array([[710.443, 144.00221, 820.29114, 307.58667]]) expected_dimensions = np.array([[1.2, 1.89, 0.48]]) expected_location = np.array([[1.8399826, 1.4700007, 8.410018]]) expected_rotation_y = np.array([-3.1315928]) expected_score = np.array([0.5]) expected_sample_idx = np.array([0]) assert np.all(result_files[0]['name'] == expected_name) assert np.allclose(result_files[0]['truncated'], expected_truncated) assert np.all(result_files[0]['occluded'] == expected_occluded) assert np.allclose(result_files[0]['alpha'], expected_alpha) assert np.allclose(result_files[0]['bbox'], expected_bbox) assert np.allclose(result_files[0]['dimensions'], expected_dimensions) assert np.allclose(result_files[0]['location'], expected_location) assert np.allclose(result_files[0]['rotation_y'], expected_rotation_y) assert np.allclose(result_files[0]['score'], expected_score) assert np.allclose(result_files[0]['sample_idx'], expected_sample_idx) tmp_dir.cleanup()
def test_vote_head(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') _setup_seed(0) vote_head_cfg = _get_vote_head_cfg( 'votenet/votenet_8x8_scannet-3d-18class.py') self = build_head(vote_head_cfg).cuda() fp_xyz = [torch.rand([2, 256, 3], dtype=torch.float32).cuda()] fp_features = [torch.rand([2, 256, 256], dtype=torch.float32).cuda()] fp_indices = [torch.randint(0, 128, [2, 256]).cuda()] input_dict = dict(fp_xyz=fp_xyz, fp_features=fp_features, fp_indices=fp_indices) # test forward ret_dict = self(input_dict, 'vote') assert ret_dict['center'].shape == torch.Size([2, 256, 3]) assert ret_dict['obj_scores'].shape == torch.Size([2, 256, 2]) assert ret_dict['size_res'].shape == torch.Size([2, 256, 18, 3]) assert ret_dict['dir_res'].shape == torch.Size([2, 256, 1]) # test loss points = [torch.rand([40000, 4], device='cuda') for i in range(2)] gt_bbox1 = LiDARInstance3DBoxes(torch.rand([10, 7], device='cuda')) gt_bbox2 = LiDARInstance3DBoxes(torch.rand([10, 7], device='cuda')) gt_bboxes = [gt_bbox1, gt_bbox2] gt_labels = [torch.randint(0, 18, [10], device='cuda') for i in range(2)] pts_semantic_mask = [ torch.randint(0, 18, [40000], device='cuda') for i in range(2) ] pts_instance_mask = [ torch.randint(0, 10, [40000], device='cuda') for i in range(2) ] losses = self.loss(ret_dict, points, gt_bboxes, gt_labels, pts_semantic_mask, pts_instance_mask) assert losses['vote_loss'] >= 0 assert losses['objectness_loss'] >= 0 assert losses['semantic_loss'] >= 0 assert losses['center_loss'] >= 0 assert losses['dir_class_loss'] >= 0 assert losses['dir_res_loss'] >= 0 assert losses['size_class_loss'] >= 0 assert losses['size_res_loss'] >= 0 # test multiclass_nms_single obj_scores = torch.rand([256], device='cuda') sem_scores = torch.rand([256, 18], device='cuda') points = torch.rand([40000, 3], device='cuda') bbox = torch.rand([256, 7], device='cuda') input_meta = dict(box_type_3d=DepthInstance3DBoxes) bbox_selected, score_selected, labels = self.multiclass_nms_single( obj_scores, sem_scores, bbox, points, input_meta) assert bbox_selected.shape[0] >= 0 assert bbox_selected.shape[1] == 7 assert score_selected.shape[0] >= 0 assert labels.shape[0] >= 0 # test get_boxes points = torch.rand([1, 40000, 4], device='cuda') seed_points = torch.rand([1, 1024, 3], device='cuda') seed_indices = torch.randint(0, 40000, [1, 1024], device='cuda') vote_points = torch.rand([1, 1024, 3], device='cuda') vote_features = torch.rand([1, 256, 1024], device='cuda') aggregated_points = torch.rand([1, 256, 3], device='cuda') aggregated_indices = torch.range(0, 256, device='cuda') obj_scores = torch.rand([1, 256, 2], device='cuda') center = torch.rand([1, 256, 3], device='cuda') dir_class = torch.rand([1, 256, 1], device='cuda') dir_res_norm = torch.rand([1, 256, 1], device='cuda') dir_res = torch.rand([1, 256, 1], device='cuda') size_class = torch.rand([1, 256, 18], device='cuda') size_res = torch.rand([1, 256, 18, 3], device='cuda') sem_scores = torch.rand([1, 256, 18], device='cuda') bbox_preds = dict(seed_points=seed_points, seed_indices=seed_indices, vote_points=vote_points, vote_features=vote_features, aggregated_points=aggregated_points, aggregated_indices=aggregated_indices, obj_scores=obj_scores, center=center, dir_class=dir_class, dir_res_norm=dir_res_norm, dir_res=dir_res, size_class=size_class, size_res=size_res, sem_scores=sem_scores) results = self.get_bboxes(points, bbox_preds, [input_meta]) assert results[0][0].tensor.shape[0] >= 0 assert results[0][0].tensor.shape[1] == 7 assert results[0][1].shape[0] >= 0 assert results[0][2].shape[0] >= 0
def test_show_result_meshlab(): pcd = 'tests/data/nuscenes/samples/LIDAR_TOP/n015-2018-08-02-17-16-37+' \ '0800__LIDAR_TOP__1533201470948018.pcd.bin' box_3d = LiDARInstance3DBoxes( torch.tensor( [[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]])) labels_3d = torch.tensor([0]) scores_3d = torch.tensor([0.5]) points = np.random.rand(100, 4) img_meta = dict(pts_filename=pcd, boxes_3d=box_3d, box_mode_3d=Box3DMode.LIDAR) data = dict(points=[[torch.tensor(points)]], img_metas=[[img_meta]]) result = [ dict(pts_bbox=dict( boxes_3d=box_3d, labels_3d=labels_3d, scores_3d=scores_3d)) ] tmp_dir = tempfile.TemporaryDirectory() temp_out_dir = tmp_dir.name out_dir, file_name = show_result_meshlab(data, result, temp_out_dir) expected_outfile_pred = file_name + '_pred.obj' expected_outfile_pts = file_name + '_points.obj' expected_outfile_pred_path = os.path.join(out_dir, file_name, expected_outfile_pred) expected_outfile_pts_path = os.path.join(out_dir, file_name, expected_outfile_pts) assert os.path.exists(expected_outfile_pred_path) assert os.path.exists(expected_outfile_pts_path) tmp_dir.cleanup() # test multi-modality show # indoor scene pcd = 'tests/data/sunrgbd/points/000001.bin' filename = 'tests/data/sunrgbd/sunrgbd_trainval/image/000001.jpg' box_3d = DepthInstance3DBoxes( torch.tensor( [[-1.1580, 3.3041, -0.9961, 0.3829, 0.4647, 0.5574, 1.1213]])) img = np.random.randn(1, 3, 608, 832) k_mat = np.array([[529.5000, 0.0000, 365.0000], [0.0000, 529.5000, 265.0000], [0.0000, 0.0000, 1.0000]]) rt_mat = np.array([[0.9980, 0.0058, -0.0634], [0.0058, 0.9835, 0.1808], [0.0634, -0.1808, 0.9815]]) rt_mat = np.array([[1, 0, 0], [0, 0, -1], [0, 1, 0]]) @ rt_mat.transpose( 1, 0) depth2img = k_mat @ rt_mat img_meta = dict(filename=filename, depth2img=depth2img, pcd_horizontal_flip=False, pcd_vertical_flip=False, box_mode_3d=Box3DMode.DEPTH, box_type_3d=DepthInstance3DBoxes, pcd_trans=np.array([0., 0., 0.]), pcd_scale_factor=1.0, pts_filename=pcd, transformation_3d_flow=['R', 'S', 'T']) data = dict(points=[[torch.tensor(points)]], img_metas=[[img_meta]], img=[img]) result = [dict(boxes_3d=box_3d, labels_3d=labels_3d, scores_3d=scores_3d)] tmp_dir = tempfile.TemporaryDirectory() temp_out_dir = tmp_dir.name out_dir, file_name = show_result_meshlab(data, result, temp_out_dir, 0.3, task='multi_modality-det') expected_outfile_pred = file_name + '_pred.obj' expected_outfile_pts = file_name + '_points.obj' expected_outfile_png = file_name + '_img.png' expected_outfile_proj = file_name + '_pred.png' expected_outfile_pred_path = os.path.join(out_dir, file_name, expected_outfile_pred) expected_outfile_pts_path = os.path.join(out_dir, file_name, expected_outfile_pts) expected_outfile_png_path = os.path.join(out_dir, file_name, expected_outfile_png) expected_outfile_proj_path = os.path.join(out_dir, file_name, expected_outfile_proj) assert os.path.exists(expected_outfile_pred_path) assert os.path.exists(expected_outfile_pts_path) assert os.path.exists(expected_outfile_png_path) assert os.path.exists(expected_outfile_proj_path) tmp_dir.cleanup() # outdoor scene pcd = 'tests/data/kitti/training/velodyne_reduced/000000.bin' filename = 'tests/data/kitti/training/image_2/000000.png' box_3d = LiDARInstance3DBoxes( torch.tensor( [[6.4495, -3.9097, -1.7409, 1.5063, 3.1819, 1.4716, 1.8782]])) img = np.random.randn(1, 3, 384, 1280) lidar2img = np.array( [[6.09695435e+02, -7.21421631e+02, -1.25125790e+00, -1.23041824e+02], [1.80384201e+02, 7.64479828e+00, -7.19651550e+02, -1.01016693e+02], [9.99945343e-01, 1.24365499e-04, 1.04513029e-02, -2.69386917e-01], [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) img_meta = dict(filename=filename, pcd_horizontal_flip=False, pcd_vertical_flip=False, box_mode_3d=Box3DMode.LIDAR, box_type_3d=LiDARInstance3DBoxes, pcd_trans=np.array([0., 0., 0.]), pcd_scale_factor=1.0, pts_filename=pcd, lidar2img=lidar2img) data = dict(points=[[torch.tensor(points)]], img_metas=[[img_meta]], img=[img]) result = [ dict(pts_bbox=dict( boxes_3d=box_3d, labels_3d=labels_3d, scores_3d=scores_3d)) ] out_dir, file_name = show_result_meshlab(data, result, temp_out_dir, 0.1, task='multi_modality-det') tmp_dir = tempfile.TemporaryDirectory() temp_out_dir = tmp_dir.name expected_outfile_pred = file_name + '_pred.obj' expected_outfile_pts = file_name + '_points.obj' expected_outfile_png = file_name + '_img.png' expected_outfile_proj = file_name + '_pred.png' expected_outfile_pred_path = os.path.join(out_dir, file_name, expected_outfile_pred) expected_outfile_pts_path = os.path.join(out_dir, file_name, expected_outfile_pts) expected_outfile_png_path = os.path.join(out_dir, file_name, expected_outfile_png) expected_outfile_proj_path = os.path.join(out_dir, file_name, expected_outfile_proj) assert os.path.exists(expected_outfile_pred_path) assert os.path.exists(expected_outfile_pts_path) assert os.path.exists(expected_outfile_png_path) assert os.path.exists(expected_outfile_proj_path) tmp_dir.cleanup() # test mono-3d show filename = 'tests/data/nuscenes/samples/CAM_BACK_LEFT/n015-2018-' \ '07-18-11-07-57+0800__CAM_BACK_LEFT__1531883530447423.jpg' box_3d = CameraInstance3DBoxes( torch.tensor( [[6.4495, -3.9097, -1.7409, 1.5063, 3.1819, 1.4716, 1.8782]])) img = np.random.randn(1, 3, 384, 1280) cam2img = np.array([[100.0, 0.0, 50.0], [0.0, 100.0, 50.0], [0.0, 0.0, 1.0]]) img_meta = dict(filename=filename, pcd_horizontal_flip=False, pcd_vertical_flip=False, box_mode_3d=Box3DMode.CAM, box_type_3d=CameraInstance3DBoxes, pcd_trans=np.array([0., 0., 0.]), pcd_scale_factor=1.0, cam2img=cam2img) data = dict(points=[[torch.tensor(points)]], img_metas=[[img_meta]], img=[img]) result = [ dict(img_bbox=dict( boxes_3d=box_3d, labels_3d=labels_3d, scores_3d=scores_3d)) ] out_dir, file_name = show_result_meshlab(data, result, temp_out_dir, 0.1, task='mono-det') tmp_dir = tempfile.TemporaryDirectory() temp_out_dir = tmp_dir.name expected_outfile_png = file_name + '_img.png' expected_outfile_proj = file_name + '_pred.png' expected_outfile_png_path = os.path.join(out_dir, file_name, expected_outfile_png) expected_outfile_proj_path = os.path.join(out_dir, file_name, expected_outfile_proj) assert os.path.exists(expected_outfile_png_path) assert os.path.exists(expected_outfile_proj_path) tmp_dir.cleanup() # test seg show pcd = 'tests/data/scannet/points/scene0000_00.bin' points = np.random.rand(100, 6) img_meta = dict(pts_filename=pcd) data = dict(points=[[torch.tensor(points)]], img_metas=[[img_meta]]) pred_seg = torch.randint(0, 20, (100, )) result = [dict(semantic_mask=pred_seg)] tmp_dir = tempfile.TemporaryDirectory() temp_out_dir = tmp_dir.name out_dir, file_name = show_result_meshlab(data, result, temp_out_dir, task='seg') expected_outfile_pred = file_name + '_pred.obj' expected_outfile_pts = file_name + '_points.obj' expected_outfile_pred_path = os.path.join(out_dir, file_name, expected_outfile_pred) expected_outfile_pts_path = os.path.join(out_dir, file_name, expected_outfile_pts) assert os.path.exists(expected_outfile_pred_path) assert os.path.exists(expected_outfile_pts_path) tmp_dir.cleanup()
def test_boxes_conversion(): # test CAM to LIDAR and DEPTH cam_boxes = CameraInstance3DBoxes( [[1.7802081, 2.516249, -1.7501148, 1.75, 3.39, 1.65, 1.48], [8.959413, 2.4567227, -1.6357126, 1.54, 4.01, 1.57, 1.62], [28.2967, -0.5557558, -1.303325, 1.47, 2.23, 1.48, -1.57], [26.66902, 21.82302, -1.736057, 1.56, 3.48, 1.4, -1.69], [31.31978, 8.162144, -1.6217787, 1.74, 3.77, 1.48, 2.79]]) convert_lidar_boxes = Coord3DMode.convert(cam_boxes, Coord3DMode.CAM, Coord3DMode.LIDAR) expected_tensor = torch.tensor( [[-1.7501, -1.7802, -2.5162, 1.6500, 1.7500, 3.3900, 1.4800], [-1.6357, -8.9594, -2.4567, 1.5700, 1.5400, 4.0100, 1.6200], [-1.3033, -28.2967, 0.5558, 1.4800, 1.4700, 2.2300, -1.5700], [-1.7361, -26.6690, -21.8230, 1.4000, 1.5600, 3.4800, -1.6900], [-1.6218, -31.3198, -8.1621, 1.4800, 1.7400, 3.7700, 2.7900]]) assert torch.allclose(expected_tensor, convert_lidar_boxes.tensor, 1e-3) convert_depth_boxes = Coord3DMode.convert(cam_boxes, Coord3DMode.CAM, Coord3DMode.DEPTH) expected_tensor = torch.tensor( [[1.7802, 1.7501, 2.5162, 1.7500, 1.6500, 3.3900, 1.4800], [8.9594, 1.6357, 2.4567, 1.5400, 1.5700, 4.0100, 1.6200], [28.2967, 1.3033, -0.5558, 1.4700, 1.4800, 2.2300, -1.5700], [26.6690, 1.7361, 21.8230, 1.5600, 1.4000, 3.4800, -1.6900], [31.3198, 1.6218, 8.1621, 1.7400, 1.4800, 3.7700, 2.7900]]) assert torch.allclose(expected_tensor, convert_depth_boxes.tensor, 1e-3) # test LIDAR to CAM and DEPTH lidar_boxes = LiDARInstance3DBoxes( [[1.7802081, 2.516249, -1.7501148, 1.75, 3.39, 1.65, 1.48], [8.959413, 2.4567227, -1.6357126, 1.54, 4.01, 1.57, 1.62], [28.2967, -0.5557558, -1.303325, 1.47, 2.23, 1.48, -1.57], [26.66902, 21.82302, -1.736057, 1.56, 3.48, 1.4, -1.69], [31.31978, 8.162144, -1.6217787, 1.74, 3.77, 1.48, 2.79]]) convert_cam_boxes = Coord3DMode.convert(lidar_boxes, Coord3DMode.LIDAR, Coord3DMode.CAM) expected_tensor = torch.tensor( [[-2.5162, 1.7501, 1.7802, 3.3900, 1.6500, 1.7500, 1.4800], [-2.4567, 1.6357, 8.9594, 4.0100, 1.5700, 1.5400, 1.6200], [0.5558, 1.3033, 28.2967, 2.2300, 1.4800, 1.4700, -1.5700], [-21.8230, 1.7361, 26.6690, 3.4800, 1.4000, 1.5600, -1.6900], [-8.1621, 1.6218, 31.3198, 3.7700, 1.4800, 1.7400, 2.7900]]) assert torch.allclose(expected_tensor, convert_cam_boxes.tensor, 1e-3) convert_depth_boxes = Coord3DMode.convert(lidar_boxes, Coord3DMode.LIDAR, Coord3DMode.DEPTH) expected_tensor = torch.tensor( [[-2.5162, 1.7802, -1.7501, 3.3900, 1.7500, 1.6500, 1.4800], [-2.4567, 8.9594, -1.6357, 4.0100, 1.5400, 1.5700, 1.6200], [0.5558, 28.2967, -1.3033, 2.2300, 1.4700, 1.4800, -1.5700], [-21.8230, 26.6690, -1.7361, 3.4800, 1.5600, 1.4000, -1.6900], [-8.1621, 31.3198, -1.6218, 3.7700, 1.7400, 1.4800, 2.7900]]) assert torch.allclose(expected_tensor, convert_depth_boxes.tensor, 1e-3) # test DEPTH to CAM and LIDAR depth_boxes = DepthInstance3DBoxes( [[1.7802081, 2.516249, -1.7501148, 1.75, 3.39, 1.65, 1.48], [8.959413, 2.4567227, -1.6357126, 1.54, 4.01, 1.57, 1.62], [28.2967, -0.5557558, -1.303325, 1.47, 2.23, 1.48, -1.57], [26.66902, 21.82302, -1.736057, 1.56, 3.48, 1.4, -1.69], [31.31978, 8.162144, -1.6217787, 1.74, 3.77, 1.48, 2.79]]) convert_cam_boxes = Coord3DMode.convert(depth_boxes, Coord3DMode.DEPTH, Coord3DMode.CAM) expected_tensor = torch.tensor( [[1.7802, -1.7501, -2.5162, 1.7500, 1.6500, 3.3900, 1.4800], [8.9594, -1.6357, -2.4567, 1.5400, 1.5700, 4.0100, 1.6200], [28.2967, -1.3033, 0.5558, 1.4700, 1.4800, 2.2300, -1.5700], [26.6690, -1.7361, -21.8230, 1.5600, 1.4000, 3.4800, -1.6900], [31.3198, -1.6218, -8.1621, 1.7400, 1.4800, 3.7700, 2.7900]]) assert torch.allclose(expected_tensor, convert_cam_boxes.tensor, 1e-3) convert_lidar_boxes = Coord3DMode.convert(depth_boxes, Coord3DMode.DEPTH, Coord3DMode.LIDAR) expected_tensor = torch.tensor( [[2.5162, -1.7802, -1.7501, 3.3900, 1.7500, 1.6500, 1.4800], [2.4567, -8.9594, -1.6357, 4.0100, 1.5400, 1.5700, 1.6200], [-0.5558, -28.2967, -1.3033, 2.2300, 1.4700, 1.4800, -1.5700], [21.8230, -26.6690, -1.7361, 3.4800, 1.5600, 1.4000, -1.6900], [8.1621, -31.3198, -1.6218, 3.7700, 1.7400, 1.4800, 2.7900]]) assert torch.allclose(expected_tensor, convert_lidar_boxes.tensor, 1e-3)
def test_PointwiseSemanticHead(): # PointwiseSemanticHead only support gpu version currently. if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') from mmdet3d.models.builder import build_head head_cfg = dict( type='PointwiseSemanticHead', in_channels=8, extra_width=0.2, seg_score_thr=0.3, num_classes=3, loss_seg=dict( type='FocalLoss', use_sigmoid=True, reduction='sum', gamma=2.0, alpha=0.25, loss_weight=1.0), loss_part=dict( type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0)) self = build_head(head_cfg) self.cuda() # test forward voxel_features = torch.rand([4, 8], dtype=torch.float32).cuda() feats_dict = self.forward(voxel_features) assert feats_dict['seg_preds'].shape == torch.Size( [voxel_features.shape[0], 1]) assert feats_dict['part_preds'].shape == torch.Size( [voxel_features.shape[0], 3]) assert feats_dict['part_feats'].shape == torch.Size( [voxel_features.shape[0], 4]) voxel_centers = torch.tensor( [[6.56126, 0.9648336, -1.7339306], [6.8162713, -2.480431, -1.3616394], [11.643568, -4.744306, -1.3580885], [23.482342, 6.5036807, 0.5806964] ], dtype=torch.float32).cuda() # n, point_features coordinates = torch.tensor( [[0, 12, 819, 131], [0, 16, 750, 136], [1, 16, 705, 232], [1, 35, 930, 469]], dtype=torch.int32).cuda() # n, 4(batch, ind_x, ind_y, ind_z) voxel_dict = dict(voxel_centers=voxel_centers, coors=coordinates) gt_bboxes = [ LiDARInstance3DBoxes( torch.tensor( [[6.4118, -3.4305, -1.7291, 1.7033, 3.4693, 1.6197, -0.9091]], dtype=torch.float32).cuda()), LiDARInstance3DBoxes( torch.tensor( [[16.9107, 9.7925, -1.9201, 1.6097, 3.2786, 1.5307, -2.4056]], dtype=torch.float32).cuda()) ] # batch size is 2 in the unit test gt_labels = list(torch.tensor([[0], [1]], dtype=torch.int64).cuda()) # test get_targets target_dict = self.get_targets(voxel_dict, gt_bboxes, gt_labels) assert target_dict['seg_targets'].shape == torch.Size( [voxel_features.shape[0]]) assert torch.allclose(target_dict['seg_targets'], target_dict['seg_targets'].new_tensor([3, -1, 3, 3])) assert target_dict['part_targets'].shape == torch.Size( [voxel_features.shape[0], 3]) assert target_dict['part_targets'].sum() == 0 # test loss loss_dict = self.loss(feats_dict, target_dict) assert loss_dict['loss_seg'] > 0 assert loss_dict['loss_part'] == 0 # no points in gt_boxes total_loss = loss_dict['loss_seg'] + loss_dict['loss_part'] total_loss.backward()
def test_shape_aware_head_loss(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') bbox_head_cfg = _get_pts_bbox_head_cfg( 'ssn/hv_ssn_secfpn_sbn-all_2x16_2x_lyft-3d.py') # modify bn config to avoid bugs caused by syncbn for task in bbox_head_cfg['tasks']: task['norm_cfg'] = dict(type='BN2d') from mmdet3d.models.builder import build_head self = build_head(bbox_head_cfg) self.cuda() assert len(self.heads) == 4 assert isinstance(self.heads[0].conv_cls, torch.nn.modules.conv.Conv2d) assert self.heads[0].conv_cls.in_channels == 64 assert self.heads[0].conv_cls.out_channels == 36 assert self.heads[0].conv_reg.out_channels == 28 assert self.heads[0].conv_dir_cls.out_channels == 8 # test forward feats = list() feats.append(torch.rand([2, 384, 200, 200], dtype=torch.float32).cuda()) (cls_score, bbox_pred, dir_cls_preds) = self.forward(feats) assert cls_score[0].shape == torch.Size([2, 420000, 9]) assert bbox_pred[0].shape == torch.Size([2, 420000, 7]) assert dir_cls_preds[0].shape == torch.Size([2, 420000, 2]) # test loss gt_bboxes = [ LiDARInstance3DBoxes( torch.tensor( [[-14.5695, -6.4169, -2.1054, 1.8830, 4.6720, 1.4840, 1.5587], [25.7215, 3.4581, -1.3456, 1.6720, 4.4090, 1.5830, 1.5301]], dtype=torch.float32).cuda()), LiDARInstance3DBoxes( torch.tensor( [[-50.763, -3.5517, -0.99658, 1.7430, 4.4020, 1.6990, 1.7874], [-68.720, 0.033, -0.75276, 1.7860, 4.9100, 1.6610, 1.7525]], dtype=torch.float32).cuda()) ] gt_labels = list(torch.tensor([[4, 4], [4, 4]], dtype=torch.int64).cuda()) input_metas = [{ 'sample_idx': 1234 }, { 'sample_idx': 2345 }] # fake input_metas losses = self.loss(cls_score, bbox_pred, dir_cls_preds, gt_bboxes, gt_labels, input_metas) assert losses['loss_cls'][0] > 0 assert losses['loss_bbox'][0] > 0 assert losses['loss_dir'][0] > 0 # test empty ground truth case gt_bboxes = list(torch.empty((2, 0, 7)).cuda()) gt_labels = list(torch.empty((2, 0)).cuda()) empty_gt_losses = self.loss(cls_score, bbox_pred, dir_cls_preds, gt_bboxes, gt_labels, input_metas) assert empty_gt_losses['loss_cls'][0] > 0 assert empty_gt_losses['loss_bbox'][0] == 0 assert empty_gt_losses['loss_dir'][0] == 0
def test_dcn_center_head(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and CUDA') set_random_seed(0) tasks = [ dict(num_class=1, class_names=['car']), dict(num_class=2, class_names=['truck', 'construction_vehicle']), dict(num_class=2, class_names=['bus', 'trailer']), dict(num_class=1, class_names=['barrier']), dict(num_class=2, class_names=['motorcycle', 'bicycle']), dict(num_class=2, class_names=['pedestrian', 'traffic_cone']), ] voxel_size = [0.2, 0.2, 8] dcn_center_head_cfg = dict( type='CenterHead', in_channels=sum([128, 128, 128]), tasks=[ dict(num_class=1, class_names=['car']), dict(num_class=2, class_names=['truck', 'construction_vehicle']), dict(num_class=2, class_names=['bus', 'trailer']), dict(num_class=1, class_names=['barrier']), dict(num_class=2, class_names=['motorcycle', 'bicycle']), dict(num_class=2, class_names=['pedestrian', 'traffic_cone']), ], common_heads={ 'reg': (2, 2), 'height': (1, 2), 'dim': (3, 2), 'rot': (2, 2), 'vel': (2, 2) }, share_conv_channel=64, bbox_coder=dict( type='CenterPointBBoxCoder', post_center_range=[-61.2, -61.2, -10.0, 61.2, 61.2, 10.0], max_num=500, score_threshold=0.1, pc_range=[-51.2, -51.2], out_size_factor=4, voxel_size=voxel_size[:2], code_size=9), separate_head=dict( type='DCNSeparateHead', dcn_config=dict( type='DCN', in_channels=64, out_channels=64, kernel_size=3, padding=1, groups=4, bias=False), # mmcv 1.2.6 doesn't support bias=True anymore init_bias=-2.19, final_kernel=3), loss_cls=dict(type='GaussianFocalLoss', reduction='mean'), loss_bbox=dict(type='L1Loss', reduction='none', loss_weight=0.25), norm_bbox=True) # model training and testing settings train_cfg = dict( grid_size=[512, 512, 1], point_cloud_range=[-51.2, -51.2, -5., 51.2, 51.2, 3.], voxel_size=voxel_size, out_size_factor=4, dense_reg=1, gaussian_overlap=0.1, max_objs=500, min_radius=2, code_weights=[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.2, 1.0, 1.0]) test_cfg = dict( post_center_limit_range=[-61.2, -61.2, -10.0, 61.2, 61.2, 10.0], max_per_img=500, max_pool_nms=False, min_radius=[4, 12, 10, 1, 0.85, 0.175], post_max_size=83, score_threshold=0.1, pc_range=[-51.2, -51.2], out_size_factor=4, voxel_size=voxel_size[:2], nms_type='circle') dcn_center_head_cfg.update(train_cfg=train_cfg, test_cfg=test_cfg) dcn_center_head = build_head(dcn_center_head_cfg).cuda() x = torch.ones([2, 384, 128, 128]).cuda() output = dcn_center_head([x]) for i in range(6): assert output[i][0]['reg'].shape == torch.Size([2, 2, 128, 128]) assert output[i][0]['height'].shape == torch.Size([2, 1, 128, 128]) assert output[i][0]['dim'].shape == torch.Size([2, 3, 128, 128]) assert output[i][0]['rot'].shape == torch.Size([2, 2, 128, 128]) assert output[i][0]['vel'].shape == torch.Size([2, 2, 128, 128]) assert output[i][0]['heatmap'].shape == torch.Size( [2, tasks[i]['num_class'], 128, 128]) # Test loss. gt_bboxes_0 = LiDARInstance3DBoxes(torch.rand([10, 9]).cuda(), box_dim=9) gt_bboxes_1 = LiDARInstance3DBoxes(torch.rand([20, 9]).cuda(), box_dim=9) gt_labels_0 = torch.randint(1, 11, [10]).cuda() gt_labels_1 = torch.randint(1, 11, [20]).cuda() gt_bboxes_3d = [gt_bboxes_0, gt_bboxes_1] gt_labels_3d = [gt_labels_0, gt_labels_1] loss = dcn_center_head.loss(gt_bboxes_3d, gt_labels_3d, output) for key, item in loss.items(): if 'heatmap' in key: assert item >= 0 else: assert torch.sum(item) >= 0 # test get_bboxes img_metas = [ dict(box_type_3d=LiDARInstance3DBoxes), dict(box_type_3d=LiDARInstance3DBoxes) ] ret_lists = dcn_center_head.get_bboxes(output, img_metas) for ret_list in ret_lists: assert ret_list[0].tensor.shape[0] <= 500 assert ret_list[1].shape[0] <= 500 assert ret_list[2].shape[0] <= 500
def test_part_aggregation_ROI_head(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') roi_head_cfg = _get_roi_head_cfg( 'parta2/hv_PartA2_secfpn_2x8_cyclic_80e_kitti-3d-3class.py') self = build_head(roi_head_cfg).cuda() features = np.load('./tests/test_samples/parta2_roihead_inputs.npz') seg_features = torch.tensor(features['seg_features'], dtype=torch.float32, device='cuda') feats_dict = dict(seg_features=seg_features) voxels = torch.tensor(features['voxels'], dtype=torch.float32, device='cuda') num_points = torch.ones([500], device='cuda') coors = torch.zeros([500, 4], device='cuda') voxel_centers = torch.zeros([500, 3], device='cuda') box_type_3d = LiDARInstance3DBoxes img_metas = [dict(box_type_3d=box_type_3d)] voxels_dict = dict(voxels=voxels, num_points=num_points, coors=coors, voxel_centers=voxel_centers) pred_bboxes = LiDARInstance3DBoxes( torch.tensor( [[0.3990, 0.5167, 0.0249, 0.9401, 0.9459, 0.7967, 0.4150], [0.8203, 0.2290, 0.9096, 0.1183, 0.0752, 0.4092, 0.9601], [0.2093, 0.1940, 0.8909, 0.4387, 0.3570, 0.5454, 0.8299], [0.2099, 0.7684, 0.4290, 0.2117, 0.6606, 0.1654, 0.4250], [0.9927, 0.6964, 0.2472, 0.7028, 0.7494, 0.9303, 0.0494]], dtype=torch.float32, device='cuda')) pred_scores = torch.tensor([0.9722, 0.7910, 0.4690, 0.3300, 0.3345], dtype=torch.float32, device='cuda') pred_labels = torch.tensor([0, 1, 0, 2, 1], dtype=torch.int64, device='cuda') pred_clses = torch.tensor( [[0.7874, 0.1344, 0.2190], [0.8193, 0.6969, 0.7304], [0.2328, 0.9028, 0.3900], [0.6177, 0.5012, 0.2330], [0.8985, 0.4894, 0.7152]], dtype=torch.float32, device='cuda') proposal = dict(boxes_3d=pred_bboxes, scores_3d=pred_scores, labels_3d=pred_labels, cls_preds=pred_clses) proposal_list = [proposal] gt_bboxes_3d = [LiDARInstance3DBoxes(torch.rand([5, 7], device='cuda'))] gt_labels_3d = [torch.randint(0, 3, [5], device='cuda')] losses = self.forward_train(feats_dict, voxels_dict, {}, proposal_list, gt_bboxes_3d, gt_labels_3d) assert losses['loss_seg'] >= 0 assert losses['loss_part'] >= 0 assert losses['loss_cls'] >= 0 assert losses['loss_bbox'] >= 0 assert losses['loss_corner'] >= 0 bbox_results = self.simple_test(feats_dict, voxels_dict, img_metas, proposal_list) boxes_3d = bbox_results[0]['boxes_3d'] scores_3d = bbox_results[0]['scores_3d'] labels_3d = bbox_results[0]['labels_3d'] assert boxes_3d.tensor.shape == (12, 7) assert scores_3d.shape == (12, ) assert labels_3d.shape == (12, )