Unverified Commit 32a4328b authored by Wenwei Zhang's avatar Wenwei Zhang Committed by GitHub
Browse files

Bump version to V1.0.0rc0

Bump version to V1.0.0rc0
parents 86cc487c a8817998
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import numpy as np import math
import os import os
import pytest
import tempfile import tempfile
import numpy as np
import pytest
import torch import torch
from mmdet3d.core.bbox import LiDARInstance3DBoxes from mmdet3d.core.bbox import LiDARInstance3DBoxes, limit_period
from mmdet3d.datasets import KittiDataset from mmdet3d.datasets import KittiDataset
...@@ -113,6 +115,7 @@ def test_getitem(): ...@@ -113,6 +115,7 @@ def test_getitem():
type='ObjectSample', type='ObjectSample',
db_sampler=dict( db_sampler=dict(
data_root='tests/data/kitti/', data_root='tests/data/kitti/',
# in coordinate system refactor, this test file is modified
info_path='tests/data/kitti/kitti_dbinfos_train.pkl', info_path='tests/data/kitti/kitti_dbinfos_train.pkl',
rate=1.0, rate=1.0,
prepare=dict( prepare=dict(
...@@ -151,8 +154,29 @@ def test_getitem(): ...@@ -151,8 +154,29 @@ def test_getitem():
gt_bboxes_3d = data['gt_bboxes_3d']._data gt_bboxes_3d = data['gt_bboxes_3d']._data
gt_labels_3d = data['gt_labels_3d']._data gt_labels_3d = data['gt_labels_3d']._data
expected_gt_bboxes_3d = torch.tensor( expected_gt_bboxes_3d = torch.tensor(
[[9.5081, -5.2269, -1.1370, 0.4915, 1.2288, 1.9353, -2.7136]]) [[9.5081, -5.2269, -1.1370, 1.2288, 0.4915, 1.9353, 1.9988]])
expected_gt_labels_3d = torch.tensor([0]) expected_gt_labels_3d = torch.tensor([0])
rot_matrix = data['img_metas']._data['pcd_rotation']
rot_angle = data['img_metas']._data['pcd_rotation_angle']
horizontal_flip = data['img_metas']._data['pcd_horizontal_flip']
vertical_flip = data['img_metas']._data['pcd_vertical_flip']
expected_rot_matrix = torch.tensor([[0.8018, 0.5976, 0.0000],
[-0.5976, 0.8018, 0.0000],
[0.0000, 0.0000, 1.0000]])
expected_rot_angle = 0.6404654291602163
noise_angle = 0.20247319
assert torch.allclose(expected_rot_matrix, rot_matrix, atol=1e-4)
assert math.isclose(expected_rot_angle, rot_angle, abs_tol=1e-4)
assert horizontal_flip is True
assert vertical_flip is False
# after coord system refactor
expected_gt_bboxes_3d[:, :3] = \
expected_gt_bboxes_3d[:, :3] @ rot_matrix @ rot_matrix
expected_gt_bboxes_3d[:, -1:] = -np.pi - expected_gt_bboxes_3d[:, -1:] \
+ 2 * rot_angle - 2 * noise_angle
expected_gt_bboxes_3d[:, -1:] = limit_period(
expected_gt_bboxes_3d[:, -1:], period=np.pi * 2)
assert points.shape == (780, 4) assert points.shape == (780, 4)
assert torch.allclose( assert torch.allclose(
gt_bboxes_3d.tensor, expected_gt_bboxes_3d, atol=1e-4) gt_bboxes_3d.tensor, expected_gt_bboxes_3d, atol=1e-4)
...@@ -232,9 +256,10 @@ def test_evaluate(): ...@@ -232,9 +256,10 @@ def test_evaluate():
def test_show(): def test_show():
import mmcv
from os import path as osp from os import path as osp
import mmcv
from mmdet3d.core.bbox import LiDARInstance3DBoxes from mmdet3d.core.bbox import LiDARInstance3DBoxes
tmp_dir = tempfile.TemporaryDirectory() tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name temp_dir = tmp_dir.name
...@@ -346,9 +371,10 @@ def test_format_results(): ...@@ -346,9 +371,10 @@ def test_format_results():
pipeline, modality, split = _generate_kitti_dataset_config() pipeline, modality, split = _generate_kitti_dataset_config()
kitti_dataset = KittiDataset(data_root, ann_file, split, pts_prefix, kitti_dataset = KittiDataset(data_root, ann_file, split, pts_prefix,
pipeline, classes, modality) pipeline, classes, modality)
# coord system refactor
boxes_3d = LiDARInstance3DBoxes( boxes_3d = LiDARInstance3DBoxes(
torch.tensor( torch.tensor(
[[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]])) [[8.7314, -1.8559, -1.5997, 1.2000, 0.4800, 1.8900, -1.5808]]))
labels_3d = torch.tensor([ labels_3d = torch.tensor([
0, 0,
]) ])
...@@ -359,21 +385,23 @@ def test_format_results(): ...@@ -359,21 +385,23 @@ def test_format_results():
expected_name = np.array(['Pedestrian']) expected_name = np.array(['Pedestrian'])
expected_truncated = np.array([0.]) expected_truncated = np.array([0.])
expected_occluded = np.array([0]) expected_occluded = np.array([0])
expected_alpha = np.array([-3.3410306]) # coord sys refactor
expected_alpha = np.array(-3.3410306 + np.pi)
expected_bbox = np.array([[710.443, 144.00221, 820.29114, 307.58667]]) expected_bbox = np.array([[710.443, 144.00221, 820.29114, 307.58667]])
expected_dimensions = np.array([[1.2, 1.89, 0.48]]) expected_dimensions = np.array([[1.2, 1.89, 0.48]])
expected_location = np.array([[1.8399826, 1.4700007, 8.410018]]) expected_location = np.array([[1.8399826, 1.4700007, 8.410018]])
expected_rotation_y = np.array([-3.1315928]) expected_rotation_y = np.array([0.0100])
expected_score = np.array([0.5]) expected_score = np.array([0.5])
expected_sample_idx = np.array([0]) expected_sample_idx = np.array([0])
assert np.all(result_files[0]['name'] == expected_name) assert np.all(result_files[0]['name'] == expected_name)
assert np.allclose(result_files[0]['truncated'], expected_truncated) assert np.allclose(result_files[0]['truncated'], expected_truncated)
assert np.all(result_files[0]['occluded'] == expected_occluded) assert np.all(result_files[0]['occluded'] == expected_occluded)
assert np.allclose(result_files[0]['alpha'], expected_alpha) assert np.allclose(result_files[0]['alpha'], expected_alpha, 1e-3)
assert np.allclose(result_files[0]['bbox'], expected_bbox) assert np.allclose(result_files[0]['bbox'], expected_bbox)
assert np.allclose(result_files[0]['dimensions'], expected_dimensions) assert np.allclose(result_files[0]['dimensions'], expected_dimensions)
assert np.allclose(result_files[0]['location'], expected_location) 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]['rotation_y'], expected_rotation_y,
1e-3)
assert np.allclose(result_files[0]['score'], expected_score) assert np.allclose(result_files[0]['score'], expected_score)
assert np.allclose(result_files[0]['sample_idx'], expected_sample_idx) assert np.allclose(result_files[0]['sample_idx'], expected_sample_idx)
tmp_dir.cleanup() tmp_dir.cleanup()
...@@ -386,7 +414,7 @@ def test_bbox2result_kitti(): ...@@ -386,7 +414,7 @@ def test_bbox2result_kitti():
pipeline, classes, modality) pipeline, classes, modality)
boxes_3d = LiDARInstance3DBoxes( boxes_3d = LiDARInstance3DBoxes(
torch.tensor( torch.tensor(
[[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]])) [[8.7314, -1.8559, -1.5997, 1.2000, 0.4800, 1.8900, -1.5808]]))
labels_3d = torch.tensor([ labels_3d = torch.tensor([
0, 0,
]) ])
...@@ -400,10 +428,11 @@ def test_bbox2result_kitti(): ...@@ -400,10 +428,11 @@ def test_bbox2result_kitti():
expected_file_path = os.path.join(temp_kitti_result_dir, '000000.txt') expected_file_path = os.path.join(temp_kitti_result_dir, '000000.txt')
expected_name = np.array(['Pedestrian']) expected_name = np.array(['Pedestrian'])
expected_dimensions = np.array([1.2000, 1.8900, 0.4800]) expected_dimensions = np.array([1.2000, 1.8900, 0.4800])
expected_rotation_y = np.array([0.0100]) - np.pi # coord system refactor (reverse sign)
expected_rotation_y = 0.0100
expected_score = np.array([0.5]) expected_score = np.array([0.5])
assert np.all(det_annos[0]['name'] == expected_name) 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]['rotation_y'], expected_rotation_y, 1e-3)
assert np.allclose(det_annos[0]['score'], expected_score) assert np.allclose(det_annos[0]['score'], expected_score)
assert np.allclose(det_annos[0]['dimensions'], expected_dimensions) assert np.allclose(det_annos[0]['dimensions'], expected_dimensions)
assert os.path.exists(expected_file_path) assert os.path.exists(expected_file_path)
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import tempfile
import mmcv import mmcv
import numpy as np import numpy as np
import tempfile
import torch import torch
from mmdet3d.core import limit_period
from mmdet3d.datasets import LyftDataset from mmdet3d.datasets import LyftDataset
...@@ -11,6 +13,7 @@ def test_getitem(): ...@@ -11,6 +13,7 @@ def test_getitem():
np.random.seed(0) np.random.seed(0)
torch.manual_seed(0) torch.manual_seed(0)
root_path = './tests/data/lyft' root_path = './tests/data/lyft'
# in coordinate system refactor, this test file is modified
ann_file = './tests/data/lyft/lyft_infos.pkl' ann_file = './tests/data/lyft/lyft_infos.pkl'
class_names = ('car', 'truck', 'bus', 'emergency_vehicle', 'other_vehicle', class_names = ('car', 'truck', 'bus', 'emergency_vehicle', 'other_vehicle',
'motorcycle', 'bicycle', 'pedestrian', 'animal') 'motorcycle', 'bicycle', 'pedestrian', 'animal')
...@@ -49,9 +52,11 @@ def test_getitem(): ...@@ -49,9 +52,11 @@ def test_getitem():
pcd_horizontal_flip = data['img_metas']._data['pcd_horizontal_flip'] pcd_horizontal_flip = data['img_metas']._data['pcd_horizontal_flip']
pcd_scale_factor = data['img_metas']._data['pcd_scale_factor'] pcd_scale_factor = data['img_metas']._data['pcd_scale_factor']
pcd_rotation = data['img_metas']._data['pcd_rotation'] pcd_rotation = data['img_metas']._data['pcd_rotation']
pcd_rotation_angle = data['img_metas']._data['pcd_rotation_angle']
sample_idx = data['img_metas']._data['sample_idx'] sample_idx = data['img_metas']._data['sample_idx']
pcd_rotation_expected = np.array([[0.99869376, -0.05109515, 0.], # coord sys refactor
[0.05109515, 0.99869376, 0.], pcd_rotation_expected = np.array([[0.99869376, 0.05109515, 0.],
[-0.05109515, 0.99869376, 0.],
[0., 0., 1.]]) [0., 0., 1.]])
assert pts_filename == \ assert pts_filename == \
'tests/data/lyft/lidar/host-a017_lidar1_1236118886901125926.bin' 'tests/data/lyft/lidar/host-a017_lidar1_1236118886901125926.bin'
...@@ -82,6 +87,21 @@ def test_getitem(): ...@@ -82,6 +87,21 @@ def test_getitem():
expected_gt_labels = np.array([0, 4, 7]) expected_gt_labels = np.array([0, 4, 7])
original_classes = lyft_dataset.CLASSES original_classes = lyft_dataset.CLASSES
# manually go through pipeline
expected_points[:, :3] = (
(expected_points[:, :3] * torch.tensor([1, -1, 1]))
@ pcd_rotation_expected @ pcd_rotation_expected) * torch.tensor(
[1, -1, 1])
expected_gt_bboxes_3d[:, :3] = (
(expected_gt_bboxes_3d[:, :3] * torch.tensor([1, -1, 1]))
@ pcd_rotation_expected @ pcd_rotation_expected) * torch.tensor(
[1, -1, 1])
expected_gt_bboxes_3d[:, 3:6] = expected_gt_bboxes_3d[:, [4, 3, 5]]
expected_gt_bboxes_3d[:, 6:] = -expected_gt_bboxes_3d[:, 6:] \
- np.pi / 2 - pcd_rotation_angle * 2
expected_gt_bboxes_3d[:, 6:] = limit_period(
expected_gt_bboxes_3d[:, 6:], period=np.pi * 2)
assert torch.allclose(points, expected_points, 1e-2) assert torch.allclose(points, expected_points, 1e-2)
assert torch.allclose(gt_bboxes_3d.tensor, expected_gt_bboxes_3d, 1e-3) assert torch.allclose(gt_bboxes_3d.tensor, expected_gt_bboxes_3d, 1e-3)
assert np.all(gt_labels_3d.numpy() == expected_gt_labels) assert np.all(gt_labels_3d.numpy() == expected_gt_labels)
...@@ -110,8 +130,10 @@ def test_getitem(): ...@@ -110,8 +130,10 @@ def test_getitem():
def test_evaluate(): def test_evaluate():
root_path = './tests/data/lyft' root_path = './tests/data/lyft'
# in coordinate system refactor, this test file is modified
ann_file = './tests/data/lyft/lyft_infos_val.pkl' ann_file = './tests/data/lyft/lyft_infos_val.pkl'
lyft_dataset = LyftDataset(ann_file, None, root_path) lyft_dataset = LyftDataset(ann_file, None, root_path)
# in coordinate system refactor, this test file is modified
results = mmcv.load('./tests/data/lyft/sample_results.pkl') results = mmcv.load('./tests/data/lyft/sample_results.pkl')
ap_dict = lyft_dataset.evaluate(results, 'bbox') ap_dict = lyft_dataset.evaluate(results, 'bbox')
car_precision = ap_dict['pts_bbox_Lyft/car_AP'] car_precision = ap_dict['pts_bbox_Lyft/car_AP']
...@@ -119,9 +141,10 @@ def test_evaluate(): ...@@ -119,9 +141,10 @@ def test_evaluate():
def test_show(): def test_show():
import mmcv
from os import path as osp from os import path as osp
import mmcv
from mmdet3d.core.bbox import LiDARInstance3DBoxes from mmdet3d.core.bbox import LiDARInstance3DBoxes
tmp_dir = tempfile.TemporaryDirectory() tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name temp_dir = tmp_dir.name
...@@ -149,11 +172,11 @@ def test_show(): ...@@ -149,11 +172,11 @@ def test_show():
kitti_dataset = LyftDataset(ann_file, None, root_path) kitti_dataset = LyftDataset(ann_file, None, root_path)
boxes_3d = LiDARInstance3DBoxes( boxes_3d = LiDARInstance3DBoxes(
torch.tensor( torch.tensor(
[[46.1218, -4.6496, -0.9275, 0.5316, 1.4442, 1.7450, 1.1749], [[46.1218, -4.6496, -0.9275, 1.4442, 0.5316, 1.7450, -2.7457],
[33.3189, 0.1981, 0.3136, 0.5656, 1.2301, 1.7985, 1.5723], [33.3189, 0.1981, 0.3136, 1.2301, 0.5656, 1.7985, 3.1401],
[46.1366, -4.6404, -0.9510, 0.5162, 1.6501, 1.7540, 1.3778], [46.1366, -4.6404, -0.9510, 1.6501, 0.5162, 1.7540, -2.9486],
[33.2646, 0.2297, 0.3446, 0.5746, 1.3365, 1.7947, 1.5430], [33.2646, 0.2297, 0.3446, 1.3365, 0.5746, 1.7947, -3.1138],
[58.9079, 16.6272, -1.5829, 1.5656, 3.9313, 1.4899, 1.5505]])) [58.9079, 16.6272, -1.5829, 3.9313, 1.5656, 1.4899, -3.1213]]))
scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780]) scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780])
labels_3d = torch.tensor([0, 0, 1, 1, 2]) labels_3d = torch.tensor([0, 0, 1, 1, 2])
result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d) result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d)
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import tempfile import tempfile
import numpy as np
import torch import torch
from mmdet3d.datasets import NuScenesDataset from mmdet3d.datasets import NuScenesDataset
...@@ -65,9 +66,10 @@ def test_getitem(): ...@@ -65,9 +66,10 @@ def test_getitem():
def test_show(): def test_show():
import mmcv
from os import path as osp from os import path as osp
import mmcv
from mmdet3d.core.bbox import LiDARInstance3DBoxes from mmdet3d.core.bbox import LiDARInstance3DBoxes
tmp_dir = tempfile.TemporaryDirectory() tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name temp_dir = tmp_dir.name
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import tempfile
from os import path as osp
import mmcv import mmcv
import numpy as np import numpy as np
import pytest import pytest
import tempfile
import torch import torch
from os import path as osp
from mmdet3d.datasets import NuScenesMonoDataset from mmdet3d.datasets import NuScenesMonoDataset
......
...@@ -239,10 +239,11 @@ def test_seg_evaluate(): ...@@ -239,10 +239,11 @@ def test_seg_evaluate():
def test_seg_show(): def test_seg_show():
import mmcv
import tempfile import tempfile
from os import path as osp from os import path as osp
import mmcv
tmp_dir = tempfile.TemporaryDirectory() tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name temp_dir = tmp_dir.name
root_path = './tests/data/s3dis' root_path = './tests/data/s3dis'
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import copy import copy
import numpy as np import numpy as np
import pytest import pytest
import torch import torch
...@@ -200,10 +201,11 @@ def test_evaluate(): ...@@ -200,10 +201,11 @@ def test_evaluate():
def test_show(): def test_show():
import mmcv
import tempfile import tempfile
from os import path as osp from os import path as osp
import mmcv
from mmdet3d.core.bbox import DepthInstance3DBoxes from mmdet3d.core.bbox import DepthInstance3DBoxes
tmp_dir = tempfile.TemporaryDirectory() tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name temp_dir = tmp_dir.name
...@@ -581,10 +583,11 @@ def test_seg_evaluate(): ...@@ -581,10 +583,11 @@ def test_seg_evaluate():
def test_seg_show(): def test_seg_show():
import mmcv
import tempfile import tempfile
from os import path as osp from os import path as osp
import mmcv
tmp_dir = tempfile.TemporaryDirectory() tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name temp_dir = tmp_dir.name
root_path = './tests/data/scannet' root_path = './tests/data/scannet'
...@@ -652,9 +655,10 @@ def test_seg_show(): ...@@ -652,9 +655,10 @@ def test_seg_show():
def test_seg_format_results(): def test_seg_format_results():
import mmcv
from os import path as osp from os import path as osp
import mmcv
root_path = './tests/data/scannet' root_path = './tests/data/scannet'
ann_file = './tests/data/scannet/scannet_infos.pkl' ann_file = './tests/data/scannet/scannet_infos.pkl'
scannet_dataset = ScanNetSegDataset( scannet_dataset = ScanNetSegDataset(
......
...@@ -8,6 +8,7 @@ from mmdet3d.datasets import SUNRGBDDataset ...@@ -8,6 +8,7 @@ from mmdet3d.datasets import SUNRGBDDataset
def _generate_sunrgbd_dataset_config(): def _generate_sunrgbd_dataset_config():
root_path = './tests/data/sunrgbd' root_path = './tests/data/sunrgbd'
# in coordinate system refactor, this test file is modified
ann_file = './tests/data/sunrgbd/sunrgbd_infos.pkl' ann_file = './tests/data/sunrgbd/sunrgbd_infos.pkl'
class_names = ('bed', 'table', 'sofa', 'chair', 'toilet', 'desk', class_names = ('bed', 'table', 'sofa', 'chair', 'toilet', 'desk',
'dresser', 'night_stand', 'bookshelf', 'bathtub') 'dresser', 'night_stand', 'bookshelf', 'bathtub')
...@@ -120,6 +121,8 @@ def test_getitem(): ...@@ -120,6 +121,8 @@ def test_getitem():
[[0.8308, 4.1168, -1.2035, 2.2493, 1.8444, 1.9245, 1.6486], [[0.8308, 4.1168, -1.2035, 2.2493, 1.8444, 1.9245, 1.6486],
[2.3002, 4.8149, -1.2442, 0.5718, 0.8629, 0.9510, 1.6030], [2.3002, 4.8149, -1.2442, 0.5718, 0.8629, 0.9510, 1.6030],
[-1.1477, 1.8090, -1.1725, 0.6965, 1.5273, 2.0563, 0.0552]]) [-1.1477, 1.8090, -1.1725, 0.6965, 1.5273, 2.0563, 0.0552]])
# coord sys refactor (rotation is correct but yaw has to be reversed)
expected_gt_bboxes_3d[:, 6:] = -expected_gt_bboxes_3d[:, 6:]
expected_gt_labels = np.array([0, 7, 6]) expected_gt_labels = np.array([0, 7, 6])
original_classes = sunrgbd_dataset.CLASSES original_classes = sunrgbd_dataset.CLASSES
...@@ -207,10 +210,11 @@ def test_evaluate(): ...@@ -207,10 +210,11 @@ def test_evaluate():
def test_show(): def test_show():
import mmcv
import tempfile import tempfile
from os import path as osp from os import path as osp
import mmcv
from mmdet3d.core.bbox import DepthInstance3DBoxes from mmdet3d.core.bbox import DepthInstance3DBoxes
tmp_dir = tempfile.TemporaryDirectory() tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name temp_dir = tmp_dir.name
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import tempfile
import numpy as np import numpy as np
import pytest import pytest
import tempfile
import torch import torch
from mmdet3d.datasets import WaymoDataset from mmdet3d.datasets import WaymoDataset
...@@ -16,6 +17,7 @@ def _generate_waymo_train_dataset_config(): ...@@ -16,6 +17,7 @@ def _generate_waymo_train_dataset_config():
file_client_args = dict(backend='disk') file_client_args = dict(backend='disk')
db_sampler = dict( db_sampler = dict(
data_root=data_root, data_root=data_root,
# in coordinate system refactor, this test file is modified
info_path=data_root + 'waymo_dbinfos_train.pkl', info_path=data_root + 'waymo_dbinfos_train.pkl',
rate=1.0, rate=1.0,
prepare=dict( prepare=dict(
...@@ -114,7 +116,7 @@ def test_getitem(): ...@@ -114,7 +116,7 @@ def test_getitem():
gt_bboxes_3d = data['gt_bboxes_3d']._data gt_bboxes_3d = data['gt_bboxes_3d']._data
gt_labels_3d = data['gt_labels_3d']._data gt_labels_3d = data['gt_labels_3d']._data
expected_gt_bboxes_3d = torch.tensor( expected_gt_bboxes_3d = torch.tensor(
[[31.4750, -4.5690, 2.1857, 2.3519, 6.0931, 3.1756, -1.2895]]) [[31.8048, -0.1002, 2.1857, 6.0931, 2.3519, 3.1756, -0.1403]])
expected_gt_labels_3d = torch.tensor([0]) expected_gt_labels_3d = torch.tensor([0])
assert points.shape == (765, 5) assert points.shape == (765, 5)
assert torch.allclose( assert torch.allclose(
...@@ -132,8 +134,8 @@ def test_evaluate(): ...@@ -132,8 +134,8 @@ def test_evaluate():
pipeline, classes, modality) pipeline, classes, modality)
boxes_3d = LiDARInstance3DBoxes( boxes_3d = LiDARInstance3DBoxes(
torch.tensor([[ torch.tensor([[
6.9684e+01, 3.3335e+01, 4.1465e-02, 2.0100e+00, 4.3600e+00, 6.9684e+01, 3.3335e+01, 4.1465e-02, 4.3600e+00, 2.0100e+00,
1.4600e+00, -9.0000e-02 1.4600e+00, 9.0000e-02 - np.pi / 2
]])) ]]))
labels_3d = torch.tensor([0]) labels_3d = torch.tensor([0])
scores_3d = torch.tensor([0.5]) scores_3d = torch.tensor([0.5])
...@@ -150,8 +152,8 @@ def test_evaluate(): ...@@ -150,8 +152,8 @@ def test_evaluate():
metric = ['waymo'] metric = ['waymo']
boxes_3d = LiDARInstance3DBoxes( boxes_3d = LiDARInstance3DBoxes(
torch.tensor([[ torch.tensor([[
6.9684e+01, 3.3335e+01, 4.1465e-02, 2.0100e+00, 4.3600e+00, 6.9684e+01, 3.3335e+01, 4.1465e-02, 4.3600e+00, 2.0100e+00,
1.4600e+00, -9.0000e-02 1.4600e+00, 9.0000e-02 - np.pi / 2
]])) ]]))
labels_3d = torch.tensor([0]) labels_3d = torch.tensor([0])
scores_3d = torch.tensor([0.8]) scores_3d = torch.tensor([0.8])
...@@ -164,9 +166,10 @@ def test_evaluate(): ...@@ -164,9 +166,10 @@ def test_evaluate():
def test_show(): def test_show():
import mmcv
from os import path as osp from os import path as osp
import mmcv
from mmdet3d.core.bbox import LiDARInstance3DBoxes from mmdet3d.core.bbox import LiDARInstance3DBoxes
# Waymo shares show function with KITTI so I just copy it here # Waymo shares show function with KITTI so I just copy it here
...@@ -178,11 +181,11 @@ def test_show(): ...@@ -178,11 +181,11 @@ def test_show():
data_root, ann_file, split=split, modality=modality, pipeline=pipeline) data_root, ann_file, split=split, modality=modality, pipeline=pipeline)
boxes_3d = LiDARInstance3DBoxes( boxes_3d = LiDARInstance3DBoxes(
torch.tensor( torch.tensor(
[[46.1218, -4.6496, -0.9275, 0.5316, 1.4442, 1.7450, 1.1749], [[46.1218, -4.6496, -0.9275, 1.4442, 0.5316, 1.7450, 1.1749],
[33.3189, 0.1981, 0.3136, 0.5656, 1.2301, 1.7985, 1.5723], [33.3189, 0.1981, 0.3136, 1.2301, 0.5656, 1.7985, 1.5723],
[46.1366, -4.6404, -0.9510, 0.5162, 1.6501, 1.7540, 1.3778], [46.1366, -4.6404, -0.9510, 1.6501, 0.5162, 1.7540, 1.3778],
[33.2646, 0.2297, 0.3446, 0.5746, 1.3365, 1.7947, 1.5430], [33.2646, 0.2297, 0.3446, 1.3365, 0.5746, 1.7947, 1.5430],
[58.9079, 16.6272, -1.5829, 1.5656, 3.9313, 1.4899, 1.5505]])) [58.9079, 16.6272, -1.5829, 3.9313, 1.5656, 1.4899, 1.5505]]))
scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780]) scores_3d = torch.tensor([0.1815, 0.1663, 0.5792, 0.2194, 0.2780])
labels_3d = torch.tensor([0, 0, 1, 1, 2]) labels_3d = torch.tensor([0, 0, 1, 1, 2])
result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d) result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d)
...@@ -231,8 +234,8 @@ def test_format_results(): ...@@ -231,8 +234,8 @@ def test_format_results():
pipeline, classes, modality) pipeline, classes, modality)
boxes_3d = LiDARInstance3DBoxes( boxes_3d = LiDARInstance3DBoxes(
torch.tensor([[ torch.tensor([[
6.9684e+01, 3.3335e+01, 4.1465e-02, 2.0100e+00, 4.3600e+00, 6.9684e+01, 3.3335e+01, 4.1465e-02, 4.3600e+00, 2.0100e+00,
1.4600e+00, -9.0000e-02 1.4600e+00, 9.0000e-02 - np.pi / 2
]])) ]]))
labels_3d = torch.tensor([0]) labels_3d = torch.tensor([0])
scores_3d = torch.tensor([0.5]) scores_3d = torch.tensor([0.5])
...@@ -252,11 +255,11 @@ def test_format_results(): ...@@ -252,11 +255,11 @@ def test_format_results():
assert np.all(result_files[0]['name'] == expected_name) assert np.all(result_files[0]['name'] == expected_name)
assert np.allclose(result_files[0]['truncated'], expected_truncated) assert np.allclose(result_files[0]['truncated'], expected_truncated)
assert np.all(result_files[0]['occluded'] == expected_occluded) 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, 1e-3)
assert np.allclose(result_files[0]['bbox'], expected_bbox)
assert np.allclose(result_files[0]['dimensions'], expected_dimensions) assert np.allclose(result_files[0]['dimensions'], expected_dimensions)
assert np.allclose(result_files[0]['location'], expected_location) 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]['rotation_y'], expected_rotation_y)
assert np.allclose(result_files[0]['score'], expected_score) assert np.allclose(result_files[0]['score'], expected_score)
assert np.allclose(result_files[0]['sample_idx'], expected_sample_idx) assert np.allclose(result_files[0]['sample_idx'], expected_sample_idx)
assert np.allclose(result_files[0]['alpha'], expected_alpha)
tmp_dir.cleanup() tmp_dir.cleanup()
...@@ -8,12 +8,14 @@ from mmdet3d.core import (Box3DMode, CameraInstance3DBoxes, ...@@ -8,12 +8,14 @@ from mmdet3d.core import (Box3DMode, CameraInstance3DBoxes,
DepthInstance3DBoxes, LiDARInstance3DBoxes) DepthInstance3DBoxes, LiDARInstance3DBoxes)
from mmdet3d.core.bbox import Coord3DMode from mmdet3d.core.bbox import Coord3DMode
from mmdet3d.core.points import DepthPoints, LiDARPoints from mmdet3d.core.points import DepthPoints, LiDARPoints
from mmdet3d.datasets import (BackgroundPointsFilter, GlobalAlignment, # yapf: disable
GlobalRotScaleTrans, ObjectNameFilter, from mmdet3d.datasets import (AffineResize, BackgroundPointsFilter,
ObjectNoise, ObjectRangeFilter, ObjectSample, GlobalAlignment, GlobalRotScaleTrans,
PointSample, PointShuffle, PointsRangeFilter, ObjectNameFilter, ObjectNoise, ObjectRangeFilter,
RandomDropPointsColor, RandomFlip3D, ObjectSample, PointSample, PointShuffle,
RandomJitterPoints, VoxelBasedPointSampler) PointsRangeFilter, RandomDropPointsColor,
RandomFlip3D, RandomJitterPoints,
RandomShiftScale, VoxelBasedPointSampler)
def test_remove_points_in_boxes(): def test_remove_points_in_boxes():
...@@ -132,8 +134,12 @@ def test_object_noise(): ...@@ -132,8 +134,12 @@ def test_object_noise():
input_dict = object_noise(input_dict) input_dict = object_noise(input_dict)
points = input_dict['points'] points = input_dict['points']
gt_bboxes_3d = input_dict['gt_bboxes_3d'].tensor gt_bboxes_3d = input_dict['gt_bboxes_3d'].tensor
expected_gt_bboxes_3d = torch.tensor(
[[9.1724, -1.7559, -1.3550, 0.4800, 1.2000, 1.8900, 0.0505]]) # coord sys refactor (lidar2cam)
expected_gt_bboxes_3d = torch.tensor([[
9.1724, -1.7559, -1.3550, 1.2000, 0.4800, 1.8900,
0.0505 - float(rots) * 2 - np.pi / 2
]])
repr_str = repr(object_noise) repr_str = repr(object_noise)
expected_repr_str = 'ObjectNoise(num_try=100, ' \ expected_repr_str = 'ObjectNoise(num_try=100, ' \
'translation_std=[0.25, 0.25, 0.25], ' \ 'translation_std=[0.25, 0.25, 0.25], ' \
...@@ -522,11 +528,11 @@ def test_random_flip_3d(): ...@@ -522,11 +528,11 @@ def test_random_flip_3d():
[21.2334, -9.3607, -0.2588, 0.0000], [21.2334, -9.3607, -0.2588, 0.0000],
[21.2179, -9.4372, -0.2598, 0.0000]]) [21.2179, -9.4372, -0.2598, 0.0000]])
expected_gt_bboxes_3d = torch.tensor( expected_gt_bboxes_3d = torch.tensor(
[[38.9229, -18.4417, -1.1459, 0.7100, 1.7600, 1.8600, 5.4068], [[38.9229, -18.4417, -1.1459, 0.7100, 1.7600, 1.8600, 2.2652],
[12.7768, -0.5795, -2.2682, 0.5700, 0.9900, 1.7200, 5.6445], [12.7768, -0.5795, -2.2682, 0.5700, 0.9900, 1.7200, 2.5029],
[12.7557, -2.2996, -1.4869, 0.6100, 1.1100, 1.9000, 5.0806], [12.7557, -2.2996, -1.4869, 0.6100, 1.1100, 1.9000, 1.9390],
[10.6677, -0.8064, -1.5435, 0.7900, 0.9600, 1.7900, 2.0560], [10.6677, -0.8064, -1.5435, 0.7900, 0.9600, 1.7900, -1.0856],
[5.0903, -5.1004, -1.2694, 0.7100, 1.7000, 1.8300, 5.0552]]) [5.0903, -5.1004, -1.2694, 0.7100, 1.7000, 1.8300, 1.9136]])
repr_str = repr(random_flip_3d) repr_str = repr(random_flip_3d)
expected_repr_str = 'RandomFlip3D(sync_2d=True,' \ expected_repr_str = 'RandomFlip3D(sync_2d=True,' \
' flip_ratio_bev_vertical=1.0)' ' flip_ratio_bev_vertical=1.0)'
...@@ -751,3 +757,96 @@ def test_points_sample(): ...@@ -751,3 +757,96 @@ def test_points_sample():
select_idx = np.array([449, 444]) select_idx = np.array([449, 444])
expected_pts = points.tensor.numpy()[select_idx] expected_pts = points.tensor.numpy()[select_idx]
assert np.allclose(sampled_pts.tensor.numpy(), expected_pts) assert np.allclose(sampled_pts.tensor.numpy(), expected_pts)
def test_affine_resize():
def create_random_bboxes(num_bboxes, img_w, img_h):
bboxes_left_top = np.random.uniform(0, 0.5, size=(num_bboxes, 2))
bboxes_right_bottom = np.random.uniform(0.5, 1, size=(num_bboxes, 2))
bboxes = np.concatenate((bboxes_left_top, bboxes_right_bottom), 1)
bboxes = (bboxes * np.array([img_w, img_h, img_w, img_h])).astype(
np.float32)
return bboxes
affine_reszie = AffineResize(img_scale=(1290, 384), down_ratio=4)
# test the situation: not use Random_Scale_Shift before AffineResize
results = dict()
img = mmcv.imread('./tests/data/kitti/training/image_2/000000.png',
'color')
results['img'] = img
results['bbox_fields'] = ['gt_bboxes']
results['bbox3d_fields'] = ['gt_bboxes_3d']
h, w, _ = img.shape
gt_bboxes = create_random_bboxes(8, w, h)
gt_bboxes_3d = CameraInstance3DBoxes(torch.randn((8, 7)))
results['gt_labels'] = np.ones(gt_bboxes.shape[0], dtype=np.int64)
results['gt_labels3d'] = results['gt_labels']
results['gt_bboxes'] = gt_bboxes
results['gt_bboxes_3d'] = gt_bboxes_3d
results['depths'] = np.random.randn(gt_bboxes.shape[0])
centers2d_x = (gt_bboxes[:, [0]] + gt_bboxes[:, [2]]) / 2
centers2d_y = (gt_bboxes[:, [1]] + gt_bboxes[:, [3]]) / 2
centers2d = np.concatenate((centers2d_x, centers2d_y), axis=1)
results['centers2d'] = centers2d
results = affine_reszie(results)
assert results['gt_labels'].shape[0] == results['centers2d'].shape[0]
assert results['gt_labels3d'].shape[0] == results['centers2d'].shape[0]
assert results['gt_bboxes'].shape[0] == results['centers2d'].shape[0]
assert results['gt_bboxes_3d'].tensor.shape[0] == \
results['centers2d'].shape[0]
assert results['affine_aug'] is False
# test the situation: not use Random_Scale_Shift before AffineResize
results = dict()
img = mmcv.imread('./tests/data/kitti/training/image_2/000000.png',
'color')
results['img'] = img
results['bbox_fields'] = ['gt_bboxes']
results['bbox3d_fields'] = ['gt_bboxes_3d']
h, w, _ = img.shape
center = np.array([w / 2, h / 2], dtype=np.float32)
size = np.array([w, h], dtype=np.float32)
results['center'] = center
results['size'] = size
results['affine_aug'] = False
gt_bboxes = create_random_bboxes(8, w, h)
gt_bboxes_3d = CameraInstance3DBoxes(torch.randn((8, 7)))
results['gt_labels'] = np.ones(gt_bboxes.shape[0], dtype=np.int64)
results['gt_labels3d'] = results['gt_labels']
results['gt_bboxes'] = gt_bboxes
results['gt_bboxes_3d'] = gt_bboxes_3d
results['depths'] = np.random.randn(gt_bboxes.shape[0])
centers2d_x = (gt_bboxes[:, [0]] + gt_bboxes[:, [2]]) / 2
centers2d_y = (gt_bboxes[:, [1]] + gt_bboxes[:, [3]]) / 2
centers2d = np.concatenate((centers2d_x, centers2d_y), axis=1)
results['centers2d'] = centers2d
results = affine_reszie(results)
assert results['gt_labels'].shape[0] == results['centers2d'].shape[0]
assert results['gt_labels3d'].shape[0] == results['centers2d'].shape[0]
assert results['gt_bboxes'].shape[0] == results['centers2d'].shape[0]
assert results['gt_bboxes_3d'].tensor.shape[0] == results[
'centers2d'].shape[0]
assert 'center' in results
assert 'size' in results
assert 'affine_aug' in results
def test_random_shift_scale():
random_shift_scale = RandomShiftScale(shift_scale=(0.2, 0.4), aug_prob=0.3)
results = dict()
img = mmcv.imread('./tests/data/kitti/training/image_2/000000.png',
'color')
results['img'] = img
results = random_shift_scale(results)
assert results['center'].dtype == np.float32
assert results['size'].dtype == np.float32
assert 'affine_aug' in results
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
from os import path as osp
import mmcv import mmcv
import numpy as np import numpy as np
import torch import torch
from os import path as osp
from mmdet3d.core.bbox import DepthInstance3DBoxes from mmdet3d.core.bbox import DepthInstance3DBoxes
from mmdet3d.datasets.pipelines import Compose from mmdet3d.datasets.pipelines import Compose
...@@ -316,10 +317,24 @@ def test_sunrgbd_pipeline(): ...@@ -316,10 +317,24 @@ def test_sunrgbd_pipeline():
[0.8636, 1.3511, 0.0504, 0.0304], [0.8636, 1.3511, 0.0504, 0.0304],
[0.8690, 1.3461, 0.1265, 0.1065], [0.8690, 1.3461, 0.1265, 0.1065],
[0.8668, 1.3434, 0.1216, 0.1017]]) [0.8668, 1.3434, 0.1216, 0.1017]])
# Depth coordinate system update: only yaw changes since rotation in depth
# is counter-clockwise and yaw angle is clockwise originally
# But heading angles in sunrgbd data also reverses the sign
# and after horizontal flip the sign reverse again
rotation_angle = info['annos']['rotation_y']
expected_gt_bboxes_3d = torch.tensor( expected_gt_bboxes_3d = torch.tensor(
[[-1.2136, 4.0206, -0.2412, 2.2493, 1.8444, 1.9245, 1.3989], [[
[-2.7420, 4.5777, -0.7686, 0.5718, 0.8629, 0.9510, 1.4446], -1.2136, 4.0206, -0.2412, 2.2493, 1.8444, 1.9245,
[0.9729, 1.9087, -0.1443, 0.6965, 1.5273, 2.0563, 2.9924]]) 1.3989 + 0.047001579467984445 * 2 - 2 * rotation_angle[0]
],
[
-2.7420, 4.5777, -0.7686, 0.5718, 0.8629, 0.9510,
1.4446 + 0.047001579467984445 * 2 - 2 * rotation_angle[1]
],
[
0.9729, 1.9087, -0.1443, 0.6965, 1.5273, 2.0563,
2.9924 + 0.047001579467984445 * 2 - 2 * rotation_angle[2]
]]).float()
expected_gt_labels_3d = np.array([0, 7, 6]) expected_gt_labels_3d = np.array([0, 7, 6])
assert torch.allclose(gt_bboxes_3d.tensor, expected_gt_bboxes_3d, 1e-3) assert torch.allclose(gt_bboxes_3d.tensor, expected_gt_bboxes_3d, 1e-3)
assert np.allclose(gt_labels_3d.flatten(), expected_gt_labels_3d) assert np.allclose(gt_labels_3d.flatten(), expected_gt_labels_3d)
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
from os import path as osp
import mmcv import mmcv
import numpy as np import numpy as np
import pytest import pytest
from os import path as osp
from mmdet3d.core.bbox import DepthInstance3DBoxes from mmdet3d.core.bbox import DepthInstance3DBoxes
from mmdet3d.core.points import DepthPoints, LiDARPoints from mmdet3d.core.points import DepthPoints, LiDARPoints
......
...@@ -38,63 +38,64 @@ def test_outdoor_aug_pipeline(): ...@@ -38,63 +38,64 @@ def test_outdoor_aug_pipeline():
] ]
pipeline = Compose(train_pipeline) pipeline = Compose(train_pipeline)
# coord sys refactor: reverse sign of yaw
gt_bboxes_3d = LiDARInstance3DBoxes( gt_bboxes_3d = LiDARInstance3DBoxes(
torch.tensor([ torch.tensor([
[ [
2.16902428e+01, -4.06038128e-02, -1.61906636e+00, 2.16902428e+01, -4.06038128e-02, -1.61906636e+00,
1.65999997e+00, 3.20000005e+00, 1.61000001e+00, -1.53999996e+00 1.65999997e+00, 3.20000005e+00, 1.61000001e+00, 1.53999996e+00
], ],
[ [
7.05006886e+00, -6.57459593e+00, -1.60107934e+00, 7.05006886e+00, -6.57459593e+00, -1.60107934e+00,
2.27999997e+00, 1.27799997e+01, 3.66000009e+00, 1.54999995e+00 2.27999997e+00, 1.27799997e+01, 3.66000009e+00, -1.54999995e+00
], ],
[ [
2.24698811e+01, -6.69203758e+00, -1.50118136e+00, 2.24698811e+01, -6.69203758e+00, -1.50118136e+00,
2.31999993e+00, 1.47299995e+01, 3.64000010e+00, 1.59000003e+00 2.31999993e+00, 1.47299995e+01, 3.64000010e+00, -1.59000003e+00
], ],
[ [
3.48291969e+01, -7.09058380e+00, -1.36622977e+00, 3.48291969e+01, -7.09058380e+00, -1.36622977e+00,
2.31999993e+00, 1.00400000e+01, 3.60999990e+00, 1.61000001e+00 2.31999993e+00, 1.00400000e+01, 3.60999990e+00, -1.61000001e+00
], ],
[ [
4.62394600e+01, -7.75838804e+00, -1.32405007e+00, 4.62394600e+01, -7.75838804e+00, -1.32405007e+00,
2.33999991e+00, 1.28299999e+01, 3.63000011e+00, 1.63999999e+00 2.33999991e+00, 1.28299999e+01, 3.63000011e+00, -1.63999999e+00
], ],
[ [
2.82966995e+01, -5.55755794e-01, -1.30332506e+00, 2.82966995e+01, -5.55755794e-01, -1.30332506e+00,
1.47000003e+00, 2.23000002e+00, 1.48000002e+00, -1.57000005e+00 1.47000003e+00, 2.23000002e+00, 1.48000002e+00, 1.57000005e+00
], ],
[ [
2.66690197e+01, 2.18230209e+01, -1.73605704e+00, 2.66690197e+01, 2.18230209e+01, -1.73605704e+00,
1.55999994e+00, 3.48000002e+00, 1.39999998e+00, -1.69000006e+00 1.55999994e+00, 3.48000002e+00, 1.39999998e+00, 1.69000006e+00
], ],
[ [
3.13197803e+01, 8.16214371e+00, -1.62177873e+00, 3.13197803e+01, 8.16214371e+00, -1.62177873e+00,
1.74000001e+00, 3.76999998e+00, 1.48000002e+00, 2.78999996e+00 1.74000001e+00, 3.76999998e+00, 1.48000002e+00, -2.78999996e+00
], ],
[ [
4.34395561e+01, -1.95209332e+01, -1.20757008e+00, 4.34395561e+01, -1.95209332e+01, -1.20757008e+00,
1.69000006e+00, 4.09999990e+00, 1.40999997e+00, -1.53999996e+00 1.69000006e+00, 4.09999990e+00, 1.40999997e+00, 1.53999996e+00
], ],
[ [
3.29882965e+01, -3.79360509e+00, -1.69245458e+00, 3.29882965e+01, -3.79360509e+00, -1.69245458e+00,
1.74000001e+00, 4.09000015e+00, 1.49000001e+00, -1.52999997e+00 1.74000001e+00, 4.09000015e+00, 1.49000001e+00, 1.52999997e+00
], ],
[ [
3.85469360e+01, 8.35060215e+00, -1.31423414e+00, 3.85469360e+01, 8.35060215e+00, -1.31423414e+00,
1.59000003e+00, 4.28000021e+00, 1.45000005e+00, 1.73000002e+00 1.59000003e+00, 4.28000021e+00, 1.45000005e+00, -1.73000002e+00
], ],
[ [
2.22492104e+01, -1.13536005e+01, -1.38272512e+00, 2.22492104e+01, -1.13536005e+01, -1.38272512e+00,
1.62000000e+00, 3.55999994e+00, 1.71000004e+00, 2.48000002e+00 1.62000000e+00, 3.55999994e+00, 1.71000004e+00, -2.48000002e+00
], ],
[ [
3.36115799e+01, -1.97708054e+01, -4.92827654e-01, 3.36115799e+01, -1.97708054e+01, -4.92827654e-01,
1.64999998e+00, 3.54999995e+00, 1.79999995e+00, -1.57000005e+00 1.64999998e+00, 3.54999995e+00, 1.79999995e+00, 1.57000005e+00
], ],
[ [
9.85029602e+00, -1.51294518e+00, -1.66834795e+00, 9.85029602e+00, -1.51294518e+00, -1.66834795e+00,
1.59000003e+00, 3.17000008e+00, 1.38999999e+00, -8.39999974e-01 1.59000003e+00, 3.17000008e+00, 1.38999999e+00, 8.39999974e-01
] ]
], ],
dtype=torch.float32)) dtype=torch.float32))
...@@ -105,23 +106,59 @@ def test_outdoor_aug_pipeline(): ...@@ -105,23 +106,59 @@ def test_outdoor_aug_pipeline():
bbox3d_fields=[], bbox3d_fields=[],
img_fields=[]) img_fields=[])
origin_center = gt_bboxes_3d.tensor[:, :3].clone()
origin_angle = gt_bboxes_3d.tensor[:, 6].clone()
output = pipeline(results) output = pipeline(results)
# manually go through the pipeline
rotation_angle = output['img_metas']._data['pcd_rotation_angle']
rotation_matrix = output['img_metas']._data['pcd_rotation']
noise_angle = torch.tensor([
0.70853819, -0.19160091, -0.71116999, 0.49571753, -0.12447527,
-0.4690133, -0.34776965, -0.65692282, -0.52442831, -0.01575567,
-0.61849673, 0.6572608, 0.30312288, -0.19182971
])
noise_trans = torch.tensor([[1.7641e+00, 4.0016e-01, 4.8937e-01],
[-1.3065e+00, 1.6581e+00, -5.9082e-02],
[-1.5504e+00, 4.1732e-01, -4.7218e-01],
[-5.2158e-01, -1.1847e+00, 4.8035e-01],
[-8.9637e-01, -1.9627e+00, 7.9241e-01],
[1.3240e-02, -1.2194e-01, 1.6953e-01],
[8.1798e-01, -2.7891e-01, 7.1578e-01],
[-4.1733e-04, 3.7416e-01, 2.0478e-01],
[1.5218e-01, -3.7413e-01, -6.7257e-03],
[-1.9138e+00, -2.2855e+00, -8.0092e-01],
[1.5933e+00, 5.6872e-01, -5.7244e-02],
[-1.8523e+00, -7.1333e-01, -8.8111e-01],
[5.2678e-01, 1.0106e-01, -1.9432e-01],
[-7.2449e-01, -8.0292e-01, -1.1334e-02]])
angle = -origin_angle - noise_angle + torch.tensor(rotation_angle)
angle -= 2 * np.pi * (angle >= np.pi)
angle += 2 * np.pi * (angle < -np.pi)
scale = output['img_metas']._data['pcd_scale_factor']
expected_tensor = torch.tensor( expected_tensor = torch.tensor(
[[20.6514, -8.8250, -1.0816, 1.5893, 3.0637, 1.5414, -1.9216], [[20.6514, -8.8250, -1.0816, 1.5893, 3.0637, 1.5414],
[7.9374, 4.9457, -1.2008, 2.1829, 12.2357, 3.5041, 1.6629], [7.9374, 4.9457, -1.2008, 2.1829, 12.2357, 3.5041],
[20.8115, -2.0273, -1.8893, 2.2212, 14.1026, 3.4850, 2.6513], [20.8115, -2.0273, -1.8893, 2.2212, 14.1026, 3.4850],
[32.3850, -5.2135, -1.1321, 2.2212, 9.6124, 3.4562, 2.6498], [32.3850, -5.2135, -1.1321, 2.2212, 9.6124, 3.4562],
[43.7022, -7.8316, -0.5090, 2.2403, 12.2836, 3.4754, 2.0146], [43.7022, -7.8316, -0.5090, 2.2403, 12.2836, 3.4754],
[25.3300, -9.6670, -1.0855, 1.4074, 2.1350, 1.4170, -0.7141], [25.3300, -9.6670, -1.0855, 1.4074, 2.1350, 1.4170],
[16.5414, -29.0583, -0.9768, 1.4936, 3.3318, 1.3404, -0.7153], [16.5414, -29.0583, -0.9768, 1.4936, 3.3318, 1.3404],
[24.6548, -18.9226, -1.3567, 1.6659, 3.6094, 1.4170, 1.3970], [24.6548, -18.9226, -1.3567, 1.6659, 3.6094, 1.4170],
[45.8403, 1.8183, -1.1626, 1.6180, 3.9254, 1.3499, -0.6886], [45.8403, 1.8183, -1.1626, 1.6180, 3.9254, 1.3499],
[30.6288, -8.4497, -1.4881, 1.6659, 3.9158, 1.4265, -0.7241], [30.6288, -8.4497, -1.4881, 1.6659, 3.9158, 1.4265],
[32.3316, -22.4611, -1.3131, 1.5223, 4.0977, 1.3882, 2.4186], [32.3316, -22.4611, -1.3131, 1.5223, 4.0977, 1.3882],
[22.4492, 3.2944, -2.1674, 1.5510, 3.4084, 1.6372, 0.3928], [22.4492, 3.2944, -2.1674, 1.5510, 3.4084, 1.6372],
[37.3824, 5.0472, -0.6579, 1.5797, 3.3988, 1.7233, -1.4862], [37.3824, 5.0472, -0.6579, 1.5797, 3.3988, 1.7233],
[8.9259, -1.2578, -1.6081, 1.5223, 3.0350, 1.3308, -1.7212]]) [8.9259, -1.2578, -1.6081, 1.5223, 3.0350, 1.3308]])
expected_tensor[:, :3] = ((
(origin_center + noise_trans) * torch.tensor([1, -1, 1]))
@ rotation_matrix) * scale
expected_tensor = torch.cat([expected_tensor, angle.unsqueeze(-1)], dim=-1)
assert torch.allclose( assert torch.allclose(
output['gt_bboxes_3d']._data.tensor, expected_tensor, atol=1e-3) output['gt_bboxes_3d']._data.tensor, expected_tensor, atol=1e-3)
...@@ -208,6 +245,11 @@ def test_outdoor_velocity_aug_pipeline(): ...@@ -208,6 +245,11 @@ def test_outdoor_velocity_aug_pipeline():
bbox3d_fields=[], bbox3d_fields=[],
img_fields=[]) img_fields=[])
origin_center = gt_bboxes_3d.tensor[:, :3].clone()
origin_angle = gt_bboxes_3d.tensor[:, 6].clone(
) # TODO: ObjectNoise modifies tensor!!
origin_velo = gt_bboxes_3d.tensor[:, 7:9].clone()
output = pipeline(results) output = pipeline(results)
expected_tensor = torch.tensor( expected_tensor = torch.tensor(
...@@ -247,5 +289,21 @@ def test_outdoor_velocity_aug_pipeline(): ...@@ -247,5 +289,21 @@ def test_outdoor_velocity_aug_pipeline():
-4.4522e+00, -2.9166e+01, -7.8938e-01, 2.2841e+00, 3.8348e+00, -4.4522e+00, -2.9166e+01, -7.8938e-01, 2.2841e+00, 3.8348e+00,
1.5925e+00, 1.4721e+00, -7.8371e-03, -8.1931e-03 1.5925e+00, 1.4721e+00, -7.8371e-03, -8.1931e-03
]]) ]])
# coord sys refactor (manually go through pipeline)
rotation_angle = output['img_metas']._data['pcd_rotation_angle']
rotation_matrix = output['img_metas']._data['pcd_rotation']
expected_tensor[:, :3] = ((origin_center @ rotation_matrix) *
output['img_metas']._data['pcd_scale_factor'] *
torch.tensor([1, -1, 1]))[[
0, 1, 2, 3, 4, 5, 6, 7, 9
]]
angle = -origin_angle - rotation_angle
angle -= 2 * np.pi * (angle >= np.pi)
angle += 2 * np.pi * (angle < -np.pi)
expected_tensor[:, 6:7] = angle.unsqueeze(-1)[[0, 1, 2, 3, 4, 5, 6, 7, 9]]
expected_tensor[:,
7:9] = ((origin_velo @ rotation_matrix[:2, :2]) *
output['img_metas']._data['pcd_scale_factor'] *
torch.tensor([1, -1]))[[0, 1, 2, 3, 4, 5, 6, 7, 9]]
assert torch.allclose( assert torch.allclose(
output['gt_bboxes_3d']._data.tensor, expected_tensor, atol=1e-3) output['gt_bboxes_3d']._data.tensor, expected_tensor, atol=1e-3)
...@@ -83,31 +83,49 @@ def test_do_eval(): ...@@ -83,31 +83,49 @@ def test_do_eval():
[[0.5, 0.5, 0.7], [0.25, 0.25, 0.5], [[0.5, 0.5, 0.7], [0.25, 0.25, 0.5],
[0.25, 0.25, 0.5]]]) [0.25, 0.25, 0.5]]])
eval_types = ['bbox', 'bev', '3d', 'aos'] eval_types = ['bbox', 'bev', '3d', 'aos']
mAP_bbox, mAP_bev, mAP_3d, mAP_aos = do_eval([gt_anno], [dt_anno], mAP11_bbox, mAP11_bev, mAP11_3d, mAP11_aos, mAP40_bbox,\
mAP40_bev, mAP40_3d, mAP40_aos = do_eval([gt_anno], [dt_anno],
current_classes, min_overlaps, current_classes, min_overlaps,
eval_types) eval_types)
expected_mAP_bbox = np.array([[[0., 0.], [9.09090909, 9.09090909], expected_mAP11_bbox = np.array([[[0., 0.], [9.09090909, 9.09090909],
[9.09090909, 9.09090909]], [9.09090909, 9.09090909]],
[[0., 0.], [9.09090909, 9.09090909], [[0., 0.], [9.09090909, 9.09090909],
[9.09090909, 9.09090909]], [9.09090909, 9.09090909]],
[[0., 0.], [9.09090909, 9.09090909], [[0., 0.], [9.09090909, 9.09090909],
[9.09090909, 9.09090909]]]) [9.09090909, 9.09090909]]])
expected_mAP_bev = np.array([[[0., 0.], [0., 0.], [0., 0.]], expected_mAP40_bbox = np.array([[[0., 0.], [0., 0.], [0., 0.]],
[[0., 0.], [0., 0.], [0., 0.]], [[0., 0.], [0., 0.], [0., 0.]],
[[0., 0.], [0., 0.], [0., 0.]]]) [[0., 0.], [2.5, 2.5], [2.5, 2.5]]])
expected_mAP_3d = np.array([[[0., 0.], [0., 0.], [0., 0.]], expected_mAP11_bev = np.array([[[0., 0.], [0., 0.], [0., 0.]],
[[0., 0.], [0., 0.], [0., 0.]], [[0., 0.], [0., 0.], [0., 0.]],
[[0., 0.], [0., 0.], [0., 0.]]]) [[0., 0.], [0., 0.], [0., 0.]]])
expected_mAP_aos = np.array([[[0., 0.], [0.55020816, 0.55020816], expected_mAP40_bev = np.array([[[0., 0.], [0., 0.], [0., 0.]],
[0.55020816, 0.55020816]], [[0., 0.], [0., 0.], [0., 0.]],
[[0., 0.], [8.36633862, 8.36633862], [[0., 0.], [0., 0.], [0., 0.]]])
[8.36633862, 8.36633862]], expected_mAP11_3d = np.array([[[0., 0.], [0., 0.], [0., 0.]],
[[0., 0.], [8.63476893, 8.63476893], [[0., 0.], [0., 0.], [0., 0.]],
[8.63476893, 8.63476893]]]) [[0., 0.], [0., 0.], [0., 0.]]])
assert np.allclose(mAP_bbox, expected_mAP_bbox) expected_mAP40_3d = np.array([[[0., 0.], [0., 0.], [0., 0.]],
assert np.allclose(mAP_bev, expected_mAP_bev) [[0., 0.], [0., 0.], [0., 0.]],
assert np.allclose(mAP_3d, expected_mAP_3d) [[0., 0.], [0., 0.], [0., 0.]]])
assert np.allclose(mAP_aos, expected_mAP_aos) expected_mAP11_aos = np.array([[[0., 0.], [0.55020816, 0.55020816],
[0.55020816, 0.55020816]],
[[0., 0.], [8.36633862, 8.36633862],
[8.36633862, 8.36633862]],
[[0., 0.], [8.63476893, 8.63476893],
[8.63476893, 8.63476893]]])
expected_mAP40_aos = np.array([[[0., 0.], [0., 0.], [0., 0.]],
[[0., 0.], [0., 0.], [0., 0.]],
[[0., 0.], [1.58140643, 1.58140643],
[1.58140643, 1.58140643]]])
assert np.allclose(mAP11_bbox, expected_mAP11_bbox)
assert np.allclose(mAP11_bev, expected_mAP11_bev)
assert np.allclose(mAP11_3d, expected_mAP11_3d)
assert np.allclose(mAP11_aos, expected_mAP11_aos)
assert np.allclose(mAP40_bbox, expected_mAP40_bbox)
assert np.allclose(mAP40_bev, expected_mAP40_bev)
assert np.allclose(mAP40_3d, expected_mAP40_3d)
assert np.allclose(mAP40_aos, expected_mAP40_aos)
def test_kitti_eval(): def test_kitti_eval():
...@@ -183,8 +201,14 @@ def test_kitti_eval(): ...@@ -183,8 +201,14 @@ def test_kitti_eval():
current_classes = [1, 2, 0] current_classes = [1, 2, 0]
result, ret_dict = kitti_eval([gt_anno], [dt_anno], current_classes) result, ret_dict = kitti_eval([gt_anno], [dt_anno], current_classes)
assert np.isclose(ret_dict['KITTI/Overall_2D_moderate'], 9.090909090909092) assert np.isclose(ret_dict['KITTI/Overall_2D_AP11_moderate'],
assert np.isclose(ret_dict['KITTI/Overall_2D_hard'], 9.090909090909092) 9.090909090909092)
assert np.isclose(ret_dict['KITTI/Overall_2D_AP11_hard'],
9.090909090909092)
assert np.isclose(ret_dict['KITTI/Overall_2D_AP40_moderate'],
0.8333333333333334)
assert np.isclose(ret_dict['KITTI/Overall_2D_AP40_hard'],
0.8333333333333334)
def test_eval_class(): def test_eval_class():
......
...@@ -3,6 +3,8 @@ import pytest ...@@ -3,6 +3,8 @@ import pytest
import torch import torch
from torch import nn as nn from torch import nn as nn
from mmdet.models import build_loss
def test_chamfer_disrance(): def test_chamfer_disrance():
from mmdet3d.models.losses import ChamferDistance, chamfer_distance from mmdet3d.models.losses import ChamferDistance, chamfer_distance
...@@ -93,7 +95,7 @@ def test_paconv_regularization_loss(): ...@@ -93,7 +95,7 @@ def test_paconv_regularization_loss():
set_random_seed(0, True) set_random_seed(0, True)
model = ToyModel() model = ToyModel()
# reduction shoule be in ['none', 'mean', 'sum'] # reduction should be in ['none', 'mean', 'sum']
with pytest.raises(AssertionError): with pytest.raises(AssertionError):
paconv_corr_loss = PAConvRegularizationLoss(reduction='l2') paconv_corr_loss = PAConvRegularizationLoss(reduction='l2')
...@@ -109,3 +111,64 @@ def test_paconv_regularization_loss(): ...@@ -109,3 +111,64 @@ def test_paconv_regularization_loss():
model.modules(), reduction_override='none') model.modules(), reduction_override='none')
assert none_corr_loss.shape[0] == 3 assert none_corr_loss.shape[0] == 3
assert torch.allclose(none_corr_loss.mean(), mean_corr_loss) assert torch.allclose(none_corr_loss.mean(), mean_corr_loss)
def test_uncertain_smooth_l1_loss():
from mmdet3d.models.losses import UncertainL1Loss, UncertainSmoothL1Loss
# reduction should be in ['none', 'mean', 'sum']
with pytest.raises(AssertionError):
uncertain_l1_loss = UncertainL1Loss(reduction='l2')
with pytest.raises(AssertionError):
uncertain_smooth_l1_loss = UncertainSmoothL1Loss(reduction='l2')
pred = torch.tensor([1.5783, 0.5972, 1.4821, 0.9488])
target = torch.tensor([1.0813, -0.3466, -1.1404, -0.9665])
sigma = torch.tensor([-1.0053, 0.4710, -1.7784, -0.8603])
# test uncertain l1 loss
uncertain_l1_loss_cfg = dict(
type='UncertainL1Loss', alpha=1.0, reduction='mean', loss_weight=1.0)
uncertain_l1_loss = build_loss(uncertain_l1_loss_cfg)
mean_l1_loss = uncertain_l1_loss(pred, target, sigma)
expected_l1_loss = torch.tensor(4.7069)
assert torch.allclose(mean_l1_loss, expected_l1_loss, atol=1e-4)
# test uncertain smooth l1 loss
uncertain_smooth_l1_loss_cfg = dict(
type='UncertainSmoothL1Loss',
alpha=1.0,
beta=0.5,
reduction='mean',
loss_weight=1.0)
uncertain_smooth_l1_loss = build_loss(uncertain_smooth_l1_loss_cfg)
mean_smooth_l1_loss = uncertain_smooth_l1_loss(pred, target, sigma)
expected_smooth_l1_loss = torch.tensor(3.9795)
assert torch.allclose(
mean_smooth_l1_loss, expected_smooth_l1_loss, atol=1e-4)
def test_multibin_loss():
from mmdet3d.models.losses import MultiBinLoss
# reduction should be in ['none', 'mean', 'sum']
with pytest.raises(AssertionError):
multibin_loss = MultiBinLoss(reduction='l2')
pred = torch.tensor([[
0.81, 0.32, 0.78, 0.52, 0.24, 0.12, 0.32, 0.11, 1.20, 1.30, 0.20, 0.11,
0.12, 0.11, 0.23, 0.31
],
[
0.02, 0.19, 0.78, 0.22, 0.31, 0.12, 0.22, 0.11,
1.20, 1.30, 0.45, 0.51, 0.12, 0.11, 0.13, 0.61
]])
target = torch.tensor([[1, 1, 0, 0, 2.14, 3.12, 0.68, -2.15],
[1, 1, 0, 0, 3.12, 3.12, 2.34, 1.23]])
multibin_loss_cfg = dict(
type='MultiBinLoss', reduction='none', loss_weight=1.0)
multibin_loss = build_loss(multibin_loss_cfg)
output_multibin_loss = multibin_loss(pred, target, num_dir_bins=4)
expected_multibin_loss = torch.tensor(2.1120)
assert torch.allclose(
output_multibin_loss, expected_multibin_loss, atol=1e-4)
...@@ -297,3 +297,59 @@ def test_pointnet2_sa_msg(): ...@@ -297,3 +297,59 @@ def test_pointnet2_sa_msg():
assert sa_indices[2].shape == torch.Size([1, 256]) assert sa_indices[2].shape == torch.Size([1, 256])
assert sa_indices[3].shape == torch.Size([1, 64]) assert sa_indices[3].shape == torch.Size([1, 64])
assert sa_indices[4].shape == torch.Size([1, 16]) assert sa_indices[4].shape == torch.Size([1, 16])
def test_dgcnn_gf():
if not torch.cuda.is_available():
pytest.skip()
# DGCNNGF used in segmentation
cfg = dict(
type='DGCNNBackbone',
in_channels=6,
num_samples=(20, 20, 20),
knn_modes=['D-KNN', 'F-KNN', 'F-KNN'],
radius=(None, None, None),
gf_channels=((64, 64), (64, 64), (64, )),
fa_channels=(1024, ),
act_cfg=dict(type='ReLU'))
self = build_backbone(cfg)
self.cuda()
xyz = np.fromfile('tests/data/sunrgbd/points/000001.bin', dtype=np.float32)
xyz = torch.from_numpy(xyz).view(1, -1, 6).cuda() # (B, N, 6)
# test forward
ret_dict = self(xyz)
gf_points = ret_dict['gf_points']
fa_points = ret_dict['fa_points']
assert len(gf_points) == 4
assert gf_points[0].shape == torch.Size([1, 100, 6])
assert gf_points[1].shape == torch.Size([1, 100, 64])
assert gf_points[2].shape == torch.Size([1, 100, 64])
assert gf_points[3].shape == torch.Size([1, 100, 64])
assert fa_points.shape == torch.Size([1, 100, 1216])
def test_dla_net():
# test DLANet used in SMOKE
# test list config
cfg = dict(
type='DLANet',
depth=34,
in_channels=3,
norm_cfg=dict(type='GN', num_groups=32))
img = torch.randn((4, 3, 32, 32))
self = build_backbone(cfg)
self.init_weights()
results = self(img)
assert len(results) == 6
assert results[0].shape == torch.Size([4, 16, 32, 32])
assert results[1].shape == torch.Size([4, 32, 16, 16])
assert results[2].shape == torch.Size([4, 64, 8, 8])
assert results[3].shape == torch.Size([4, 128, 4, 4])
assert results[4].shape == torch.Size([4, 256, 2, 2])
assert results[5].shape == torch.Size([4, 512, 1, 1])
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import pytest
import torch
def test_dgcnn_gf_module():
if not torch.cuda.is_available():
pytest.skip()
from mmdet3d.ops import DGCNNGFModule
self = DGCNNGFModule(
mlp_channels=[18, 64, 64],
num_sample=20,
knn_mod='D-KNN',
radius=None,
norm_cfg=dict(type='BN2d'),
act_cfg=dict(type='ReLU'),
pool_mod='max').cuda()
assert self.mlps[0].layer0.conv.in_channels == 18
assert self.mlps[0].layer0.conv.out_channels == 64
xyz = np.fromfile('tests/data/sunrgbd/points/000001.bin', np.float32)
# (B, N, C)
xyz = torch.from_numpy(xyz).view(1, -1, 3).cuda()
points = xyz.repeat([1, 1, 3])
# test forward
new_points = self(points)
assert new_points.shape == torch.Size([1, 200, 64])
# test F-KNN mod
self = DGCNNGFModule(
mlp_channels=[6, 64, 64],
num_sample=20,
knn_mod='F-KNN',
radius=None,
norm_cfg=dict(type='BN2d'),
act_cfg=dict(type='ReLU'),
pool_mod='max').cuda()
# test forward
new_points = self(xyz)
assert new_points.shape == torch.Size([1, 200, 64])
# test ball query
self = DGCNNGFModule(
mlp_channels=[6, 64, 64],
num_sample=20,
knn_mod='F-KNN',
radius=0.2,
norm_cfg=dict(type='BN2d'),
act_cfg=dict(type='ReLU'),
pool_mod='max').cuda()
def test_dgcnn_fa_module():
if not torch.cuda.is_available():
pytest.skip()
from mmdet3d.ops import DGCNNFAModule
self = DGCNNFAModule(mlp_channels=[24, 16]).cuda()
assert self.mlps.layer0.conv.in_channels == 24
assert self.mlps.layer0.conv.out_channels == 16
points = [torch.rand(1, 200, 12).float().cuda() for _ in range(3)]
fa_points = self(points)
assert fa_points.shape == torch.Size([1, 200, 40])
def test_dgcnn_fp_module():
if not torch.cuda.is_available():
pytest.skip()
from mmdet3d.ops import DGCNNFPModule
self = DGCNNFPModule(mlp_channels=[24, 16]).cuda()
assert self.mlps.layer0.conv.in_channels == 24
assert self.mlps.layer0.conv.out_channels == 16
xyz = np.fromfile('tests/data/sunrgbd/points/000001.bin',
np.float32).reshape((-1, 6))
# (B, N, 3)
xyz = torch.from_numpy(xyz).view(1, -1, 3).cuda()
points = xyz.repeat([1, 1, 8]).cuda()
fp_points = self(points)
assert fp_points.shape == torch.Size([1, 200, 16])
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment