Commit c9b69f5a authored by ZwwWayne's avatar ZwwWayne Committed by ChaimZhu
Browse files

Clean unit tests

parent a34823dc
......@@ -3,9 +3,7 @@ from unittest import TestCase
import numpy as np
import pytest
import torch
# TODO: will use real PixelData once it is added in mmengine
from mmengine.data import BaseDataElement as PixelData
from mmengine.data import InstanceData
from mmengine.data import InstanceData, PixelData
from mmdet3d.core import Det3DDataSample
......
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import torch
from mmdet3d.datasets.builder import build_dataset
def test_getitem():
np.random.seed(1)
torch.manual_seed(1)
point_cloud_range = [-50, -50, -5, 50, 50, 3]
file_client_args = dict(backend='disk')
class_names = [
'car', 'truck', 'trailer', 'bus', 'construction_vehicle', 'bicycle',
'motorcycle', 'pedestrian', 'traffic_cone', 'barrier'
]
pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=5,
use_dim=5,
file_client_args=file_client_args),
dict(
type='LoadPointsFromMultiSweeps',
sweeps_num=9,
use_dim=[0, 1, 2, 3, 4],
file_client_args=file_client_args,
pad_empty_sweeps=True,
remove_close=True,
test_mode=True),
dict(type='LoadAnnotations3D', with_bbox_3d=True, with_label_3d=True),
# dict(type='ObjectSample', db_sampler=db_sampler),
dict(
type='GlobalRotScaleTrans',
rot_range=[-0.3925, 0.3925],
scale_ratio_range=[0.95, 1.05],
translation_std=[0, 0, 0]),
dict(type='RandomFlip3D', flip_ratio_bev_horizontal=0.5),
dict(type='PointsRangeFilter', point_cloud_range=point_cloud_range),
dict(type='ObjectRangeFilter', point_cloud_range=point_cloud_range),
dict(type='ObjectNameFilter', classes=class_names),
dict(type='PointShuffle'),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D', keys=['points', 'gt_bboxes_3d', 'gt_labels_3d'])
]
input_modality = dict(
use_lidar=True,
use_camera=False,
use_radar=False,
use_map=False,
use_external=False)
dataset_cfg = dict(
type='CBGSDataset',
dataset=dict(
type='NuScenesDataset',
data_root='tests/data/nuscenes',
ann_file='tests/data/nuscenes/nus_info.pkl',
pipeline=pipeline,
classes=class_names,
modality=input_modality,
test_mode=False,
use_valid_flag=True,
# we use box_type_3d='LiDAR' in kitti and nuscenes dataset
# and box_type_3d='Depth' in sunrgbd and scannet dataset.
box_type_3d='LiDAR'))
nus_dataset = build_dataset(dataset_cfg)
assert len(nus_dataset) == 20
data = nus_dataset[0]
assert data['img_metas'].data['flip'] is True
assert data['img_metas'].data['pcd_horizontal_flip'] is True
assert data['points']._data.shape == (537, 5)
data = nus_dataset[2]
assert data['img_metas'].data['flip'] is False
assert data['img_metas'].data['pcd_horizontal_flip'] is False
assert data['points']._data.shape == (901, 5)
# Copyright (c) OpenMMLab. All rights reserved.
import math
import os
import tempfile
import numpy as np
import pytest
import torch
from mmdet3d.core.bbox import LiDARInstance3DBoxes, limit_period
from mmdet3d.datasets import KittiDataset
def _generate_kitti_dataset_config():
data_root = 'tests/data/kitti'
ann_file = 'tests/data/kitti/kitti_infos_train.pkl'
classes = ['Pedestrian', 'Cyclist', 'Car']
pts_prefix = 'velodyne_reduced'
pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=4,
use_dim=4,
file_client_args=dict(backend='disk')),
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.0, 1.0],
translation_std=[0, 0, 0]),
dict(type='RandomFlip3D'),
dict(
type='PointsRangeFilter',
point_cloud_range=[0, -40, -3, 70.4, 40, 1]),
dict(
type='DefaultFormatBundle3D',
class_names=classes,
with_label=False),
dict(type='Collect3D', keys=['points'])
])
]
modality = dict(use_lidar=True, use_camera=False)
split = 'training'
return data_root, ann_file, classes, pts_prefix, pipeline, modality, split
def _generate_kitti_multi_modality_dataset_config():
data_root = 'tests/data/kitti'
ann_file = 'tests/data/kitti/kitti_infos_train.pkl'
classes = ['Pedestrian', 'Cyclist', 'Car']
pts_prefix = 'velodyne_reduced'
img_norm_cfg = dict(
mean=[103.530, 116.280, 123.675], std=[1.0, 1.0, 1.0], to_rgb=False)
pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=4,
use_dim=4,
file_client_args=dict(backend='disk')),
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug3D',
img_scale=(1333, 800),
pts_scale_ratio=1,
flip=False,
transforms=[
dict(type='Resize', multiscale_mode='value', keep_ratio=True),
dict(
type='GlobalRotScaleTrans',
rot_range=[0, 0],
scale_ratio_range=[1., 1.],
translation_std=[0, 0, 0]),
dict(type='RandomFlip3D'),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(
type='PointsRangeFilter',
point_cloud_range=[0, -40, -3, 70.4, 40, 1]),
dict(
type='DefaultFormatBundle3D',
class_names=classes,
with_label=False),
dict(type='Collect3D', keys=['points', 'img'])
])
]
modality = dict(use_lidar=True, use_camera=True)
split = 'training'
return data_root, ann_file, classes, pts_prefix, pipeline, modality, split
def test_getitem():
np.random.seed(0)
data_root, ann_file, classes, pts_prefix, \
_, modality, split = _generate_kitti_dataset_config()
pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=4,
use_dim=4,
file_client_args=dict(backend='disk')),
dict(
type='LoadAnnotations3D',
with_bbox_3d=True,
with_label_3d=True,
file_client_args=dict(backend='disk')),
dict(
type='ObjectSample',
db_sampler=dict(
data_root='tests/data/kitti/',
# in coordinate system refactor, this test file is modified
info_path='tests/data/kitti/kitti_dbinfos_train.pkl',
rate=1.0,
prepare=dict(
filter_by_difficulty=[-1],
filter_by_min_points=dict(Pedestrian=10)),
classes=['Pedestrian', 'Cyclist', 'Car'],
sample_groups=dict(Pedestrian=6))),
dict(
type='ObjectNoise',
num_try=100,
translation_std=[1.0, 1.0, 0.5],
global_rot_range=[0.0, 0.0],
rot_range=[-0.78539816, 0.78539816]),
dict(type='RandomFlip3D', flip_ratio_bev_horizontal=0.5),
dict(
type='GlobalRotScaleTrans',
rot_range=[-0.78539816, 0.78539816],
scale_ratio_range=[0.95, 1.05]),
dict(
type='PointsRangeFilter',
point_cloud_range=[0, -40, -3, 70.4, 40, 1]),
dict(
type='ObjectRangeFilter',
point_cloud_range=[0, -40, -3, 70.4, 40, 1]),
dict(type='PointShuffle'),
dict(
type='DefaultFormatBundle3D',
class_names=['Pedestrian', 'Cyclist', 'Car']),
dict(
type='Collect3D', keys=['points', 'gt_bboxes_3d', 'gt_labels_3d'])
]
kitti_dataset = KittiDataset(data_root, ann_file, split, pts_prefix,
pipeline, classes, modality)
data = kitti_dataset[0]
points = data['points']._data
gt_bboxes_3d = data['gt_bboxes_3d']._data
gt_labels_3d = data['gt_labels_3d']._data
expected_gt_bboxes_3d = torch.tensor(
[[9.5081, -5.2269, -1.1370, 1.2288, 0.4915, 1.9353, 1.9988]])
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 torch.allclose(
gt_bboxes_3d.tensor, expected_gt_bboxes_3d, atol=1e-4)
assert torch.all(gt_labels_3d == expected_gt_labels_3d)
# test multi-modality KITTI dataset
np.random.seed(0)
point_cloud_range = [0, -40, -3, 70.4, 40, 1]
img_norm_cfg = dict(
mean=[103.530, 116.280, 123.675], std=[1.0, 1.0, 1.0], to_rgb=False)
multi_modality_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=4,
use_dim=4),
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations3D', with_bbox_3d=True, with_label_3d=True),
dict(
type='Resize',
img_scale=[(640, 192), (2560, 768)],
multiscale_mode='range',
keep_ratio=True),
dict(
type='GlobalRotScaleTrans',
rot_range=[-0.78539816, 0.78539816],
scale_ratio_range=[0.95, 1.05],
translation_std=[0.2, 0.2, 0.2]),
dict(type='RandomFlip3D', flip_ratio_bev_horizontal=0.5),
dict(type='PointsRangeFilter', point_cloud_range=point_cloud_range),
dict(type='ObjectRangeFilter', point_cloud_range=point_cloud_range),
dict(type='PointShuffle'),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle3D', class_names=classes),
dict(
type='Collect3D',
keys=['points', 'img', 'gt_bboxes_3d', 'gt_labels_3d']),
]
modality = dict(use_lidar=True, use_camera=True)
kitti_dataset = KittiDataset(data_root, ann_file, split, pts_prefix,
multi_modality_pipeline, classes, modality)
data = kitti_dataset[0]
img = data['img']._data
lidar2img = data['img_metas']._data['lidar2img']
expected_lidar2img = np.array(
[[6.02943726e+02, -7.07913330e+02, -1.22748432e+01, -1.70942719e+02],
[1.76777252e+02, 8.80879879e+00, -7.07936157e+02, -1.02568634e+02],
[9.99984801e-01, -1.52826728e-03, -5.29071223e-03, -3.27567995e-01],
[0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]])
assert img.shape[:] == (3, 416, 1344)
assert np.allclose(lidar2img, expected_lidar2img)
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()
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])
metric = ['mAP']
result = dict(boxes_3d=boxes_3d, labels_3d=labels_3d, scores_3d=scores_3d)
ap_dict = kitti_dataset.evaluate([result], metric)
assert np.isclose(ap_dict['KITTI/Overall_3D_AP11_easy'],
3.0303030303030307)
assert np.isclose(ap_dict['KITTI/Overall_3D_AP11_moderate'],
3.0303030303030307)
assert np.isclose(ap_dict['KITTI/Overall_3D_AP11_hard'],
3.0303030303030307)
def test_show():
from os import path as osp
import mmcv
from mmdet3d.core.bbox import LiDARInstance3DBoxes
tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name
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, show=False)
pts_file_path = osp.join(temp_dir, '000000', '000000_points.obj')
gt_file_path = osp.join(temp_dir, '000000', '000000_gt.obj')
pred_file_path = osp.join(temp_dir, '000000', '000000_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
eval_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=4,
use_dim=4),
dict(
type='DefaultFormatBundle3D',
class_names=classes,
with_label=False),
dict(type='Collect3D', keys=['points'])
]
tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name
kitti_dataset.show(results, temp_dir, show=False, pipeline=eval_pipeline)
pts_file_path = osp.join(temp_dir, '000000', '000000_points.obj')
gt_file_path = osp.join(temp_dir, '000000', '000000_gt.obj')
pred_file_path = osp.join(temp_dir, '000000', '000000_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 multi-modality show
tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name
_, _, _, _, multi_modality_pipeline, modality, _ = \
_generate_kitti_multi_modality_dataset_config()
kitti_dataset = KittiDataset(data_root, ann_file, split, pts_prefix,
multi_modality_pipeline, classes, modality)
kitti_dataset.show(results, temp_dir, show=False)
pts_file_path = osp.join(temp_dir, '000000', '000000_points.obj')
gt_file_path = osp.join(temp_dir, '000000', '000000_gt.obj')
pred_file_path = osp.join(temp_dir, '000000', '000000_pred.obj')
img_file_path = osp.join(temp_dir, '000000', '000000_img.png')
img_pred_path = osp.join(temp_dir, '000000', '000000_pred.png')
img_gt_file = osp.join(temp_dir, '000000', '000000_gt.png')
mmcv.check_file_exist(pts_file_path)
mmcv.check_file_exist(gt_file_path)
mmcv.check_file_exist(pred_file_path)
mmcv.check_file_exist(img_file_path)
mmcv.check_file_exist(img_pred_path)
mmcv.check_file_exist(img_gt_file)
tmp_dir.cleanup()
# test multi-modality show with pipeline
eval_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=4,
use_dim=4),
dict(type='LoadImageFromFile'),
dict(
type='DefaultFormatBundle3D',
class_names=classes,
with_label=False),
dict(type='Collect3D', keys=['points', 'img'])
]
tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name
kitti_dataset.show(results, temp_dir, show=False, pipeline=eval_pipeline)
pts_file_path = osp.join(temp_dir, '000000', '000000_points.obj')
gt_file_path = osp.join(temp_dir, '000000', '000000_gt.obj')
pred_file_path = osp.join(temp_dir, '000000', '000000_pred.obj')
img_file_path = osp.join(temp_dir, '000000', '000000_img.png')
img_pred_path = osp.join(temp_dir, '000000', '000000_pred.png')
img_gt_file = osp.join(temp_dir, '000000', '000000_gt.png')
mmcv.check_file_exist(pts_file_path)
mmcv.check_file_exist(gt_file_path)
mmcv.check_file_exist(pred_file_path)
mmcv.check_file_exist(img_file_path)
mmcv.check_file_exist(img_pred_path)
mmcv.check_file_exist(img_gt_file)
tmp_dir.cleanup()
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)
# coord system refactor
boxes_3d = LiDARInstance3DBoxes(
torch.tensor(
[[8.7314, -1.8559, -1.5997, 1.2000, 0.4800, 1.8900, -1.5808]]))
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])
# coord sys refactor
expected_alpha = np.array(-3.3410306 + np.pi)
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([0.0100])
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, 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]['location'], expected_location)
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]['sample_idx'], expected_sample_idx)
tmp_dir.cleanup()
def test_bbox2result_kitti():
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, 1.2000, 0.4800, 1.8900, -1.5808]]))
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]
tmp_dir = tempfile.TemporaryDirectory()
temp_kitti_result_dir = tmp_dir.name
det_annos = kitti_dataset.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])
# coord system refactor (reverse sign)
expected_rotation_y = 0.0100
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, 1e-3)
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)
tmp_dir.cleanup()
tmp_dir = tempfile.TemporaryDirectory()
temp_kitti_result_dir = tmp_dir.name
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 = kitti_dataset.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)
tmp_dir.cleanup()
def test_bbox2result_kitti2d():
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)
bboxes = np.array([[[46.1218, -4.6496, -0.9275, 0.5316, 0.5],
[33.3189, 0.1981, 0.3136, 0.5656, 0.5]],
[[46.1366, -4.6404, -0.9510, 0.5162, 0.5],
[33.2646, 0.2297, 0.3446, 0.5746, 0.5]]])
det_annos = kitti_dataset.bbox2result_kitti2d([bboxes], classes)
expected_name = np.array(
['Pedestrian', 'Pedestrian', 'Cyclist', 'Cyclist'])
expected_bbox = np.array([[46.1218, -4.6496, -0.9275, 0.5316],
[33.3189, 0.1981, 0.3136, 0.5656],
[46.1366, -4.6404, -0.951, 0.5162],
[33.2646, 0.2297, 0.3446, 0.5746]])
expected_score = np.array([0.5, 0.5, 0.5, 0.5])
assert np.all(det_annos[0]['name'] == expected_name)
assert np.allclose(det_annos[0]['bbox'], expected_bbox)
assert np.allclose(det_annos[0]['score'], expected_score)
# Copyright (c) OpenMMLab. All rights reserved.
import mmcv
import numpy as np
import pytest
import torch
from mmdet3d.datasets import KittiMonoDataset
def test_getitem():
np.random.seed(0)
class_names = ['Pedestrian', 'Cyclist', 'Car']
img_norm_cfg = dict(
mean=[103.530, 116.280, 123.675], std=[1.0, 1.0, 1.0], to_rgb=False)
pipeline = [
dict(type='LoadImageFromFileMono3D'),
dict(
type='LoadAnnotations3D',
with_bbox=True,
with_label=True,
with_attr_label=False,
with_bbox_3d=True,
with_label_3d=True,
with_bbox_depth=True),
dict(type='Resize', img_scale=(1242, 375), keep_ratio=True),
dict(type='RandomFlip3D', flip_ratio_bev_horizontal=1.0),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=[
'img', 'gt_bboxes', 'gt_labels', 'gt_bboxes_3d',
'gt_labels_3d', 'centers2d', 'depths'
]),
]
kitti_dataset = KittiMonoDataset(
ann_file='tests/data/kitti/kitti_infos_mono3d.coco.json',
info_file='tests/data/kitti/kitti_infos_mono3d.pkl',
pipeline=pipeline,
data_root='tests/data/kitti/',
img_prefix='tests/data/kitti/',
test_mode=False)
data = kitti_dataset[0]
img_metas = data['img_metas']._data
filename = img_metas['filename']
img_shape = img_metas['img_shape']
pad_shape = img_metas['pad_shape']
flip = img_metas['flip']
bboxes = data['gt_bboxes']._data
labels3d = data['gt_labels_3d']._data
labels = data['gt_labels']._data
centers2d = data['centers2d']._data
depths = data['depths']._data
expected_filename = 'tests/data/kitti/training/image_2/000007.png'
expected_img_shape = (375, 1242, 3)
expected_pad_shape = (384, 1248, 3)
expected_flip = True
expected_bboxes = torch.tensor([[625.3445, 175.0120, 676.5177, 224.9605],
[729.5906, 179.8571, 760.1503, 202.5390],
[676.7557, 175.7334, 699.7753, 193.9447],
[886.5021, 176.1380, 911.1581, 213.8148]])
expected_labels = torch.tensor([2, 2, 2, 1])
expected_centers2d = torch.tensor([[650.6185, 198.3731],
[744.2711, 190.7532],
[687.8787, 184.5331],
[898.4750, 194.4337]])
expected_depths = torch.tensor([25.0127, 47.5527, 60.5227, 34.0927])
assert filename == expected_filename
assert img_shape == expected_img_shape
assert pad_shape == expected_pad_shape
assert flip == expected_flip
assert torch.allclose(bboxes, expected_bboxes, 1e-5)
assert torch.all(labels == expected_labels)
assert torch.all(labels3d == expected_labels)
assert torch.allclose(centers2d, expected_centers2d, 1e-5)
assert torch.allclose(depths, expected_depths, 1e-5)
def test_format_results():
root_path = 'tests/data/kitti/'
info_file = 'tests/data/kitti/kitti_infos_mono3d.pkl'
ann_file = 'tests/data/kitti/kitti_infos_mono3d.coco.json'
class_names = ['Pedestrian', 'Cyclist', 'Car']
pipeline = [
dict(type='LoadImageFromFileMono3D'),
dict(
type='LoadAnnotations3D',
with_bbox=True,
with_label=True,
with_attr_label=False,
with_bbox_3d=True,
with_label_3d=True,
with_bbox_depth=True),
dict(type='Resize', img_scale=(1242, 375), keep_ratio=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=[
'img', 'gt_bboxes', 'gt_labels', 'gt_bboxes_3d',
'gt_labels_3d', 'centers2d', 'depths'
]),
]
kitti_dataset = KittiMonoDataset(
ann_file=ann_file,
info_file=info_file,
pipeline=pipeline,
data_root=root_path,
test_mode=True)
# format 3D detection results
results = mmcv.load('tests/data/kitti/mono3d_sample_results.pkl')
result_files, tmp_dir = kitti_dataset.format_results(results)
result_data = result_files['img_bbox']
assert len(result_data) == 1
assert len(result_data[0]['name']) == 4
det = result_data[0]
expected_bbox = torch.tensor([[565.4989, 175.02547, 616.70184, 225.00565],
[481.85907, 179.8642, 512.43414, 202.5624],
[542.23157, 175.73912, 565.26263, 193.96303],
[330.8572, 176.1482, 355.53937, 213.8469]])
expected_dims = torch.tensor([[3.201, 1.6110001, 1.661],
[3.701, 1.401, 1.511],
[4.051, 1.4610001, 1.661],
[1.9510001, 1.7210001, 0.501]])
expected_rotation = torch.tensor([-1.59, 1.55, 1.56, 1.54])
expected_detname = ['Car', 'Car', 'Car', 'Cyclist']
assert torch.allclose(torch.from_numpy(det['bbox']), expected_bbox, 1e-5)
assert torch.allclose(
torch.from_numpy(det['dimensions']), expected_dims, 1e-5)
assert torch.allclose(
torch.from_numpy(det['rotation_y']), expected_rotation, 1e-5)
assert det['name'].tolist() == expected_detname
# format 2D detection results
results = mmcv.load('tests/data/kitti/mono3d_sample_results2d.pkl')
result_files, tmp_dir = kitti_dataset.format_results(results)
result_data = result_files['img_bbox2d']
assert len(result_data) == 1
assert len(result_data[0]['name']) == 4
det = result_data[0]
expected_bbox = torch.tensor(
[[330.84191493, 176.13804312, 355.49885373, 213.81578769],
[565.48227204, 175.01202566, 616.65650883, 224.96147091],
[481.84967085, 179.85710612, 512.41043776, 202.54001526],
[542.22471517, 175.73341152, 565.24534908, 193.94568878]])
expected_dims = torch.tensor([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.],
[0., 0., 0.]])
expected_rotation = torch.tensor([0., 0., 0., 0.])
expected_detname = ['Cyclist', 'Car', 'Car', 'Car']
assert torch.allclose(
torch.from_numpy(det['bbox']).float(), expected_bbox, 1e-5)
assert torch.allclose(
torch.from_numpy(det['dimensions']).float(), expected_dims, 1e-5)
assert torch.allclose(
torch.from_numpy(det['rotation_y']).float(), expected_rotation, 1e-5)
assert det['name'].tolist() == expected_detname
def test_evaluate():
if not torch.cuda.is_available():
pytest.skip('test requires GPU and torch+cuda')
root_path = 'tests/data/kitti/'
info_file = 'tests/data/kitti/kitti_infos_mono3d.pkl'
ann_file = 'tests/data/kitti/kitti_infos_mono3d.coco.json'
class_names = ['Pedestrian', 'Cyclist', 'Car']
pipeline = [
dict(type='LoadImageFromFileMono3D'),
dict(
type='LoadAnnotations3D',
with_bbox=True,
with_label=True,
with_attr_label=False,
with_bbox_3d=True,
with_label_3d=True,
with_bbox_depth=True),
dict(type='Resize', img_scale=(1242, 375), keep_ratio=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=[
'img', 'gt_bboxes', 'gt_labels', 'gt_bboxes_3d',
'gt_labels_3d', 'centers2d', 'depths'
]),
]
kitti_dataset = KittiMonoDataset(
ann_file=ann_file,
info_file=info_file,
pipeline=pipeline,
data_root=root_path,
test_mode=True)
# format 3D detection results
results = mmcv.load('tests/data/kitti/mono3d_sample_results.pkl')
results2d = mmcv.load('tests/data/kitti/mono3d_sample_results2d.pkl')
results[0]['img_bbox2d'] = results2d[0]['img_bbox2d']
metric = ['mAP']
ap_dict = kitti_dataset.evaluate(results, metric)
assert np.isclose(ap_dict['img_bbox/KITTI/Overall_3D_AP11_easy'], 3.0303)
assert np.isclose(ap_dict['img_bbox/KITTI/Overall_3D_AP11_moderate'],
6.0606)
assert np.isclose(ap_dict['img_bbox/KITTI/Overall_3D_AP11_hard'], 6.0606)
assert np.isclose(ap_dict['img_bbox2d/KITTI/Overall_2D_AP11_easy'], 3.0303)
assert np.isclose(ap_dict['img_bbox2d/KITTI/Overall_2D_AP11_moderate'],
6.0606)
assert np.isclose(ap_dict['img_bbox2d/KITTI/Overall_2D_AP11_hard'], 6.0606)
# Copyright (c) OpenMMLab. All rights reserved.
import tempfile
import mmcv
import numpy as np
import torch
from mmdet3d.core import limit_period
from mmdet3d.datasets import LyftDataset
def test_getitem():
np.random.seed(0)
torch.manual_seed(0)
root_path = './tests/data/lyft'
# in coordinate system refactor, this test file is modified
ann_file = './tests/data/lyft/lyft_infos.pkl'
class_names = ('car', 'truck', 'bus', 'emergency_vehicle', 'other_vehicle',
'motorcycle', 'bicycle', 'pedestrian', 'animal')
point_cloud_range = [-80, -80, -10, 80, 80, 10]
pipelines = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=5,
use_dim=5,
file_client_args=dict(backend='disk')),
dict(
type='LoadPointsFromMultiSweeps',
sweeps_num=2,
file_client_args=dict(backend='disk')),
dict(type='LoadAnnotations3D', with_bbox_3d=True, with_label_3d=True),
dict(
type='GlobalRotScaleTrans',
rot_range=[-0.523599, 0.523599],
scale_ratio_range=[0.85, 1.15],
translation_std=[0, 0, 0]),
dict(type='RandomFlip3D', flip_ratio_bev_horizontal=0.5),
dict(type='PointsRangeFilter', point_cloud_range=point_cloud_range),
dict(type='ObjectRangeFilter', point_cloud_range=point_cloud_range),
dict(type='PointShuffle'),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D', keys=['points', 'gt_bboxes_3d', 'gt_labels_3d'])
]
lyft_dataset = LyftDataset(ann_file, pipelines, root_path)
data = lyft_dataset[0]
points = data['points']._data
gt_bboxes_3d = data['gt_bboxes_3d']._data
gt_labels_3d = data['gt_labels_3d']._data
pts_filename = data['img_metas']._data['pts_filename']
pcd_horizontal_flip = data['img_metas']._data['pcd_horizontal_flip']
pcd_scale_factor = data['img_metas']._data['pcd_scale_factor']
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']
# coord sys refactor
pcd_rotation_expected = np.array([[0.99869376, 0.05109515, 0.],
[-0.05109515, 0.99869376, 0.],
[0., 0., 1.]])
assert pts_filename == \
'tests/data/lyft/lidar/host-a017_lidar1_1236118886901125926.bin'
assert pcd_horizontal_flip is True
assert abs(pcd_scale_factor - 1.0645568099117257) < 1e-5
assert np.allclose(pcd_rotation, pcd_rotation_expected, 1e-3)
assert sample_idx == \
'b98a05255ba2632e957884758cb31f0e6fcc8d3cd6ee76b6d0ba55b72f08fc54'
expected_points = torch.tensor([[61.4785, -3.7393, 6.7699, 0.4001],
[47.7904, -3.9887, 6.0926, 0.0000],
[52.5683, -4.2178, 6.7179, 0.0000],
[52.4867, -4.0315, 6.7057, 0.0000],
[59.8372, -1.7366, 6.5864, 0.4001],
[53.0842, -3.7064, 6.7811, 0.0000],
[60.5549, -3.4978, 6.6578, 0.4001],
[59.1695, -1.2910, 7.0296, 0.2000],
[53.0702, -3.8868, 6.7807, 0.0000],
[47.9579, -4.1648, 5.6219, 0.2000],
[59.8226, -1.5522, 6.5867, 0.4001],
[61.2858, -4.2254, 7.3089, 0.2000],
[49.9896, -4.5202, 5.8823, 0.2000],
[61.4597, -4.6402, 7.3340, 0.2000],
[59.8244, -1.3499, 6.5895, 0.4001]])
expected_gt_bboxes_3d = torch.tensor(
[[63.2257, 17.5206, -0.6307, 2.0109, 5.1652, 1.9471, -1.5868],
[-25.3804, 27.4598, -2.3297, 2.7412, 8.4792, 3.4343, -1.5939],
[-15.2098, -7.0109, -2.2566, 0.7931, 0.8410, 1.7916, 1.5090]])
expected_gt_labels = np.array([0, 4, 7])
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(gt_bboxes_3d.tensor, expected_gt_bboxes_3d, 1e-3)
assert np.all(gt_labels_3d.numpy() == expected_gt_labels)
assert original_classes == class_names
lyft_dataset = LyftDataset(
ann_file, None, root_path, classes=['car', 'pedestrian'])
assert lyft_dataset.CLASSES != original_classes
assert lyft_dataset.CLASSES == ['car', 'pedestrian']
lyft_dataset = LyftDataset(
ann_file, None, root_path, classes=('car', 'pedestrian'))
assert lyft_dataset.CLASSES != original_classes
assert lyft_dataset.CLASSES == ('car', 'pedestrian')
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
path = tmpdir + 'classes.txt'
with open(path, 'w') as f:
f.write('car\npedestrian\n')
lyft_dataset = LyftDataset(ann_file, None, root_path, classes=path)
assert lyft_dataset.CLASSES != original_classes
assert lyft_dataset.CLASSES == ['car', 'pedestrian']
def test_evaluate():
root_path = './tests/data/lyft'
# in coordinate system refactor, this test file is modified
ann_file = './tests/data/lyft/lyft_infos_val.pkl'
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')
ap_dict = lyft_dataset.evaluate(results, 'bbox')
car_precision = ap_dict['pts_bbox_Lyft/car_AP']
assert car_precision == 0.6
def test_show():
from os import path as osp
import mmcv
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, 1.4442, 0.5316, 1.7450, -2.7457],
[33.3189, 0.1981, 0.3136, 1.2301, 0.5656, 1.7985, 3.1401],
[46.1366, -4.6404, -0.9510, 1.6501, 0.5162, 1.7540, -2.9486],
[33.2646, 0.2297, 0.3446, 1.3365, 0.5746, 1.7947, -3.1138],
[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])
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()
# Copyright (c) OpenMMLab. All rights reserved.
import tempfile
import numpy as np
import torch
from mmdet3d.datasets import NuScenesDataset
def test_getitem():
np.random.seed(0)
point_cloud_range = [-50, -50, -5, 50, 50, 3]
file_client_args = dict(backend='disk')
class_names = [
'car', 'truck', 'trailer', 'bus', 'construction_vehicle', 'bicycle',
'motorcycle', 'pedestrian', 'traffic_cone', 'barrier'
]
pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=5,
use_dim=5,
file_client_args=file_client_args),
dict(
type='LoadPointsFromMultiSweeps',
sweeps_num=2,
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'])
])
]
nus_dataset = NuScenesDataset(
'tests/data/nuscenes/nus_info.pkl',
pipeline,
'tests/data/nuscenes',
test_mode=True)
data = nus_dataset[0]
assert data['img_metas'][0].data['flip'] is False
assert data['img_metas'][0].data['pcd_horizontal_flip'] is False
assert data['points'][0]._data.shape == (100, 4)
data = nus_dataset[1]
assert data['img_metas'][0].data['flip'] is False
assert data['img_metas'][0].data['pcd_horizontal_flip'] is False
assert data['points'][0]._data.shape == (597, 4)
def test_show():
from os import path as osp
import mmcv
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()
# Copyright (c) OpenMMLab. All rights reserved.
import tempfile
from os import path as osp
import mmcv
import numpy as np
import pytest
import torch
from mmdet3d.datasets import NuScenesMonoDataset
def test_getitem():
np.random.seed(0)
class_names = [
'car', 'truck', 'trailer', 'bus', 'construction_vehicle', 'bicycle',
'motorcycle', 'pedestrian', 'traffic_cone', 'barrier'
]
img_norm_cfg = dict(
mean=[102.9801, 115.9465, 122.7717], std=[1.0, 1.0, 1.0], to_rgb=False)
pipeline = [
dict(type='LoadImageFromFileMono3D'),
dict(
type='LoadAnnotations3D',
with_bbox=True,
with_label=True,
with_attr_label=True,
with_bbox_3d=True,
with_label_3d=True,
with_bbox_depth=True),
dict(type='Resize', img_scale=(1600, 900), keep_ratio=True),
dict(type='RandomFlip3D', flip_ratio_bev_horizontal=1.0),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=[
'img', 'gt_bboxes', 'gt_labels', 'attr_labels', 'gt_bboxes_3d',
'gt_labels_3d', 'centers2d', 'depths'
]),
]
nus_dataset = NuScenesMonoDataset(
ann_file='tests/data/nuscenes/nus_infos_mono3d.coco.json',
pipeline=pipeline,
data_root='tests/data/nuscenes/',
img_prefix='tests/data/nuscenes/',
test_mode=False)
data = nus_dataset[0]
img_metas = data['img_metas']._data
filename = img_metas['filename']
img_shape = img_metas['img_shape']
pad_shape = img_metas['pad_shape']
flip = img_metas['flip']
bboxes = data['gt_bboxes']._data
attrs = data['attr_labels']._data
labels3d = data['gt_labels_3d']._data
labels = data['gt_labels']._data
centers2d = data['centers2d']._data
depths = data['depths']._data
expected_filename = 'tests/data/nuscenes/samples/CAM_BACK_LEFT/' + \
'n015-2018-07-18-11-07-57+0800__CAM_BACK_LEFT__1531883530447423.jpg'
expected_img_shape = (900, 1600, 3)
expected_pad_shape = (928, 1600, 3)
expected_flip = True
expected_bboxes = torch.tensor([[485.4207, 513.7568, 515.4637, 576.1393],
[748.9482, 512.0452, 776.4941, 571.6310],
[432.1318, 427.8805, 508.4290, 578.1468],
[367.3779, 427.7682, 439.4244, 578.8904],
[592.8713, 515.0040, 623.4984, 575.0945]])
expected_attr_labels = torch.tensor([8, 8, 4, 4, 8])
expected_labels = torch.tensor([8, 8, 7, 7, 8])
expected_centers2d = torch.tensor([[500.6090, 544.6358],
[762.8789, 541.5280],
[471.1633, 502.2295],
[404.1957, 502.5908],
[608.3627, 544.7317]])
expected_depths = torch.tensor(
[15.3193, 15.6073, 14.7567, 14.8803, 15.4923])
assert filename == expected_filename
assert img_shape == expected_img_shape
assert pad_shape == expected_pad_shape
assert flip == expected_flip
assert torch.allclose(bboxes, expected_bboxes, 1e-5)
assert torch.all(attrs == expected_attr_labels)
assert torch.all(labels == expected_labels)
assert torch.all(labels3d == expected_labels)
assert torch.allclose(centers2d, expected_centers2d, 1e-5)
assert torch.allclose(depths, expected_depths, 1e-5)
def test_format_results():
if not torch.cuda.is_available():
pytest.skip('test requires GPU and torch+cuda')
root_path = 'tests/data/nuscenes/'
ann_file = 'tests/data/nuscenes/nus_infos_mono3d.coco.json'
class_names = [
'car', 'truck', 'trailer', 'bus', 'construction_vehicle', 'bicycle',
'motorcycle', 'pedestrian', 'traffic_cone', 'barrier'
]
pipeline = [
dict(type='LoadImageFromFileMono3D'),
dict(
type='LoadAnnotations3D',
with_bbox=True,
with_label=True,
with_attr_label=True,
with_bbox_3d=True,
with_label_3d=True,
with_bbox_depth=True),
dict(type='Resize', img_scale=(1600, 900), keep_ratio=True),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=[
'img', 'gt_bboxes', 'gt_labels', 'attr_labels', 'gt_bboxes_3d',
'gt_labels_3d', 'centers2d', 'depths'
]),
]
nus_dataset = NuScenesMonoDataset(
ann_file=ann_file,
pipeline=pipeline,
data_root=root_path,
test_mode=True)
results = mmcv.load('tests/data/nuscenes/mono3d_sample_results.pkl')
result_files, tmp_dir = nus_dataset.format_results(results)
result_data = mmcv.load(result_files['img_bbox'])
assert len(result_data['results'].keys()) == 1
assert len(result_data['results']['e93e98b63d3b40209056d129dc53ceee']) == 8
det = result_data['results']['e93e98b63d3b40209056d129dc53ceee'][0]
expected_token = 'e93e98b63d3b40209056d129dc53ceee'
expected_trans = torch.tensor(
[1018.753821915645, 605.190386124652, 0.7266818822266328])
expected_size = torch.tensor([1.440000057220459, 1.6380000114440918, 4.25])
expected_rotation = torch.tensor([-0.5717, -0.0014, 0.0170, -0.8203])
expected_detname = 'car'
expected_attr = 'vehicle.moving'
assert det['sample_token'] == expected_token
assert torch.allclose(
torch.tensor(det['translation']), expected_trans, 1e-5)
assert torch.allclose(torch.tensor(det['size']), expected_size, 1e-5)
assert torch.allclose(
torch.tensor(det['rotation']), expected_rotation, atol=1e-4)
assert det['detection_name'] == expected_detname
assert det['attribute_name'] == expected_attr
def test_show():
root_path = 'tests/data/nuscenes/'
ann_file = 'tests/data/nuscenes/nus_infos_mono3d.coco.json'
class_names = [
'car', 'truck', 'trailer', 'bus', 'construction_vehicle', 'bicycle',
'motorcycle', 'pedestrian', 'traffic_cone', 'barrier'
]
eval_pipeline = [
dict(type='LoadImageFromFileMono3D'),
dict(
type='DefaultFormatBundle3D',
class_names=class_names,
with_label=False),
dict(type='Collect3D', keys=['img'])
]
nus_dataset = NuScenesMonoDataset(
data_root=root_path,
ann_file=ann_file,
img_prefix='tests/data/nuscenes/',
test_mode=True,
pipeline=eval_pipeline)
results = mmcv.load('tests/data/nuscenes/mono3d_sample_results.pkl')
results = [results[0]]
# show with eval_pipeline
tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name
nus_dataset.show(results, temp_dir, show=False)
file_name = 'n015-2018-07-18-11-07-57+0800__' \
'CAM_BACK_LEFT__1531883530447423'
img_file_path = osp.join(temp_dir, file_name, f'{file_name}_img.png')
gt_file_path = osp.join(temp_dir, file_name, f'{file_name}_gt.png')
pred_file_path = osp.join(temp_dir, file_name, f'{file_name}_pred.png')
mmcv.check_file_exist(img_file_path)
mmcv.check_file_exist(gt_file_path)
mmcv.check_file_exist(pred_file_path)
tmp_dir.cleanup()
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import pytest
import torch
from mmdet3d.datasets import S3DISDataset, S3DISSegDataset
def test_getitem():
np.random.seed(0)
root_path = './tests/data/s3dis/'
ann_file = './tests/data/s3dis/s3dis_infos.pkl'
class_names = ('table', 'chair', 'sofa', 'bookcase', 'board')
pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
load_dim=6,
use_dim=[0, 1, 2, 3, 4, 5]),
dict(type='LoadAnnotations3D', with_bbox_3d=True, with_label_3d=True),
dict(type='PointSample', num_points=40000),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D', keys=['points', 'gt_bboxes_3d', 'gt_labels_3d'])
]
s3dis_dataset = S3DISDataset(
data_root=root_path, ann_file=ann_file, pipeline=pipeline)
data = s3dis_dataset[0]
points = data['points']._data
gt_bboxes_3d = data['gt_bboxes_3d']._data
gt_labels_3d = data['gt_labels_3d']._data
expected_gt_bboxes_3d = torch.tensor(
[[2.3080, 2.4175, 0.2010, 0.8820, 0.8690, 0.6970, 0.0000],
[2.4730, 0.7090, 0.2010, 0.9080, 0.9620, 0.7030, 0.0000],
[5.3235, 0.4910, 0.0740, 0.8410, 0.9020, 0.8790, 0.0000]])
expected_gt_labels = np.array([1, 1, 3, 1, 2, 0, 0, 0, 3])
assert tuple(points.shape) == (40000, 6)
assert torch.allclose(gt_bboxes_3d[:3].tensor, expected_gt_bboxes_3d, 1e-2)
assert np.all(gt_labels_3d.numpy() == expected_gt_labels)
def test_evaluate():
if not torch.cuda.is_available():
pytest.skip()
from mmdet3d.core.bbox.structures import DepthInstance3DBoxes
root_path = './tests/data/s3dis'
ann_file = './tests/data/s3dis/s3dis_infos.pkl'
s3dis_dataset = S3DISDataset(root_path, ann_file)
results = []
pred_boxes = dict()
pred_boxes['boxes_3d'] = DepthInstance3DBoxes(
torch.tensor([[2.3080, 2.4175, 0.2010, 0.8820, 0.8690, 0.6970, 0.0000],
[2.4730, 0.7090, 0.2010, 0.9080, 0.9620, 0.7030, 0.0000],
[5.3235, 0.4910, 0.0740, 0.8410, 0.9020, 0.8790,
0.0000]]))
pred_boxes['labels_3d'] = torch.tensor([1, 1, 3])
pred_boxes['scores_3d'] = torch.tensor([0.5, 1.0, 1.0])
results.append(pred_boxes)
ret_dict = s3dis_dataset.evaluate(results)
assert abs(ret_dict['chair_AP_0.25'] - 0.666) < 0.01
assert abs(ret_dict['chair_AP_0.50'] - 0.666) < 0.01
assert abs(ret_dict['bookcase_AP_0.25'] - 0.5) < 0.01
assert abs(ret_dict['bookcase_AP_0.50'] - 0.5) < 0.01
def test_seg_getitem():
np.random.seed(0)
root_path = './tests/data/s3dis/'
ann_file = './tests/data/s3dis/s3dis_infos.pkl'
class_names = ('ceiling', 'floor', 'wall', 'beam', 'column', 'window',
'door', 'table', 'chair', 'sofa', 'bookcase', 'board',
'clutter')
palette = [[0, 255, 0], [0, 0, 255], [0, 255, 255], [255, 255, 0],
[255, 0, 255], [100, 100, 255], [200, 200, 100],
[170, 120, 200], [255, 0, 0], [200, 100, 100], [10, 200, 100],
[200, 200, 200], [50, 50, 50]]
scene_idxs = [0 for _ in range(20)]
pipelines = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=True,
load_dim=6,
use_dim=[0, 1, 2, 3, 4, 5]),
dict(
type='LoadAnnotations3D',
with_bbox_3d=False,
with_label_3d=False,
with_mask_3d=False,
with_seg_3d=True),
dict(
type='PointSegClassMapping',
valid_cat_ids=tuple(range(len(class_names))),
max_cat_id=13),
dict(
type='IndoorPatchPointSample',
num_points=5,
block_size=1.0,
ignore_index=len(class_names),
use_normalized_coord=True,
enlarge_size=0.2,
min_unique_num=None),
dict(type='NormalizePointsColor', color_mean=None),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=['points', 'pts_semantic_mask'],
meta_keys=['file_name', 'sample_idx'])
]
s3dis_dataset = S3DISSegDataset(
data_root=root_path,
ann_files=ann_file,
pipeline=pipelines,
classes=None,
palette=None,
modality=None,
test_mode=False,
ignore_index=None,
scene_idxs=scene_idxs)
data = s3dis_dataset[0]
points = data['points']._data
pts_semantic_mask = data['pts_semantic_mask']._data
file_name = data['img_metas']._data['file_name']
sample_idx = data['img_metas']._data['sample_idx']
assert file_name == './tests/data/s3dis/points/Area_1_office_2.bin'
assert sample_idx == 'Area_1_office_2'
expected_points = torch.tensor([[
0.0000, 0.0000, 3.1720, 0.4706, 0.4431, 0.3725, 0.4624, 0.7502, 0.9543
], [
0.2880, -0.5900, 0.0650, 0.3451, 0.3373, 0.3490, 0.5119, 0.5518, 0.0196
], [
0.1570, 0.6000, 3.1700, 0.4941, 0.4667, 0.3569, 0.4893, 0.9519, 0.9537
], [
-0.1320, 0.3950, 0.2720, 0.3216, 0.2863, 0.2275, 0.4397, 0.8830, 0.0818
],
[
-0.4860, -0.0640, 3.1710, 0.3843,
0.3725, 0.3059, 0.3789, 0.7286, 0.9540
]])
expected_pts_semantic_mask = np.array([0, 1, 0, 8, 0])
original_classes = s3dis_dataset.CLASSES
original_palette = s3dis_dataset.PALETTE
assert s3dis_dataset.CLASSES == class_names
assert s3dis_dataset.ignore_index == 13
assert torch.allclose(points, expected_points, 1e-2)
assert np.all(pts_semantic_mask.numpy() == expected_pts_semantic_mask)
assert original_classes == class_names
assert original_palette == palette
assert s3dis_dataset.scene_idxs.dtype == np.int32
assert np.all(s3dis_dataset.scene_idxs == np.array(scene_idxs))
# test dataset with selected classes
s3dis_dataset = S3DISSegDataset(
data_root=root_path,
ann_files=ann_file,
pipeline=None,
classes=['beam', 'window'],
scene_idxs=scene_idxs)
label_map = {i: 13 for i in range(14)}
label_map.update({3: 0, 5: 1})
assert s3dis_dataset.CLASSES != original_classes
assert s3dis_dataset.CLASSES == ['beam', 'window']
assert s3dis_dataset.PALETTE == [palette[3], palette[5]]
assert s3dis_dataset.VALID_CLASS_IDS == [3, 5]
assert s3dis_dataset.label_map == label_map
assert s3dis_dataset.label2cat == {0: 'beam', 1: 'window'}
# test load classes from file
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
path = tmpdir + 'classes.txt'
with open(path, 'w') as f:
f.write('beam\nwindow\n')
s3dis_dataset = S3DISSegDataset(
data_root=root_path,
ann_files=ann_file,
pipeline=None,
classes=path,
scene_idxs=scene_idxs)
assert s3dis_dataset.CLASSES != original_classes
assert s3dis_dataset.CLASSES == ['beam', 'window']
assert s3dis_dataset.PALETTE == [palette[3], palette[5]]
assert s3dis_dataset.VALID_CLASS_IDS == [3, 5]
assert s3dis_dataset.label_map == label_map
assert s3dis_dataset.label2cat == {0: 'beam', 1: 'window'}
# test scene_idxs in dataset
# we should input scene_idxs in train mode
with pytest.raises(NotImplementedError):
s3dis_dataset = S3DISSegDataset(
data_root=root_path,
ann_files=ann_file,
pipeline=None,
scene_idxs=None)
# test mode
s3dis_dataset = S3DISSegDataset(
data_root=root_path,
ann_files=ann_file,
pipeline=None,
test_mode=True,
scene_idxs=scene_idxs)
assert np.all(s3dis_dataset.scene_idxs == np.array([0]))
def test_seg_evaluate():
if not torch.cuda.is_available():
pytest.skip()
root_path = './tests/data/s3dis'
ann_file = './tests/data/s3dis/s3dis_infos.pkl'
s3dis_dataset = S3DISSegDataset(
data_root=root_path, ann_files=ann_file, test_mode=True)
results = []
pred_sem_mask = dict(
semantic_mask=torch.tensor([
2, 3, 1, 2, 2, 6, 1, 0, 1, 1, 9, 12, 3, 0, 2, 0, 2, 0, 8, 3, 1, 2,
0, 2, 1, 7, 2, 10, 2, 0, 0, 0, 2, 3, 2, 2, 2, 2, 2, 3, 0, 0, 4, 6,
7, 2, 1, 2, 0, 1, 7, 0, 2, 2, 2, 0, 2, 2, 1, 12, 0, 2, 2, 2, 2, 7,
2, 2, 0, 2, 6, 2, 12, 6, 3, 12, 2, 1, 6, 1, 2, 6, 8, 2, 10, 1, 11,
0, 6, 9, 4, 3, 0, 0, 12, 1, 1, 5, 3, 2
]).long())
results.append(pred_sem_mask)
ret_dict = s3dis_dataset.evaluate(results)
assert abs(ret_dict['miou'] - 0.7625) < 0.01
assert abs(ret_dict['acc'] - 0.9) < 0.01
assert abs(ret_dict['acc_cls'] - 0.9074) < 0.01
def test_seg_show():
import tempfile
from os import path as osp
import mmcv
tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name
root_path = './tests/data/s3dis'
ann_file = './tests/data/s3dis/s3dis_infos.pkl'
s3dis_dataset = S3DISSegDataset(
data_root=root_path, ann_files=ann_file, scene_idxs=[0])
result = dict(
semantic_mask=torch.tensor([
2, 2, 1, 2, 2, 5, 1, 0, 1, 1, 9, 12, 3, 0, 2, 0, 2, 0, 8, 2, 0, 2,
0, 2, 1, 7, 2, 10, 2, 0, 0, 0, 2, 2, 2, 2, 2, 1, 2, 2, 0, 0, 4, 6,
7, 2, 1, 2, 0, 1, 7, 0, 2, 2, 2, 0, 2, 2, 1, 12, 0, 2, 2, 2, 2, 7,
2, 2, 0, 2, 6, 2, 12, 6, 2, 12, 2, 1, 6, 1, 2, 6, 8, 2, 10, 1, 10,
0, 6, 9, 4, 3, 0, 0, 12, 1, 1, 5, 2, 2
]).long())
results = [result]
s3dis_dataset.show(results, temp_dir, show=False)
pts_file_path = osp.join(temp_dir, 'Area_1_office_2',
'Area_1_office_2_points.obj')
gt_file_path = osp.join(temp_dir, 'Area_1_office_2',
'Area_1_office_2_gt.obj')
pred_file_path = osp.join(temp_dir, 'Area_1_office_2',
'Area_1_office_2_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
class_names = ('ceiling', 'floor', 'wall', 'beam', 'column', 'window',
'door', 'table', 'chair', 'sofa', 'bookcase', 'board',
'clutter')
eval_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=True,
load_dim=6,
use_dim=[0, 1, 2, 3, 4, 5]),
dict(
type='LoadAnnotations3D',
with_bbox_3d=False,
with_label_3d=False,
with_mask_3d=False,
with_seg_3d=True),
dict(
type='PointSegClassMapping',
valid_cat_ids=tuple(range(len(class_names))),
max_cat_id=13),
dict(
type='DefaultFormatBundle3D',
with_label=False,
class_names=class_names),
dict(type='Collect3D', keys=['points', 'pts_semantic_mask'])
]
s3dis_dataset.show(results, temp_dir, show=False, pipeline=eval_pipeline)
pts_file_path = osp.join(temp_dir, 'Area_1_office_2',
'Area_1_office_2_points.obj')
gt_file_path = osp.join(temp_dir, 'Area_1_office_2',
'Area_1_office_2_gt.obj')
pred_file_path = osp.join(temp_dir, 'Area_1_office_2',
'Area_1_office_2_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_multi_areas():
# S3DIS dataset has 6 areas, we often train on several of them
# need to verify the concat function of S3DISSegDataset
root_path = './tests/data/s3dis'
ann_file = './tests/data/s3dis/s3dis_infos.pkl'
class_names = ('ceiling', 'floor', 'wall', 'beam', 'column', 'window',
'door', 'table', 'chair', 'sofa', 'bookcase', 'board',
'clutter')
palette = [[0, 255, 0], [0, 0, 255], [0, 255, 255], [255, 255, 0],
[255, 0, 255], [100, 100, 255], [200, 200, 100],
[170, 120, 200], [255, 0, 0], [200, 100, 100], [10, 200, 100],
[200, 200, 200], [50, 50, 50]]
scene_idxs = [0 for _ in range(20)]
# repeat
repeat_num = 3
s3dis_dataset = S3DISSegDataset(
data_root=root_path,
ann_files=[ann_file for _ in range(repeat_num)],
scene_idxs=scene_idxs)
assert s3dis_dataset.CLASSES == class_names
assert s3dis_dataset.PALETTE == palette
assert len(s3dis_dataset.data_infos) == repeat_num
assert np.all(s3dis_dataset.scene_idxs == np.concatenate(
[np.array(scene_idxs) + i for i in range(repeat_num)]))
# different scene_idxs input
s3dis_dataset = S3DISSegDataset(
data_root=root_path,
ann_files=[ann_file for _ in range(repeat_num)],
scene_idxs=[[0, 0, 1, 2, 2], [0, 1, 2, 3, 3, 4], [0, 1, 1, 2, 2, 2]])
assert np.all(s3dis_dataset.scene_idxs == np.array(
[0, 0, 1, 2, 2, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 10, 10]))
# Copyright (c) OpenMMLab. All rights reserved.
import copy
import numpy as np
import pytest
import torch
from mmdet3d.datasets import (ScanNetDataset, ScanNetInstanceSegDataset,
ScanNetSegDataset)
def test_getitem():
np.random.seed(0)
root_path = './tests/data/scannet/'
ann_file = './tests/data/scannet/scannet_infos.pkl'
class_names = ('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')
pipelines = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=True,
load_dim=6,
use_dim=[0, 1, 2]),
dict(
type='LoadAnnotations3D',
with_bbox_3d=True,
with_label_3d=True,
with_mask_3d=True,
with_seg_3d=True),
dict(type='GlobalAlignment', rotation_axis=2),
dict(
type='PointSegClassMapping',
valid_cat_ids=(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33,
34, 36, 39)),
dict(type='PointSample', num_points=5),
dict(
type='RandomFlip3D',
sync_2d=False,
flip_ratio_bev_horizontal=1.0,
flip_ratio_bev_vertical=1.0),
dict(
type='GlobalRotScaleTrans',
rot_range=[-0.087266, 0.087266],
scale_ratio_range=[1.0, 1.0],
shift_height=True),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=[
'points', 'gt_bboxes_3d', 'gt_labels_3d', 'pts_semantic_mask',
'pts_instance_mask'
],
meta_keys=['file_name', 'sample_idx', 'pcd_rotation']),
]
scannet_dataset = ScanNetDataset(root_path, ann_file, pipelines)
data = scannet_dataset[0]
points = data['points']._data
gt_bboxes_3d = data['gt_bboxes_3d']._data
gt_labels = data['gt_labels_3d']._data
pts_semantic_mask = data['pts_semantic_mask']._data
pts_instance_mask = data['pts_instance_mask']._data
file_name = data['img_metas']._data['file_name']
pcd_rotation = data['img_metas']._data['pcd_rotation']
sample_idx = data['img_metas']._data['sample_idx']
expected_rotation = np.array([[0.99654, 0.08311407, 0.],
[-0.08311407, 0.99654, 0.], [0., 0., 1.]])
assert file_name == './tests/data/scannet/points/scene0000_00.bin'
assert np.allclose(pcd_rotation, expected_rotation, 1e-3)
assert sample_idx == 'scene0000_00'
expected_points = torch.tensor(
[[1.8339e+00, 2.1093e+00, 2.2900e+00, 2.3895e+00],
[3.6079e+00, 1.4592e-01, 2.0687e+00, 2.1682e+00],
[4.1886e+00, 5.0614e+00, -1.0841e-01, -8.8736e-03],
[6.8790e+00, 1.5086e+00, -9.3154e-02, 6.3816e-03],
[4.8253e+00, 2.6668e-01, 1.4917e+00, 1.5912e+00]])
expected_gt_bboxes_3d = torch.tensor(
[[-1.1835, -3.6317, 1.5704, 1.7577, 0.3761, 0.5724, 0.0000],
[-3.1832, 3.2269, 1.1911, 0.6727, 0.2251, 0.6715, 0.0000],
[-0.9598, -2.2864, 0.0093, 0.7506, 2.5709, 1.2145, 0.0000],
[-2.6988, -2.7354, 0.8288, 0.7680, 1.8877, 0.2870, 0.0000],
[3.2989, 0.2885, -0.0090, 0.7600, 3.8814, 2.1603, 0.0000]])
expected_gt_labels = np.array([
6, 6, 4, 9, 11, 11, 10, 0, 15, 17, 17, 17, 3, 12, 4, 4, 14, 1, 0, 0, 0,
0, 0, 0, 5, 5, 5
])
expected_pts_semantic_mask = np.array([0, 18, 18, 18, 18])
expected_pts_instance_mask = np.array([44, 22, 10, 10, 57])
original_classes = scannet_dataset.CLASSES
assert scannet_dataset.CLASSES == class_names
assert torch.allclose(points, expected_points, 1e-2)
assert gt_bboxes_3d.tensor[:5].shape == (5, 7)
assert torch.allclose(gt_bboxes_3d.tensor[:5], expected_gt_bboxes_3d, 1e-2)
assert np.all(gt_labels.numpy() == expected_gt_labels)
assert np.all(pts_semantic_mask.numpy() == expected_pts_semantic_mask)
assert np.all(pts_instance_mask.numpy() == expected_pts_instance_mask)
assert original_classes == class_names
scannet_dataset = ScanNetDataset(
root_path, ann_file, pipeline=None, classes=['cabinet', 'bed'])
assert scannet_dataset.CLASSES != original_classes
assert scannet_dataset.CLASSES == ['cabinet', 'bed']
scannet_dataset = ScanNetDataset(
root_path, ann_file, pipeline=None, classes=('cabinet', 'bed'))
assert scannet_dataset.CLASSES != original_classes
assert scannet_dataset.CLASSES == ('cabinet', 'bed')
# Test load classes from file
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
path = tmpdir + 'classes.txt'
with open(path, 'w') as f:
f.write('cabinet\nbed\n')
scannet_dataset = ScanNetDataset(
root_path, ann_file, pipeline=None, classes=path)
assert scannet_dataset.CLASSES != original_classes
assert scannet_dataset.CLASSES == ['cabinet', 'bed']
def test_evaluate():
if not torch.cuda.is_available():
pytest.skip()
from mmdet3d.core.bbox.structures import DepthInstance3DBoxes
root_path = './tests/data/scannet'
ann_file = './tests/data/scannet/scannet_infos.pkl'
scannet_dataset = ScanNetDataset(root_path, ann_file)
results = []
pred_boxes = dict()
pred_boxes['boxes_3d'] = DepthInstance3DBoxes(
torch.tensor([[
1.4813e+00, 3.5207e+00, 1.5704e+00, 1.7445e+00, 2.3196e-01,
5.7235e-01, 0.0000e+00
],
[
2.9040e+00, -3.4803e+00, 1.1911e+00, 6.6078e-01,
1.7072e-01, 6.7154e-01, 0.0000e+00
],
[
1.1466e+00, 2.1987e+00, 9.2576e-03, 5.4184e-01,
2.5346e+00, 1.2145e+00, 0.0000e+00
],
[
2.9168e+00, 2.5016e+00, 8.2875e-01, 6.1697e-01,
1.8428e+00, 2.8697e-01, 0.0000e+00
],
[
-3.3114e+00, -1.3351e-02, -8.9524e-03, 4.4082e-01,
3.8582e+00, 2.1603e+00, 0.0000e+00
],
[
-2.0135e+00, -3.4857e+00, 9.3848e-01, 1.9911e+00,
2.1603e-01, 1.2767e+00, 0.0000e+00
],
[
-2.1945e+00, -3.1402e+00, -3.8165e-02, 1.4801e+00,
6.8676e-01, 1.0586e+00, 0.0000e+00
],
[
-2.7553e+00, 2.4055e+00, -2.9972e-02, 1.4764e+00,
1.4927e+00, 2.3380e+00, 0.0000e+00
]]))
pred_boxes['labels_3d'] = torch.tensor([6, 6, 4, 9, 11, 11])
pred_boxes['scores_3d'] = torch.tensor([0.5, 1.0, 1.0, 1.0, 1.0, 0.5])
results.append(pred_boxes)
metric = [0.25, 0.5]
ret_dict = scannet_dataset.evaluate(results, metric)
assert abs(ret_dict['table_AP_0.25'] - 0.3333) < 0.01
assert abs(ret_dict['window_AP_0.25'] - 1.0) < 0.01
assert abs(ret_dict['counter_AP_0.25'] - 1.0) < 0.01
assert abs(ret_dict['curtain_AP_0.25'] - 1.0) < 0.01
# test evaluate with pipeline
class_names = ('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')
eval_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
load_dim=6,
use_dim=[0, 1, 2]),
dict(type='GlobalAlignment', rotation_axis=2),
dict(
type='DefaultFormatBundle3D',
class_names=class_names,
with_label=False),
dict(type='Collect3D', keys=['points'])
]
ret_dict = scannet_dataset.evaluate(
results, metric, pipeline=eval_pipeline)
assert abs(ret_dict['table_AP_0.25'] - 0.3333) < 0.01
assert abs(ret_dict['window_AP_0.25'] - 1.0) < 0.01
assert abs(ret_dict['counter_AP_0.25'] - 1.0) < 0.01
assert abs(ret_dict['curtain_AP_0.25'] - 1.0) < 0.01
def test_show():
import tempfile
from os import path as osp
import mmcv
from mmdet3d.core.bbox import DepthInstance3DBoxes
tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name
root_path = './tests/data/scannet'
ann_file = './tests/data/scannet/scannet_infos.pkl'
scannet_dataset = ScanNetDataset(root_path, ann_file)
boxes_3d = DepthInstance3DBoxes(
torch.tensor([[
-2.4053e+00, 9.2295e-01, 8.0661e-02, 2.4054e+00, 2.1468e+00,
8.5990e-01, 0.0000e+00
],
[
-1.9341e+00, -2.0741e+00, 3.0698e-03, 3.2206e-01,
2.5322e-01, 3.5144e-01, 0.0000e+00
],
[
-3.6908e+00, 8.0684e-03, 2.6201e-01, 4.1515e-01,
7.6489e-01, 5.3585e-01, 0.0000e+00
],
[
2.6332e+00, 8.5143e-01, -4.9964e-03, 3.0367e-01,
1.3448e+00, 1.8329e+00, 0.0000e+00
],
[
2.0221e-02, 2.6153e+00, 1.5109e-02, 7.3335e-01,
1.0429e+00, 1.0251e+00, 0.0000e+00
]]))
scores_3d = torch.tensor(
[1.2058e-04, 2.3012e-03, 6.2324e-06, 6.6139e-06, 6.7965e-05])
labels_3d = torch.tensor([0, 0, 0, 0, 0])
result = dict(boxes_3d=boxes_3d, scores_3d=scores_3d, labels_3d=labels_3d)
results = [result]
scannet_dataset.show(results, temp_dir, show=False)
pts_file_path = osp.join(temp_dir, 'scene0000_00',
'scene0000_00_points.obj')
gt_file_path = osp.join(temp_dir, 'scene0000_00', 'scene0000_00_gt.obj')
pred_file_path = osp.join(temp_dir, 'scene0000_00',
'scene0000_00_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()
# show function with pipeline
class_names = ('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')
eval_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
load_dim=6,
use_dim=[0, 1, 2]),
dict(type='GlobalAlignment', rotation_axis=2),
dict(
type='DefaultFormatBundle3D',
class_names=class_names,
with_label=False),
dict(type='Collect3D', keys=['points'])
]
tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name
scannet_dataset.show(results, temp_dir, show=False, pipeline=eval_pipeline)
pts_file_path = osp.join(temp_dir, 'scene0000_00',
'scene0000_00_points.obj')
gt_file_path = osp.join(temp_dir, 'scene0000_00', 'scene0000_00_gt.obj')
pred_file_path = osp.join(temp_dir, 'scene0000_00',
'scene0000_00_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_seg_getitem():
np.random.seed(0)
root_path = './tests/data/scannet/'
ann_file = './tests/data/scannet/scannet_infos.pkl'
class_names = ('wall', 'floor', 'cabinet', 'bed', 'chair', 'sofa', 'table',
'door', 'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'otherfurniture')
palette = [
[174, 199, 232],
[152, 223, 138],
[31, 119, 180],
[255, 187, 120],
[188, 189, 34],
[140, 86, 75],
[255, 152, 150],
[214, 39, 40],
[197, 176, 213],
[148, 103, 189],
[196, 156, 148],
[23, 190, 207],
[247, 182, 210],
[219, 219, 141],
[255, 127, 14],
[158, 218, 229],
[44, 160, 44],
[112, 128, 144],
[227, 119, 194],
[82, 84, 163],
]
scene_idxs = [0 for _ in range(20)]
# test network inputs are (xyz, rgb, normalized_xyz)
pipelines = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=True,
load_dim=6,
use_dim=[0, 1, 2, 3, 4, 5]),
dict(
type='LoadAnnotations3D',
with_bbox_3d=False,
with_label_3d=False,
with_mask_3d=False,
with_seg_3d=True),
dict(
type='PointSegClassMapping',
valid_cat_ids=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24,
28, 33, 34, 36, 39),
max_cat_id=40),
dict(
type='IndoorPatchPointSample',
num_points=5,
block_size=1.5,
ignore_index=len(class_names),
use_normalized_coord=True,
enlarge_size=0.2,
min_unique_num=None),
dict(type='NormalizePointsColor', color_mean=None),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=['points', 'pts_semantic_mask'],
meta_keys=['file_name', 'sample_idx'])
]
scannet_dataset = ScanNetSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=pipelines,
classes=None,
palette=None,
modality=None,
test_mode=False,
ignore_index=None,
scene_idxs=scene_idxs)
data = scannet_dataset[0]
points = data['points']._data
pts_semantic_mask = data['pts_semantic_mask']._data
file_name = data['img_metas']._data['file_name']
sample_idx = data['img_metas']._data['sample_idx']
assert file_name == './tests/data/scannet/points/scene0000_00.bin'
assert sample_idx == 'scene0000_00'
expected_points = torch.tensor([[
0.0000, 0.0000, 1.2427, 0.6118, 0.5529, 0.4471, -0.6462, -1.0046,
0.4280
],
[
0.1553, -0.0074, 1.6077, 0.5882,
0.6157, 0.5569, -0.6001, -1.0068,
0.5537
],
[
0.1518, 0.6016, 0.6548, 0.1490, 0.1059,
0.0431, -0.6012, -0.8309, 0.2255
],
[
-0.7494, 0.1033, 0.6756, 0.5216,
0.4353, 0.3333, -0.8687, -0.9748,
0.2327
],
[
-0.6836, -0.0203, 0.5884, 0.5765,
0.5020, 0.4510, -0.8491, -1.0105,
0.2027
]])
expected_pts_semantic_mask = np.array([13, 13, 12, 2, 0])
original_classes = scannet_dataset.CLASSES
original_palette = scannet_dataset.PALETTE
assert scannet_dataset.CLASSES == class_names
assert scannet_dataset.ignore_index == 20
assert torch.allclose(points, expected_points, 1e-2)
assert np.all(pts_semantic_mask.numpy() == expected_pts_semantic_mask)
assert original_classes == class_names
assert original_palette == palette
assert scannet_dataset.scene_idxs.dtype == np.int32
assert np.all(scannet_dataset.scene_idxs == np.array(scene_idxs))
# test network inputs are (xyz, rgb)
np.random.seed(0)
new_pipelines = copy.deepcopy(pipelines)
new_pipelines[3] = dict(
type='IndoorPatchPointSample',
num_points=5,
block_size=1.5,
ignore_index=len(class_names),
use_normalized_coord=False,
enlarge_size=0.2,
min_unique_num=None)
scannet_dataset = ScanNetSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=new_pipelines,
scene_idxs=scene_idxs)
data = scannet_dataset[0]
points = data['points']._data
assert torch.allclose(points, expected_points[:, :6], 1e-2)
# test network inputs are (xyz, normalized_xyz)
np.random.seed(0)
new_pipelines = copy.deepcopy(pipelines)
new_pipelines[0] = dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=False,
load_dim=6,
use_dim=[0, 1, 2])
new_pipelines.remove(new_pipelines[4])
scannet_dataset = ScanNetSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=new_pipelines,
scene_idxs=scene_idxs)
data = scannet_dataset[0]
points = data['points']._data
assert torch.allclose(points, expected_points[:, [0, 1, 2, 6, 7, 8]], 1e-2)
# test network inputs are (xyz,)
np.random.seed(0)
new_pipelines = copy.deepcopy(pipelines)
new_pipelines[0] = dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=False,
load_dim=6,
use_dim=[0, 1, 2])
new_pipelines[3] = dict(
type='IndoorPatchPointSample',
num_points=5,
block_size=1.5,
ignore_index=len(class_names),
use_normalized_coord=False,
enlarge_size=0.2,
min_unique_num=None)
new_pipelines.remove(new_pipelines[4])
scannet_dataset = ScanNetSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=new_pipelines,
scene_idxs=scene_idxs)
data = scannet_dataset[0]
points = data['points']._data
assert torch.allclose(points, expected_points[:, :3], 1e-2)
# test dataset with selected classes
scannet_dataset = ScanNetSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=None,
classes=['cabinet', 'chair'],
scene_idxs=scene_idxs)
label_map = {i: 20 for i in range(41)}
label_map.update({3: 0, 5: 1})
assert scannet_dataset.CLASSES != original_classes
assert scannet_dataset.CLASSES == ['cabinet', 'chair']
assert scannet_dataset.PALETTE == [palette[2], palette[4]]
assert scannet_dataset.VALID_CLASS_IDS == [3, 5]
assert scannet_dataset.label_map == label_map
assert scannet_dataset.label2cat == {0: 'cabinet', 1: 'chair'}
# test load classes from file
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
path = tmpdir + 'classes.txt'
with open(path, 'w') as f:
f.write('cabinet\nchair\n')
scannet_dataset = ScanNetSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=None,
classes=path,
scene_idxs=scene_idxs)
assert scannet_dataset.CLASSES != original_classes
assert scannet_dataset.CLASSES == ['cabinet', 'chair']
assert scannet_dataset.PALETTE == [palette[2], palette[4]]
assert scannet_dataset.VALID_CLASS_IDS == [3, 5]
assert scannet_dataset.label_map == label_map
assert scannet_dataset.label2cat == {0: 'cabinet', 1: 'chair'}
# test scene_idxs in dataset
# we should input scene_idxs in train mode
with pytest.raises(NotImplementedError):
scannet_dataset = ScanNetSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=None,
scene_idxs=None)
# test mode
scannet_dataset = ScanNetSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=None,
test_mode=True,
scene_idxs=scene_idxs)
assert np.all(scannet_dataset.scene_idxs == np.array([0]))
def test_seg_evaluate():
if not torch.cuda.is_available():
pytest.skip()
root_path = './tests/data/scannet'
ann_file = './tests/data/scannet/scannet_infos.pkl'
scannet_dataset = ScanNetSegDataset(
data_root=root_path, ann_file=ann_file, test_mode=True)
results = []
pred_sem_mask = dict(
semantic_mask=torch.tensor([
13, 5, 1, 2, 6, 2, 13, 1, 14, 2, 0, 0, 5, 5, 3, 0, 1, 14, 0, 0, 0,
18, 6, 15, 13, 0, 2, 4, 0, 3, 16, 6, 13, 5, 13, 0, 0, 0, 0, 1, 7,
3, 19, 12, 8, 0, 11, 0, 0, 1, 2, 13, 17, 1, 1, 1, 6, 2, 13, 19, 4,
17, 0, 14, 1, 7, 2, 1, 7, 2, 0, 5, 17, 5, 0, 0, 3, 6, 5, 11, 1, 13,
13, 2, 3, 1, 0, 13, 19, 1, 14, 5, 3, 1, 13, 1, 2, 3, 2, 1
]).long())
results.append(pred_sem_mask)
class_names = ('wall', 'floor', 'cabinet', 'bed', 'chair', 'sofa', 'table',
'door', 'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'otherfurniture')
eval_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=True,
load_dim=6,
use_dim=[0, 1, 2, 3, 4, 5]),
dict(
type='LoadAnnotations3D',
with_bbox_3d=False,
with_label_3d=False,
with_mask_3d=False,
with_seg_3d=True),
dict(
type='PointSegClassMapping',
valid_cat_ids=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24,
28, 33, 34, 36, 39),
max_cat_id=40),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(type='Collect3D', keys=['points', 'pts_semantic_mask'])
]
ret_dict = scannet_dataset.evaluate(results, pipeline=eval_pipeline)
assert abs(ret_dict['miou'] - 0.5308) < 0.01
assert abs(ret_dict['acc'] - 0.8219) < 0.01
assert abs(ret_dict['acc_cls'] - 0.7649) < 0.01
def test_seg_show():
import tempfile
from os import path as osp
import mmcv
tmp_dir = tempfile.TemporaryDirectory()
temp_dir = tmp_dir.name
root_path = './tests/data/scannet'
ann_file = './tests/data/scannet/scannet_infos.pkl'
scannet_dataset = ScanNetSegDataset(
data_root=root_path, ann_file=ann_file, scene_idxs=[0])
result = dict(
semantic_mask=torch.tensor([
13, 5, 1, 2, 6, 2, 13, 1, 14, 2, 0, 0, 5, 5, 3, 0, 1, 14, 0, 0, 0,
18, 6, 15, 13, 0, 2, 4, 0, 3, 16, 6, 13, 5, 13, 0, 0, 0, 0, 1, 7,
3, 19, 12, 8, 0, 11, 0, 0, 1, 2, 13, 17, 1, 1, 1, 6, 2, 13, 19, 4,
17, 0, 14, 1, 7, 2, 1, 7, 2, 0, 5, 17, 5, 0, 0, 3, 6, 5, 11, 1, 13,
13, 2, 3, 1, 0, 13, 19, 1, 14, 5, 3, 1, 13, 1, 2, 3, 2, 1
]).long())
results = [result]
scannet_dataset.show(results, temp_dir, show=False)
pts_file_path = osp.join(temp_dir, 'scene0000_00',
'scene0000_00_points.obj')
gt_file_path = osp.join(temp_dir, 'scene0000_00', 'scene0000_00_gt.obj')
pred_file_path = osp.join(temp_dir, 'scene0000_00',
'scene0000_00_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
class_names = ('wall', 'floor', 'cabinet', 'bed', 'chair', 'sofa', 'table',
'door', 'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'otherfurniture')
eval_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=True,
load_dim=6,
use_dim=[0, 1, 2, 3, 4, 5]),
dict(
type='LoadAnnotations3D',
with_bbox_3d=False,
with_label_3d=False,
with_mask_3d=False,
with_seg_3d=True),
dict(
type='PointSegClassMapping',
valid_cat_ids=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24,
28, 33, 34, 36, 39),
max_cat_id=40),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(type='Collect3D', keys=['points', 'pts_semantic_mask'])
]
scannet_dataset.show(results, temp_dir, show=False, pipeline=eval_pipeline)
pts_file_path = osp.join(temp_dir, 'scene0000_00',
'scene0000_00_points.obj')
gt_file_path = osp.join(temp_dir, 'scene0000_00', 'scene0000_00_gt.obj')
pred_file_path = osp.join(temp_dir, 'scene0000_00',
'scene0000_00_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_seg_format_results():
from os import path as osp
import mmcv
root_path = './tests/data/scannet'
ann_file = './tests/data/scannet/scannet_infos.pkl'
scannet_dataset = ScanNetSegDataset(
data_root=root_path, ann_file=ann_file, test_mode=True)
results = []
pred_sem_mask = dict(
semantic_mask=torch.tensor([
13, 5, 1, 2, 6, 2, 13, 1, 14, 2, 0, 0, 5, 5, 3, 0, 1, 14, 0, 0, 0,
18, 6, 15, 13, 0, 2, 4, 0, 3, 16, 6, 13, 5, 13, 0, 0, 0, 0, 1, 7,
3, 19, 12, 8, 0, 11, 0, 0, 1, 2, 13, 17, 1, 1, 1, 6, 2, 13, 19, 4,
17, 0, 14, 1, 7, 2, 1, 7, 2, 0, 5, 17, 5, 0, 0, 3, 6, 5, 11, 1, 13,
13, 2, 3, 1, 0, 13, 19, 1, 14, 5, 3, 1, 13, 1, 2, 3, 2, 1
]).long())
results.append(pred_sem_mask)
result_files, tmp_dir = scannet_dataset.format_results(results)
expected_label = np.array([
16, 6, 2, 3, 7, 3, 16, 2, 24, 3, 1, 1, 6, 6, 4, 1, 2, 24, 1, 1, 1, 36,
7, 28, 16, 1, 3, 5, 1, 4, 33, 7, 16, 6, 16, 1, 1, 1, 1, 2, 8, 4, 39,
14, 9, 1, 12, 1, 1, 2, 3, 16, 34, 2, 2, 2, 7, 3, 16, 39, 5, 34, 1, 24,
2, 8, 3, 2, 8, 3, 1, 6, 34, 6, 1, 1, 4, 7, 6, 12, 2, 16, 16, 3, 4, 2,
1, 16, 39, 2, 24, 6, 4, 2, 16, 2, 3, 4, 3, 2
])
expected_txt_path = osp.join(tmp_dir.name, 'results', 'scene0000_00.txt')
assert np.all(result_files[0]['seg_mask'] == expected_label)
mmcv.check_file_exist(expected_txt_path)
def test_instance_seg_getitem():
np.random.seed(0)
root_path = './tests/data/scannet/'
ann_file = './tests/data/scannet/scannet_infos.pkl'
class_names = ('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')
train_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=True,
load_dim=6,
use_dim=[0, 1, 2, 3, 4, 5]),
dict(
type='LoadAnnotations3D',
with_bbox_3d=False,
with_label_3d=False,
with_mask_3d=True,
with_seg_3d=True),
dict(
type='PointSegClassMapping',
valid_cat_ids=(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33,
34, 36, 39),
max_cat_id=40),
dict(type='NormalizePointsColor', color_mean=None),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=['points', 'pts_semantic_mask', 'pts_instance_mask'])
]
scannet_dataset = ScanNetInstanceSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=train_pipeline,
classes=class_names,
test_mode=False)
expected_points = torch.tensor([[
-3.4742e+00, 7.8792e-01, 1.7397e+00, 3.3725e-01, 3.5294e-01, 3.0588e-01
], [
2.7216e+00, 3.4164e+00, 2.4572e+00, 6.6275e-01, 6.2745e-01, 5.1373e-01
],
[
1.3404e+00, -1.4675e+00, -4.4059e-02,
3.8431e-01, 3.6078e-01, 3.5686e-01
],
[
-3.0335e+00, 2.7273e+00, 1.5181e+00,
2.3137e-01, 1.6078e-01, 8.2353e-02
],
[
-4.3207e-01, 1.8154e+00, 1.7455e-01,
4.0392e-01, 3.8039e-01, 4.1961e-01
]])
data = scannet_dataset[0]
points = data['points']._data[:5]
pts_semantic_mask = data['pts_semantic_mask']._data[:5]
pts_instance_mask = data['pts_instance_mask']._data[:5]
expected_semantic_mask = np.array([11, 18, 18, 0, 4])
expected_instance_mask = np.array([6, 56, 10, 9, 35])
assert torch.allclose(points, expected_points, 1e-2)
assert np.all(pts_semantic_mask.numpy() == expected_semantic_mask)
assert np.all(pts_instance_mask.numpy() == expected_instance_mask)
def test_instance_seg_evaluate():
root_path = './tests/data/scannet'
ann_file = './tests/data/scannet/scannet_infos.pkl'
class_names = ('cabinet', 'bed', 'chair', 'sofa', 'table', 'door',
'window', 'bookshelf', 'picture', 'counter', 'desk',
'curtain', 'refrigerator', 'showercurtrain', 'toilet',
'sink', 'bathtub', 'garbagebin')
test_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=True,
load_dim=6,
use_dim=[0, 1, 2, 3, 4, 5]),
dict(type='NormalizePointsColor', color_mean=None),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(type='Collect3D', keys=['points'])
]
scannet_dataset = ScanNetInstanceSegDataset(
data_root=root_path,
ann_file=ann_file,
pipeline=test_pipeline,
test_mode=True)
pred_mask = torch.tensor([
1, -1, -1, -1, 7, 11, 2, -1, 1, 10, -1, -1, 5, -1, -1, -1, -1, 1, -1,
-1, -1, -1, 0, -1, 1, -1, 12, -1, -1, -1, 8, 5, 1, 5, 2, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 8, -1, -1, -1,
0, 4, 3, -1, 9, -1, -1, 6, -1, -1, -1, -1, 13, -1, -1, 5, -1, 5, -1,
-1, 9, 0, 5, -1, -1, 2, 3, 4, -1, -1, -1, 2, -1, -1, -1, 5, 9, -1, 1,
-1, 4, 10, 4, -1
]).long()
pred_labels = torch.tensor(
[4, 11, 11, 10, 0, 3, 12, 4, 14, 1, 0, 0, 0, 5, 5]).long()
pred_scores = torch.tensor([.99 for _ in range(len(pred_labels))])
results = [
dict(
instance_mask=pred_mask,
instance_label=pred_labels,
instance_score=torch.tensor(pred_scores))
]
eval_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='DEPTH',
shift_height=False,
use_color=True,
load_dim=6,
use_dim=[0, 1, 2, 3, 4, 5]),
dict(
type='LoadAnnotations3D',
with_bbox_3d=False,
with_label_3d=False,
with_mask_3d=True,
with_seg_3d=True),
dict(
type='PointSegClassMapping',
valid_cat_ids=(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33,
34, 36, 39),
max_cat_id=40),
dict(type='NormalizePointsColor', color_mean=None),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=['points', 'pts_semantic_mask', 'pts_instance_mask'])
]
# We add options here as default min_region_size
# is much bigger than test instances.
ret_dict = scannet_dataset.evaluate(
results,
pipeline=eval_pipeline,
options=dict(min_region_sizes=np.array([1])))
assert abs(ret_dict['all_ap'] - 0.90625) < 0.001
assert abs(ret_dict['all_ap_50%'] - 0.90625) < 0.001
assert abs(ret_dict['all_ap_25%'] - 0.94444) < 0.001
assert abs(ret_dict['classes']['cabinet']['ap25%'] - 1.0) < 0.001
assert abs(ret_dict['classes']['cabinet']['ap50%'] - 0.65625) < 0.001
assert abs(ret_dict['classes']['door']['ap25%'] - 0.5) < 0.001
assert abs(ret_dict['classes']['door']['ap50%'] - 0.5) < 0.001
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
from mmdet3d.datasets import SemanticKITTIDataset
def test_getitem():
np.random.seed(0)
root_path = './tests/data/semantickitti/'
ann_file = './tests/data/semantickitti/semantickitti_infos.pkl'
class_names = ('unlabeled', 'car', 'bicycle', 'motorcycle', 'truck', 'bus',
'person', 'bicyclist', 'motorcyclist', 'road', 'parking',
'sidewalk', 'other-ground', 'building', 'fence',
'vegetation', 'trunck', 'terrian', 'pole', 'traffic-sign')
pipelines = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
shift_height=True,
load_dim=4,
use_dim=[0, 1, 2]),
dict(
type='LoadAnnotations3D',
with_bbox_3d=False,
with_label_3d=False,
with_mask_3d=False,
with_seg_3d=True,
seg_3d_dtype=np.int32),
dict(
type='RandomFlip3D',
sync_2d=False,
flip_ratio_bev_horizontal=1.0,
flip_ratio_bev_vertical=1.0),
dict(
type='GlobalRotScaleTrans',
rot_range=[-0.087266, 0.087266],
scale_ratio_range=[1.0, 1.0],
shift_height=True),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=[
'points',
'pts_semantic_mask',
],
meta_keys=['file_name', 'sample_idx', 'pcd_rotation']),
]
semantickitti_dataset = SemanticKITTIDataset(root_path, ann_file,
pipelines)
data = semantickitti_dataset[0]
assert data['points']._data.shape[0] == data[
'pts_semantic_mask']._data.shape[0]
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