Skip to content

Commit

Permalink
add lidarseg config && support torchsparse++
Browse files Browse the repository at this point in the history
  • Loading branch information
sunjiahao1999 committed Feb 22, 2024
1 parent 22e456d commit 4ba030a
Show file tree
Hide file tree
Showing 44 changed files with 1,073 additions and 6 deletions.
221 changes: 221 additions & 0 deletions mmdet3d/configs/_base_/datasets/nus_seg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
# Copyright (c) OpenMMLab. All rights reserved.
from mmcv.transforms import TestTimeAug
from mmengine.dataset.sampler import DefaultSampler
from mmengine.visualization import LocalVisBackend

from mmdet3d.datasets import NuScenesSegDataset
from mmdet3d.datasets.transforms import (GlobalRotScaleTrans,
LoadAnnotations3D, LoadPointsFromFile,
Pack3DDetInputs, PointSegClassMapping,
RandomFlip3D)
from mmdet3d.evaluation import SegMetric
from mmdet3d.models import Seg3DTTAModel
from mmdet3d.visualization import Det3DLocalVisualizer

# For nuScenes we usually do 16-class segmentation.
# For labels_map we follow the uniform format of MMDetection & MMSegmentation
# i.e. we consider the unlabeled class as the last one, which is different
# from the original implementation of some methods e.g. Cylinder3D.
data_root = 'data/nuscenes/'
class_names = [
'barrier', 'bicycle', 'bus', 'car', 'construction_vehicle', 'motorcycle',
'pedestrian', 'traffic_cone', 'trailer', 'truck', 'driveable_surface',
'other_flat', 'sidewalk', 'terrain', 'manmade', 'vegetation'
]
labels_map = {
0: 16,
1: 16,
2: 6,
3: 6,
4: 6,
5: 16,
6: 6,
7: 16,
8: 16,
9: 0,
10: 16,
11: 16,
12: 7,
13: 16,
14: 1,
15: 2,
16: 2,
17: 3,
18: 4,
19: 16,
20: 16,
21: 5,
22: 8,
23: 9,
24: 10,
25: 11,
26: 12,
27: 13,
28: 14,
29: 16,
30: 15,
31: 16
}

metainfo = dict(
classes=class_names, seg_label_mapping=labels_map, max_label=31)

input_modality = dict(use_lidar=True, use_camera=False)
data_prefix = dict(
pts='samples/LIDAR_TOP',
img='',
pts_semantic_mask='lidarseg/v1.0-trainval')

# Example to use different file client
# Method 1: simply set the data root and let the file I/O module
# automatically infer from prefix (not support LMDB and Memcache yet)

# data_root = 's3://openmmlab/datasets/detection3d/nuscenes/'

# Method 2: Use backend_args, file_client_args in versions before 1.1.0
# backend_args = dict(
# backend='petrel',
# path_mapping=dict({
# './data/': 's3://openmmlab/datasets/detection3d/',
# 'data/': 's3://openmmlab/datasets/detection3d/'
# }))
backend_args = None

train_pipeline = [
dict(
type=LoadPointsFromFile,
coord_type='LIDAR',
load_dim=5,
use_dim=4,
backend_args=backend_args),
dict(
type=LoadAnnotations3D,
with_bbox_3d=False,
with_label_3d=False,
with_seg_3d=True,
seg_3d_dtype='np.uint8',
backend_args=backend_args),
dict(type=PointSegClassMapping),
dict(
type=RandomFlip3D,
sync_2d=False,
flip_ratio_bev_horizontal=0.5,
flip_ratio_bev_vertical=0.5),
dict(
type=GlobalRotScaleTrans,
rot_range=[-0.78539816, 0.78539816],
scale_ratio_range=[0.95, 1.05],
translation_std=[0.1, 0.1, 0.1]),
dict(type=Pack3DDetInputs, keys=['points', 'pts_semantic_mask'])
]
test_pipeline = [
dict(
type=LoadPointsFromFile,
coord_type='LIDAR',
load_dim=5,
use_dim=4,
backend_args=backend_args),
dict(
type=LoadAnnotations3D,
with_bbox_3d=False,
with_label_3d=False,
with_seg_3d=True,
seg_3d_dtype='np.uint8',
backend_args=backend_args),
dict(type=PointSegClassMapping),
dict(type=Pack3DDetInputs, keys=['points'])
]
tta_pipeline = [
dict(
type=LoadPointsFromFile,
coord_type='LIDAR',
load_dim=5,
use_dim=4,
backend_args=backend_args),
dict(
type=LoadAnnotations3D,
with_bbox_3d=False,
with_label_3d=False,
with_seg_3d=True,
seg_3d_dtype='np.uint8',
backend_args=backend_args),
dict(type=PointSegClassMapping),
dict(
type=TestTimeAug,
transforms=[[
dict(
type=RandomFlip3D,
sync_2d=False,
flip_ratio_bev_horizontal=0.,
flip_ratio_bev_vertical=0.),
dict(
type=RandomFlip3D,
sync_2d=False,
flip_ratio_bev_horizontal=0.,
flip_ratio_bev_vertical=1.),
dict(
type=RandomFlip3D,
sync_2d=False,
flip_ratio_bev_horizontal=1.,
flip_ratio_bev_vertical=0.),
dict(
type=RandomFlip3D,
sync_2d=False,
flip_ratio_bev_horizontal=1.,
flip_ratio_bev_vertical=1.)
],
[
dict(
type=GlobalRotScaleTrans,
rot_range=[pcd_rotate_range, pcd_rotate_range],
scale_ratio_range=[
pcd_scale_factor, pcd_scale_factor
],
translation_std=[0, 0, 0])
for pcd_rotate_range in [-0.78539816, 0.0, 0.78539816]
for pcd_scale_factor in [0.95, 1.0, 1.05]
], [dict(type=Pack3DDetInputs, keys=['points'])]])
]

train_dataloader = dict(
batch_size=2,
num_workers=4,
persistent_workers=True,
sampler=dict(type=DefaultSampler, shuffle=True),
dataset=dict(
type=NuScenesSegDataset,
data_root=data_root,
ann_file='nuscenes_infos_train.pkl',
data_prefix=data_prefix,
pipeline=train_pipeline,
metainfo=metainfo,
modality=input_modality,
ignore_index=16,
backend_args=backend_args))
val_dataloader = dict(
batch_size=1,
num_workers=1,
persistent_workers=True,
drop_last=False,
sampler=dict(type=DefaultSampler, shuffle=False),
dataset=dict(
type=NuScenesSegDataset,
data_root=data_root,
ann_file='nuscenes_infos_val.pkl',
data_prefix=data_prefix,
pipeline=test_pipeline,
metainfo=metainfo,
modality=input_modality,
ignore_index=16,
test_mode=True,
backend_args=backend_args))
test_dataloader = val_dataloader

val_evaluator = dict(type=SegMetric)
test_evaluator = val_evaluator

vis_backends = [dict(type=LocalVisBackend)]
visualizer = dict(
type=Det3DLocalVisualizer, vis_backends=vis_backends, name='visualizer')

tta_model = dict(type=Seg3DTTAModel)
34 changes: 34 additions & 0 deletions mmdet3d/configs/_base_/schedules/lidarseg_50e.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) OpenMMLab. All rights reserved.
from mmengine.optim.optimizer.optimizer_wrapper import OptimWrapper
from mmengine.optim.scheduler.lr_scheduler import OneCycleLR
from mmengine.runner.loops import EpochBasedTrainLoop, TestLoop, ValLoop
from torch.optim.adamw import AdamW

# training schedule for 50e
train_cfg = dict(type=EpochBasedTrainLoop, max_epochs=50, val_interval=1)
val_cfg = dict(type=ValLoop)
test_cfg = dict(type=TestLoop)

# learning rate
lr = 0.01
param_scheduler = [
dict(
type=OneCycleLR,
eta_max=lr,
pct_start=0.2,
div_factor=25.0,
final_div_factor=100.0,
by_epoch=False)
]

# optimizer
optim_wrapper = dict(
type=OptimWrapper,
optimizer=dict(
type=AdamW, lr=lr, betas=(0.9, 0.999), weight_decay=0.01, eps=1e-6))

# Default setting for scaling LR automatically
# - `enable` means enable scaling LR automatically
# or not by default.
# - `base_batch_size` = (8 GPUs) x (2 samples per GPU).
auto_scale_lr = dict(enable=False, base_batch_size=16)
34 changes: 34 additions & 0 deletions mmdet3d/configs/_base_/schedules/lidarseg_80e.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) OpenMMLab. All rights reserved.
from mmengine.optim.optimizer.optimizer_wrapper import OptimWrapper
from mmengine.optim.scheduler.lr_scheduler import OneCycleLR
from mmengine.runner.loops import EpochBasedTrainLoop, TestLoop, ValLoop
from torch.optim.adamw import AdamW

# training schedule for 80e
train_cfg = dict(type=EpochBasedTrainLoop, max_epochs=80, val_interval=1)
val_cfg = dict(type=ValLoop)
test_cfg = dict(type=TestLoop)

# learning rate
lr = 0.01
param_scheduler = [
dict(
type=OneCycleLR,
eta_max=lr,
pct_start=0.2,
div_factor=25.0,
final_div_factor=100.0,
by_epoch=False)
]

# optimizer
optim_wrapper = dict(
type=OptimWrapper,
optimizer=dict(
type=AdamW, lr=lr, betas=(0.9, 0.999), weight_decay=0.01, eps=1e-6))

# Default setting for scaling LR automatically
# - `enable` means enable scaling LR automatically
# or not by default.
# - `base_batch_size` = (8 GPUs) x (2 samples per GPU).
auto_scale_lr = dict(enable=False, base_batch_size=16)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright (c) OpenMMLab. All rights reserved.
from mmengine import read_base

with read_base():
from .._base_.datasets.semantickitti import *
from .._base_.models.cylinder3d import *
from .._base_.schedules.lidarseg_50e import *
from .._base_.default_runtime import *

from mmengine.hooks.checkpoint_hook import CheckpointHook
from mmengine.visualization.vis_backend import LocalVisBackend, WandbVisBackend

visualizer.update(
dict(vis_backends=[dict(type=LocalVisBackend),
dict(type=WandbVisBackend)]))
default_hooks.update(
dict(checkpoint=dict(type=CheckpointHook, save_best='miou')))
23 changes: 23 additions & 0 deletions mmdet3d/configs/lidarseg_benchmark/cylinder3d_8xb2_80e_nus_seg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (c) OpenMMLab. All rights reserved.
from mmengine import read_base

with read_base():
from .._base_.datasets.nus_seg import *
from .._base_.models.cylinder3d import *
from .._base_.schedules.lidarseg_80e import *
from .._base_.default_runtime import *

from mmengine.hooks.checkpoint_hook import CheckpointHook
from mmengine.visualization.vis_backend import LocalVisBackend, WandbVisBackend

model.update(dict(decode_head=dict(num_classes=17, ignore_index=16)))

train_dataloader.update(
dict(dataset=dict(ann_file='nuscenes_lidarseg_infos_train.pkl')))
test_dataloader.update(
dict(dataset=dict(ann_file='nuscenes_lidarseg_infos_val.pkl')))
visualizer.update(
dict(vis_backends=[dict(type=LocalVisBackend),
dict(type=WandbVisBackend)]))
default_hooks.update(
dict(checkpoint=dict(type=CheckpointHook, save_best='miou')))
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) OpenMMLab. All rights reserved.
from mmengine import read_base

with read_base():
from .cylinder3d_8xb2_50e_semantickitti import *

optim_wrapper.update(dict(type='AmpOptimWrapper', loss_scale='dynamic'))
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) OpenMMLab. All rights reserved.
from mmengine import read_base

with read_base():
from .cylinder3d_8xb2_80e_nus_seg import *

optim_wrapper.update(dict(type='AmpOptimWrapper', loss_scale='dynamic'))
Loading

0 comments on commit 4ba030a

Please sign in to comment.