Commit 41b18fd8 authored by zhe chen's avatar zhe chen
Browse files

Use pre-commit to reformat code


Use pre-commit to reformat code
parent ff20ea39
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
# --------------------------------------------- # ---------------------------------------------
# Modified by Xiaoyu Tian # Modified by Xiaoyu Tian
# --------------------------------------------- # ---------------------------------------------
from data_converter.create_gt_database import create_groundtruth_database import argparse
import sys
from os import path as osp
from data_converter import nuscenes_converter as nuscenes_converter from data_converter import nuscenes_converter as nuscenes_converter
from data_converter import nuscenes_occ_converter as occ_converter from data_converter import nuscenes_occ_converter as occ_converter
import argparse
from os import path as osp
import sys
sys.path.append('.') sys.path.append('.')
...@@ -55,13 +55,13 @@ def nuscenes_data_prep(root_path, ...@@ -55,13 +55,13 @@ def nuscenes_data_prep(root_path,
def occ_nuscenes_data_prep(root_path, def occ_nuscenes_data_prep(root_path,
occ_path, occ_path,
can_bus_root_path, can_bus_root_path,
info_prefix, info_prefix,
version, version,
dataset_name, dataset_name,
out_dir, out_dir,
max_sweeps=10): max_sweeps=10):
"""Prepare occ data related to nuScenes dataset. """Prepare occ data related to nuScenes dataset.
Related data consists of '.pkl' files recording basic infos, Related data consists of '.pkl' files recording basic infos,
...@@ -76,28 +76,7 @@ def occ_nuscenes_data_prep(root_path, ...@@ -76,28 +76,7 @@ def occ_nuscenes_data_prep(root_path,
max_sweeps (int): Number of input consecutive frames. Default: 10 max_sweeps (int): Number of input consecutive frames. Default: 10
""" """
occ_converter.create_nuscenes_occ_infos( occ_converter.create_nuscenes_occ_infos(
root_path, occ_path,out_dir, can_bus_root_path, info_prefix, version=version, max_sweeps=max_sweeps) root_path, occ_path, out_dir, can_bus_root_path, info_prefix, version=version, max_sweeps=max_sweeps)
# if version == 'v1.0-test':
# info_test_path = osp.join(
# out_dir, f'{info_prefix}_infos_temporal_test.pkl')
# nuscenes_converter.export_2d_annotation(
# root_path, info_test_path, version=version)
# else:
# info_train_path = osp.join(
# out_dir, f'{info_prefix}_infos_temporal_train.pkl')
# info_val_path = osp.join(
# out_dir, f'{info_prefix}_infos_temporal_val.pkl')
# nuscenes_converter.export_2d_annotation(
# root_path, info_train_path, version=version)
# nuscenes_converter.export_2d_annotation(
# root_path, info_val_path, version=version)
# create_groundtruth_database(dataset_name, root_path, info_prefix,
# f'{out_dir}/{info_prefix}_infos_train.pkl')
parser = argparse.ArgumentParser(description='Data converter arg parser') parser = argparse.ArgumentParser(description='Data converter arg parser')
...@@ -161,7 +140,6 @@ if __name__ == '__main__': ...@@ -161,7 +140,6 @@ if __name__ == '__main__':
out_dir=args.out_dir, out_dir=args.out_dir,
max_sweeps=args.max_sweeps) max_sweeps=args.max_sweeps)
elif args.dataset == 'nuscenes' and args.version == 'v1.0-mini': elif args.dataset == 'nuscenes' and args.version == 'v1.0-mini':
train_version = f'{args.version}' train_version = f'{args.version}'
nuscenes_data_prep( nuscenes_data_prep(
...@@ -203,4 +181,3 @@ if __name__ == '__main__': ...@@ -203,4 +181,3 @@ if __name__ == '__main__':
dataset_name='NuScenesDataset', dataset_name='NuScenesDataset',
out_dir=args.out_dir, out_dir=args.out_dir,
max_sweeps=args.max_sweeps) max_sweeps=args.max_sweeps)
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import pickle
from os import path as osp
import mmcv import mmcv
import numpy as np import numpy as np
import pickle
from mmcv import track_iter_progress from mmcv import track_iter_progress
from mmcv.ops import roi_align from mmcv.ops import roi_align
from os import path as osp
from pycocotools import mask as maskUtils
from pycocotools.coco import COCO
from mmdet3d.core.bbox import box_np_ops as box_np_ops from mmdet3d.core.bbox import box_np_ops as box_np_ops
from mmdet3d.datasets import build_dataset from mmdet3d.datasets import build_dataset
from mmdet.core.evaluation.bbox_overlaps import bbox_overlaps from mmdet.core.evaluation.bbox_overlaps import bbox_overlaps
from pycocotools import mask as maskUtils
from pycocotools.coco import COCO
def _poly2mask(mask_ann, img_h, img_w): def _poly2mask(mask_ann, img_h, img_w):
......
...@@ -3,19 +3,19 @@ ...@@ -3,19 +3,19 @@
# --------------------------------------------- # ---------------------------------------------
# Modified by Xiaoyu Tian # Modified by Xiaoyu Tian
# --------------------------------------------- # ---------------------------------------------
import mmcv
import numpy as np
import os import os
from collections import OrderedDict from collections import OrderedDict
from nuscenes.nuscenes import NuScenes
from nuscenes.utils.geometry_utils import view_points
from os import path as osp from os import path as osp
from pyquaternion import Quaternion
from shapely.geometry import MultiPoint, box
from typing import List, Tuple, Union from typing import List, Tuple, Union
import mmcv
import numpy as np
from mmdet3d.core.bbox.box_np_ops import points_cam2img from mmdet3d.core.bbox.box_np_ops import points_cam2img
from mmdet3d.datasets import NuScenesDataset from mmdet3d.datasets import NuScenesDataset
from nuscenes.nuscenes import NuScenes
from nuscenes.utils.geometry_utils import view_points
from pyquaternion import Quaternion
from shapely.geometry import MultiPoint, box
nus_categories = ('car', 'truck', 'trailer', 'bus', 'construction_vehicle', nus_categories = ('car', 'truck', 'trailer', 'bus', 'construction_vehicle',
'bicycle', 'motorcycle', 'pedestrian', 'traffic_cone', 'bicycle', 'motorcycle', 'pedestrian', 'traffic_cone',
...@@ -45,8 +45,8 @@ def create_nuscenes_infos(root_path, ...@@ -45,8 +45,8 @@ def create_nuscenes_infos(root_path,
max_sweeps (int): Max number of sweeps. max_sweeps (int): Max number of sweeps.
Default: 10 Default: 10
""" """
from nuscenes.nuscenes import NuScenes
from nuscenes.can_bus.can_bus_api import NuScenesCanBus from nuscenes.can_bus.can_bus_api import NuScenesCanBus
from nuscenes.nuscenes import NuScenes
print(version, root_path) print(version, root_path)
nusc = NuScenes(version=version, dataroot=root_path, verbose=True) nusc = NuScenes(version=version, dataroot=root_path, verbose=True)
nusc_can_bus = NuScenesCanBus(dataroot=can_bus_root_path) nusc_can_bus = NuScenesCanBus(dataroot=can_bus_root_path)
...@@ -369,9 +369,9 @@ def obtain_sensor2top(nusc, ...@@ -369,9 +369,9 @@ def obtain_sensor2top(nusc,
l2e_r_s_mat = Quaternion(l2e_r_s).rotation_matrix l2e_r_s_mat = Quaternion(l2e_r_s).rotation_matrix
e2g_r_s_mat = Quaternion(e2g_r_s).rotation_matrix e2g_r_s_mat = Quaternion(e2g_r_s).rotation_matrix
R = (l2e_r_s_mat.T @ e2g_r_s_mat.T) @ ( R = (l2e_r_s_mat.T @ e2g_r_s_mat.T) @ (
np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T) np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T)
T = (l2e_t_s @ e2g_r_s_mat.T + e2g_t_s) @ ( T = (l2e_t_s @ e2g_r_s_mat.T + e2g_t_s) @ (
np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T) np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T)
T -= e2g_t @ (np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T T -= e2g_t @ (np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T
) + l2e_t @ np.linalg.inv(l2e_r_mat).T ) + l2e_t @ np.linalg.inv(l2e_r_mat).T
sweep['sensor2lidar_rotation'] = R.T # points @ R.T + T sweep['sensor2lidar_rotation'] = R.T # points @ R.T + T
...@@ -464,8 +464,8 @@ def get_2d_boxes(nusc, ...@@ -464,8 +464,8 @@ def get_2d_boxes(nusc,
sd_rec = nusc.get('sample_data', sample_data_token) sd_rec = nusc.get('sample_data', sample_data_token)
assert sd_rec[ assert sd_rec[
'sensor_modality'] == 'camera', 'Error: get_2d_boxes only works' \ 'sensor_modality'] == 'camera', 'Error: get_2d_boxes only works' \
' for camera sample_data!' ' for camera sample_data!'
if not sd_rec['is_key_frame']: if not sd_rec['is_key_frame']:
raise ValueError( raise ValueError(
'The 2D re-projections are available only for keyframes.') 'The 2D re-projections are available only for keyframes.')
...@@ -576,7 +576,7 @@ def get_2d_boxes(nusc, ...@@ -576,7 +576,7 @@ def get_2d_boxes(nusc,
def post_process_coords( def post_process_coords(
corner_coords: List, imsize: Tuple[int, int] = (1600, 900) corner_coords: List, imsize: Tuple[int, int] = (1600, 900)
) -> Union[Tuple[float, float, float, float], None]: ) -> Union[Tuple[float, float, float, float], None]:
"""Get the intersection of the convex hull of the reprojected bbox corners """Get the intersection of the convex hull of the reprojected bbox corners
and the image canvas, return None if no intersection. and the image canvas, return None if no intersection.
......
...@@ -3,20 +3,20 @@ ...@@ -3,20 +3,20 @@
# --------------------------------------------- # ---------------------------------------------
# Modified by Xiaoyu Tian # Modified by Xiaoyu Tian
# --------------------------------------------- # ---------------------------------------------
import mmcv
import numpy as np
import os import os
from collections import OrderedDict from collections import OrderedDict
from nuscenes.nuscenes import NuScenes
from nuscenes.utils.geometry_utils import view_points
from os import path as osp from os import path as osp
from pyquaternion import Quaternion
from shapely.geometry import MultiPoint, box
from typing import List, Tuple, Union from typing import List, Tuple, Union
import mmcv
import numpy as np
import simplejson as json
from mmdet3d.core.bbox.box_np_ops import points_cam2img from mmdet3d.core.bbox.box_np_ops import points_cam2img
from mmdet3d.datasets import NuScenesDataset from mmdet3d.datasets import NuScenesDataset
import simplejson as json from nuscenes.nuscenes import NuScenes
from nuscenes.utils.geometry_utils import view_points
from pyquaternion import Quaternion
from shapely.geometry import MultiPoint, box
nus_categories = ('car', 'truck', 'trailer', 'bus', 'construction_vehicle', nus_categories = ('car', 'truck', 'trailer', 'bus', 'construction_vehicle',
'bicycle', 'motorcycle', 'pedestrian', 'traffic_cone', 'bicycle', 'motorcycle', 'pedestrian', 'traffic_cone',
...@@ -29,12 +29,12 @@ nus_attributes = ('cycle.with_rider', 'cycle.without_rider', ...@@ -29,12 +29,12 @@ nus_attributes = ('cycle.with_rider', 'cycle.without_rider',
def create_nuscenes_occ_infos(root_path, def create_nuscenes_occ_infos(root_path,
occ_path, occ_path,
out_path, out_path,
can_bus_root_path, can_bus_root_path,
info_prefix, info_prefix,
version='v1.0-trainval', version='v1.0-trainval',
max_sweeps=10): max_sweeps=10):
"""Create info file of nuscene dataset. """Create info file of nuscene dataset.
Given the raw data, generate its related info file in pkl format. Given the raw data, generate its related info file in pkl format.
...@@ -48,8 +48,8 @@ def create_nuscenes_occ_infos(root_path, ...@@ -48,8 +48,8 @@ def create_nuscenes_occ_infos(root_path,
Default: 10 Default: 10
""" """
from nuscenes.nuscenes import NuScenes
from nuscenes.can_bus.can_bus_api import NuScenesCanBus from nuscenes.can_bus.can_bus_api import NuScenesCanBus
from nuscenes.nuscenes import NuScenes
print(version, root_path) print(version, root_path)
nusc = NuScenes(version=version, dataroot=root_path, verbose=True) nusc = NuScenes(version=version, dataroot=root_path, verbose=True)
nusc_can_bus = NuScenesCanBus(dataroot=can_bus_root_path) nusc_can_bus = NuScenesCanBus(dataroot=can_bus_root_path)
...@@ -58,7 +58,7 @@ def create_nuscenes_occ_infos(root_path, ...@@ -58,7 +58,7 @@ def create_nuscenes_occ_infos(root_path,
available_vers = ['v1.0-trainval', 'v1.0-test', 'v1.0-mini'] available_vers = ['v1.0-trainval', 'v1.0-test', 'v1.0-mini']
assert version in available_vers assert version in available_vers
with open(os.path.join(occ_path,'annotations.json'),'r') as f: with open(os.path.join(occ_path, 'annotations.json'), 'r') as f:
occ_anno = json.load(f) occ_anno = json.load(f)
if version == 'v1.0-trainval': if version == 'v1.0-trainval':
...@@ -89,8 +89,7 @@ def create_nuscenes_occ_infos(root_path, ...@@ -89,8 +89,7 @@ def create_nuscenes_occ_infos(root_path,
]) ])
token2name = dict() token2name = dict()
for scene in nusc.scene: for scene in nusc.scene:
token2name[scene['token']]=scene['name'] token2name[scene['token']] = scene['name']
test = 'test' in version test = 'test' in version
if test: if test:
...@@ -100,7 +99,7 @@ def create_nuscenes_occ_infos(root_path, ...@@ -100,7 +99,7 @@ def create_nuscenes_occ_infos(root_path,
len(train_scenes), len(val_scenes))) len(train_scenes), len(val_scenes)))
train_nusc_infos, val_nusc_infos = _fill_occ_trainval_infos( train_nusc_infos, val_nusc_infos = _fill_occ_trainval_infos(
nusc,occ_anno,token2name, nusc_can_bus, train_scenes, val_scenes, test, max_sweeps=max_sweeps) nusc, occ_anno, token2name, nusc_can_bus, train_scenes, val_scenes, test, max_sweeps=max_sweeps)
metadata = dict(version=version) metadata = dict(version=version)
if test: if test:
...@@ -189,13 +188,13 @@ def _get_can_bus_info(nusc, nusc_can_bus, sample): ...@@ -189,13 +188,13 @@ def _get_can_bus_info(nusc, nusc_can_bus, sample):
def _fill_occ_trainval_infos(nusc, def _fill_occ_trainval_infos(nusc,
occ_anno, occ_anno,
token2name, token2name,
nusc_can_bus, nusc_can_bus,
train_scenes, train_scenes,
val_scenes, val_scenes,
test=False, test=False,
max_sweeps=10): max_sweeps=10):
"""Generate the train/val infos from the raw data. """Generate the train/val infos from the raw data.
Args: Args:
...@@ -213,20 +212,18 @@ def _fill_occ_trainval_infos(nusc, ...@@ -213,20 +212,18 @@ def _fill_occ_trainval_infos(nusc,
train_nusc_infos = [] train_nusc_infos = []
val_nusc_infos = [] val_nusc_infos = []
frame_idx = 0 frame_idx = 0
scene_infos=occ_anno['scene_infos'] scene_infos = occ_anno['scene_infos']
for sample in mmcv.track_iter_progress(nusc.sample): for sample in mmcv.track_iter_progress(nusc.sample):
lidar_token = sample['data']['LIDAR_TOP'] lidar_token = sample['data']['LIDAR_TOP']
sd_rec = nusc.get('sample_data', sample['data']['LIDAR_TOP']) sd_rec = nusc.get('sample_data', sample['data']['LIDAR_TOP'])
scene_token = sample['scene_token'] scene_token = sample['scene_token']
scene_name = token2name[scene_token] scene_name = token2name[scene_token]
sample_token=sd_rec['sample_token'] sample_token = sd_rec['sample_token']
if sample_token in scene_infos[scene_name].keys(): if sample_token in scene_infos[scene_name].keys():
occ_sample=scene_infos[scene_name][sample_token] occ_sample = scene_infos[scene_name][sample_token]
else: else:
continue continue
...@@ -397,9 +394,9 @@ def obtain_sensor2top(nusc, ...@@ -397,9 +394,9 @@ def obtain_sensor2top(nusc,
l2e_r_s_mat = Quaternion(l2e_r_s).rotation_matrix l2e_r_s_mat = Quaternion(l2e_r_s).rotation_matrix
e2g_r_s_mat = Quaternion(e2g_r_s).rotation_matrix e2g_r_s_mat = Quaternion(e2g_r_s).rotation_matrix
R = (l2e_r_s_mat.T @ e2g_r_s_mat.T) @ ( R = (l2e_r_s_mat.T @ e2g_r_s_mat.T) @ (
np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T) np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T)
T = (l2e_t_s @ e2g_r_s_mat.T + e2g_t_s) @ ( T = (l2e_t_s @ e2g_r_s_mat.T + e2g_t_s) @ (
np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T) np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T)
T -= e2g_t @ (np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T T -= e2g_t @ (np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T
) + l2e_t @ np.linalg.inv(l2e_r_mat).T ) + l2e_t @ np.linalg.inv(l2e_r_mat).T
sweep['sensor2lidar_rotation'] = R.T # points @ R.T + T sweep['sensor2lidar_rotation'] = R.T # points @ R.T + T
...@@ -492,8 +489,8 @@ def get_2d_boxes(nusc, ...@@ -492,8 +489,8 @@ def get_2d_boxes(nusc,
sd_rec = nusc.get('sample_data', sample_data_token) sd_rec = nusc.get('sample_data', sample_data_token)
assert sd_rec[ assert sd_rec[
'sensor_modality'] == 'camera', 'Error: get_2d_boxes only works' \ 'sensor_modality'] == 'camera', 'Error: get_2d_boxes only works' \
' for camera sample_data!' ' for camera sample_data!'
if not sd_rec['is_key_frame']: if not sd_rec['is_key_frame']:
raise ValueError( raise ValueError(
'The 2D re-projections are available only for keyframes.') 'The 2D re-projections are available only for keyframes.')
...@@ -604,7 +601,7 @@ def get_2d_boxes(nusc, ...@@ -604,7 +601,7 @@ def get_2d_boxes(nusc,
def post_process_coords( def post_process_coords(
corner_coords: List, imsize: Tuple[int, int] = (1600, 900) corner_coords: List, imsize: Tuple[int, int] = (1600, 900)
) -> Union[Tuple[float, float, float, float], None]: ) -> Union[Tuple[float, float, float, float], None]:
"""Get the intersection of the convex hull of the reprojected bbox corners """Get the intersection of the convex hull of the reprojected bbox corners
and the image canvas, return None if no intersection. and the image canvas, return None if no intersection.
......
...@@ -17,4 +17,4 @@ python -m torch.distributed.launch \ ...@@ -17,4 +17,4 @@ python -m torch.distributed.launch \
$(dirname "$0")/train.py \ $(dirname "$0")/train.py \
$CONFIG \ $CONFIG \
--deterministic \ --deterministic \
--launcher pytorch ${@:3} --launcher pytorch ${@:3}
\ No newline at end of file
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
from __future__ import division from __future__ import division
import argparse import argparse
import copy import copy
import mmcv import os
import os import time
import time import warnings
import torch from os import path as osp
import warnings
from mmcv import Config, DictAction import mmcv
from mmcv.runner import get_dist_info, init_dist, wrap_fp16_model import torch
from os import path as osp from mmcv import Config, DictAction
from mmcv.runner import get_dist_info, init_dist, wrap_fp16_model
from mmdet import __version__ as mmdet_version from mmcv.utils import TORCH_VERSION, digit_version
from mmdet3d import __version__ as mmdet3d_version from mmdet import __version__ as mmdet_version
#from mmdet3d.apis import train_model from mmdet3d import __version__ as mmdet3d_version
from mmdet3d.models import build_model
from mmdet3d.datasets import build_dataset from mmdet3d.utils import collect_env, get_root_logger
from mmdet3d.models import build_model from mmdet.apis import set_random_seed
from mmdet3d.utils import collect_env, get_root_logger from mmseg import __version__ as mmseg_version
from mmdet.apis import set_random_seed
from mmseg import __version__ as mmseg_version # from mmdet3d.apis import train_model
from mmcv.utils import TORCH_VERSION, digit_version
def parse_args():
def parse_args(): parser = argparse.ArgumentParser(description='Train a detector')
parser = argparse.ArgumentParser(description='Train a detector') parser.add_argument('config', help='train config file path')
parser.add_argument('config', help='train config file path') parser.add_argument('--work-dir', help='the dir to save logs and models')
parser.add_argument('--work-dir', help='the dir to save logs and models') parser.add_argument(
parser.add_argument( '--resume-from', help='the checkpoint file to resume from')
'--resume-from', help='the checkpoint file to resume from') parser.add_argument(
parser.add_argument( '--no-validate',
'--no-validate', action='store_true',
action='store_true', help='whether not to evaluate the checkpoint during training')
help='whether not to evaluate the checkpoint during training') group_gpus = parser.add_mutually_exclusive_group()
group_gpus = parser.add_mutually_exclusive_group() group_gpus.add_argument(
group_gpus.add_argument( '--gpus',
'--gpus', type=int,
type=int, help='number of gpus to use '
help='number of gpus to use ' '(only applicable to non-distributed training)')
'(only applicable to non-distributed training)') group_gpus.add_argument(
group_gpus.add_argument( '--gpu-ids',
'--gpu-ids', type=int,
type=int, nargs='+',
nargs='+', help='ids of gpus to use '
help='ids of gpus to use ' '(only applicable to non-distributed training)')
'(only applicable to non-distributed training)') parser.add_argument('--seed', type=int, default=0, help='random seed')
parser.add_argument('--seed', type=int, default=0, help='random seed') parser.add_argument(
parser.add_argument( '--deterministic',
'--deterministic', action='store_true',
action='store_true', help='whether to set deterministic options for CUDNN backend.')
help='whether to set deterministic options for CUDNN backend.') parser.add_argument(
parser.add_argument( '--options',
'--options', nargs='+',
nargs='+', action=DictAction,
action=DictAction, help='override some settings in the used config, the key-value pair '
help='override some settings in the used config, the key-value pair ' 'in xxx=yyy format will be merged into config file (deprecate), '
'in xxx=yyy format will be merged into config file (deprecate), ' 'change to --cfg-options instead.')
'change to --cfg-options instead.') parser.add_argument(
parser.add_argument( '--cfg-options',
'--cfg-options', nargs='+',
nargs='+', action=DictAction,
action=DictAction, help='override some settings in the used config, the key-value pair '
help='override some settings in the used config, the key-value pair ' 'in xxx=yyy format will be merged into config file. If the value to '
'in xxx=yyy format will be merged into config file. If the value to ' 'be overwritten is a list, it should be like key="[a,b]" or key=a,b '
'be overwritten is a list, it should be like key="[a,b]" or key=a,b ' 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" '
'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ' 'Note that the quotation marks are necessary and that no white space '
'Note that the quotation marks are necessary and that no white space ' 'is allowed.')
'is allowed.') parser.add_argument(
parser.add_argument( '--launcher',
'--launcher', choices=['none', 'pytorch', 'slurm', 'mpi'],
choices=['none', 'pytorch', 'slurm', 'mpi'], default='none',
default='none', help='job launcher')
help='job launcher') parser.add_argument('--local_rank', type=int, default=0)
parser.add_argument('--local_rank', type=int, default=0) parser.add_argument(
parser.add_argument( '--autoscale-lr',
'--autoscale-lr', action='store_true',
action='store_true', help='automatically scale lr with the number of gpus')
help='automatically scale lr with the number of gpus') args = parser.parse_args()
args = parser.parse_args() if 'LOCAL_RANK' not in os.environ:
if 'LOCAL_RANK' not in os.environ: os.environ['LOCAL_RANK'] = str(args.local_rank)
os.environ['LOCAL_RANK'] = str(args.local_rank)
if args.options and args.cfg_options:
if args.options and args.cfg_options: raise ValueError(
raise ValueError( '--options and --cfg-options cannot be both specified, '
'--options and --cfg-options cannot be both specified, ' '--options is deprecated in favor of --cfg-options')
'--options is deprecated in favor of --cfg-options') if args.options:
if args.options: warnings.warn('--options is deprecated in favor of --cfg-options')
warnings.warn('--options is deprecated in favor of --cfg-options') args.cfg_options = args.options
args.cfg_options = args.options
return args
return args
def main():
def main(): args = parse_args()
args = parse_args()
cfg = Config.fromfile(args.config)
cfg = Config.fromfile(args.config) if args.cfg_options is not None:
if args.cfg_options is not None: cfg.merge_from_dict(args.cfg_options)
cfg.merge_from_dict(args.cfg_options) # import modules from string list.
# import modules from string list. if cfg.get('custom_imports', None):
if cfg.get('custom_imports', None): from mmcv.utils import import_modules_from_strings
from mmcv.utils import import_modules_from_strings import_modules_from_strings(**cfg['custom_imports'])
import_modules_from_strings(**cfg['custom_imports'])
# import modules from plguin/xx, registry will be updated
# import modules from plguin/xx, registry will be updated if hasattr(cfg, 'plugin'):
if hasattr(cfg, 'plugin'): if cfg.plugin:
if cfg.plugin: import importlib
import importlib if hasattr(cfg, 'plugin_dir'):
if hasattr(cfg, 'plugin_dir'): plugin_dir = cfg.plugin_dir
plugin_dir = cfg.plugin_dir _module_dir = os.path.dirname(plugin_dir)
_module_dir = os.path.dirname(plugin_dir) _module_dir = _module_dir.split('/')
_module_dir = _module_dir.split('/') _module_path = _module_dir[0]
_module_path = _module_dir[0]
for m in _module_dir[1:]:
for m in _module_dir[1:]: _module_path = _module_path + '.' + m
_module_path = _module_path + '.' + m print(_module_path)
print(_module_path) plg_lib = importlib.import_module(_module_path)
plg_lib = importlib.import_module(_module_path) else:
else: # import dir is the dirpath for the config file
# import dir is the dirpath for the config file _module_dir = os.path.dirname(args.config)
_module_dir = os.path.dirname(args.config) _module_dir = _module_dir.split('/')
_module_dir = _module_dir.split('/') _module_path = _module_dir[0]
_module_path = _module_dir[0] for m in _module_dir[1:]:
for m in _module_dir[1:]: _module_path = _module_path + '.' + m
_module_path = _module_path + '.' + m print(_module_path)
print(_module_path) plg_lib = importlib.import_module(_module_path)
plg_lib = importlib.import_module(_module_path)
from projects.mmdet3d_plugin.bevformer.apis import \
from projects.mmdet3d_plugin.bevformer.apis import custom_train_model custom_train_model
# set cudnn_benchmark # set cudnn_benchmark
if cfg.get('cudnn_benchmark', False): if cfg.get('cudnn_benchmark', False):
torch.backends.cudnn.benchmark = True torch.backends.cudnn.benchmark = True
# work_dir is determined in this priority: CLI > segment in file > filename # work_dir is determined in this priority: CLI > segment in file > filename
if args.work_dir is not None: if args.work_dir is not None:
# update configs according to CLI args if args.work_dir is not None # update configs according to CLI args if args.work_dir is not None
cfg.work_dir = args.work_dir cfg.work_dir = args.work_dir
elif cfg.get('work_dir', None) is None: elif cfg.get('work_dir', None) is None:
# use config filename as default work_dir if cfg.work_dir is None # use config filename as default work_dir if cfg.work_dir is None
cfg.work_dir = osp.join('./work_dirs', cfg.work_dir = osp.join('./work_dirs',
osp.splitext(osp.basename(args.config))[0]) osp.splitext(osp.basename(args.config))[0])
#if args.resume_from is not None: # if args.resume_from is not None:
if args.resume_from is not None and osp.isfile(args.resume_from): if args.resume_from is not None and osp.isfile(args.resume_from):
cfg.resume_from = args.resume_from cfg.resume_from = args.resume_from
if args.gpu_ids is not None: if args.gpu_ids is not None:
cfg.gpu_ids = args.gpu_ids cfg.gpu_ids = args.gpu_ids
else: else:
cfg.gpu_ids = range(1) if args.gpus is None else range(args.gpus) cfg.gpu_ids = range(1) if args.gpus is None else range(args.gpus)
if digit_version(TORCH_VERSION) != digit_version('1.8.1'): if digit_version(TORCH_VERSION) != digit_version('1.8.1'):
cfg.optimizer['type'] = 'AdamW' cfg.optimizer['type'] = 'AdamW'
if args.autoscale_lr: if args.autoscale_lr:
# apply the linear scaling rule (https://arxiv.org/abs/1706.02677) # apply the linear scaling rule (https://arxiv.org/abs/1706.02677)
cfg.optimizer['lr'] = cfg.optimizer['lr'] * len(cfg.gpu_ids) / 8 cfg.optimizer['lr'] = cfg.optimizer['lr'] * len(cfg.gpu_ids) / 8
# init distributed env first, since logger depends on the dist info. # init distributed env first, since logger depends on the dist info.
if args.launcher == 'none': if args.launcher == 'none':
assert False, 'DOT NOT SUPPORT!!!' assert False, 'DOT NOT SUPPORT!!!'
distributed = False distributed = False
else: else:
distributed = True distributed = True
init_dist(args.launcher, **cfg.dist_params) init_dist(args.launcher, **cfg.dist_params)
# re-set gpu_ids with distributed training mode # re-set gpu_ids with distributed training mode
_, world_size = get_dist_info() _, world_size = get_dist_info()
cfg.gpu_ids = range(world_size) cfg.gpu_ids = range(world_size)
# create work_dir # create work_dir
mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir)) mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir))
# dump config # dump config
cfg.dump(osp.join(cfg.work_dir, osp.basename(args.config))) cfg.dump(osp.join(cfg.work_dir, osp.basename(args.config)))
# init the logger before other steps # init the logger before other steps
timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime())
log_file = osp.join(cfg.work_dir, f'{timestamp}.log') log_file = osp.join(cfg.work_dir, f'{timestamp}.log')
# specify logger name, if we still use 'mmdet', the output info will be # specify logger name, if we still use 'mmdet', the output info will be
# filtered and won't be saved in the log_file # filtered and won't be saved in the log_file
# TODO: ugly workaround to judge whether we are training det or seg model # TODO: ugly workaround to judge whether we are training det or seg model
if cfg.model.type in ['EncoderDecoder3D']: if cfg.model.type in ['EncoderDecoder3D']:
logger_name = 'mmseg' logger_name = 'mmseg'
else: else:
logger_name = 'mmdet' logger_name = 'mmdet'
logger = get_root_logger( logger = get_root_logger(
log_file=log_file, log_level=cfg.log_level, name=logger_name) log_file=log_file, log_level=cfg.log_level, name=logger_name)
# init the meta dict to record some important information such as # init the meta dict to record some important information such as
# environment info and seed, which will be logged # environment info and seed, which will be logged
meta = dict() meta = dict()
# log env info # log env info
env_info_dict = collect_env() env_info_dict = collect_env()
env_info = '\n'.join([(f'{k}: {v}') for k, v in env_info_dict.items()]) env_info = '\n'.join([(f'{k}: {v}') for k, v in env_info_dict.items()])
dash_line = '-' * 60 + '\n' dash_line = '-' * 60 + '\n'
logger.info('Environment info:\n' + dash_line + env_info + '\n' + logger.info('Environment info:\n' + dash_line + env_info + '\n' +
dash_line) dash_line)
meta['env_info'] = env_info meta['env_info'] = env_info
meta['config'] = cfg.pretty_text meta['config'] = cfg.pretty_text
# log some basic info # log some basic info
logger.info(f'Distributed training: {distributed}') logger.info(f'Distributed training: {distributed}')
logger.info(f'Config:\n{cfg.pretty_text}') logger.info(f'Config:\n{cfg.pretty_text}')
# set random seeds # set random seeds
if args.seed is not None: if args.seed is not None:
logger.info(f'Set random seed to {args.seed}, ' logger.info(f'Set random seed to {args.seed}, '
f'deterministic: {args.deterministic}') f'deterministic: {args.deterministic}')
set_random_seed(args.seed, deterministic=args.deterministic) set_random_seed(args.seed, deterministic=args.deterministic)
cfg.seed = args.seed cfg.seed = args.seed
meta['seed'] = args.seed meta['seed'] = args.seed
meta['exp_name'] = osp.basename(args.config) meta['exp_name'] = osp.basename(args.config)
model = build_model( model = build_model(
cfg.model, cfg.model,
train_cfg=cfg.get('train_cfg'), train_cfg=cfg.get('train_cfg'),
test_cfg=cfg.get('test_cfg')) test_cfg=cfg.get('test_cfg'))
model.init_weights() model.init_weights()
eval_model_config = copy.deepcopy(cfg.model) eval_model_config = copy.deepcopy(cfg.model)
eval_model = build_model( eval_model = build_model(
eval_model_config, eval_model_config,
train_cfg=cfg.get('train_cfg'), train_cfg=cfg.get('train_cfg'),
test_cfg=cfg.get('test_cfg')) test_cfg=cfg.get('test_cfg'))
fp16_cfg = cfg.get('fp16', None) fp16_cfg = cfg.get('fp16', None)
if fp16_cfg is not None: if fp16_cfg is not None:
wrap_fp16_model(eval_model) wrap_fp16_model(eval_model)
#eval_model.init_weights() # eval_model.init_weights()
eval_model.load_state_dict(model.state_dict()) eval_model.load_state_dict(model.state_dict())
logger.info(f'Model:\n{model}') logger.info(f'Model:\n{model}')
from projects.mmdet3d_plugin.datasets import custom_build_dataset from projects.mmdet3d_plugin.datasets import custom_build_dataset
datasets = [custom_build_dataset(cfg.data.train)] datasets = [custom_build_dataset(cfg.data.train)]
if len(cfg.workflow) == 2: if len(cfg.workflow) == 2:
val_dataset = copy.deepcopy(cfg.data.val) val_dataset = copy.deepcopy(cfg.data.val)
# in case we use a dataset wrapper # in case we use a dataset wrapper
if 'dataset' in cfg.data.train: if 'dataset' in cfg.data.train:
val_dataset.pipeline = cfg.data.train.dataset.pipeline val_dataset.pipeline = cfg.data.train.dataset.pipeline
else: else:
val_dataset.pipeline = cfg.data.train.pipeline val_dataset.pipeline = cfg.data.train.pipeline
# set test_mode=False here in deep copied config # set test_mode=False here in deep copied config
# which do not affect AP/AR calculation later # which do not affect AP/AR calculation later
# refer to https://mmdetection3d.readthedocs.io/en/latest/tutorials/customize_runtime.html#customize-workflow # noqa # refer to https://mmdetection3d.readthedocs.io/en/latest/tutorials/customize_runtime.html#customize-workflow # noqa
val_dataset.test_mode = False val_dataset.test_mode = False
datasets.append(custom_build_dataset(val_dataset)) datasets.append(custom_build_dataset(val_dataset))
if cfg.checkpoint_config is not None: if cfg.checkpoint_config is not None:
# save mmdet version, config file content and class names in # save mmdet version, config file content and class names in
# checkpoints as meta data # checkpoints as meta data
cfg.checkpoint_config.meta = dict( cfg.checkpoint_config.meta = dict(
mmdet_version=mmdet_version, mmdet_version=mmdet_version,
mmseg_version=mmseg_version, mmseg_version=mmseg_version,
mmdet3d_version=mmdet3d_version, mmdet3d_version=mmdet3d_version,
config=cfg.pretty_text, config=cfg.pretty_text,
CLASSES=datasets[0].CLASSES, CLASSES=datasets[0].CLASSES,
PALETTE=datasets[0].PALETTE # for segmentors PALETTE=datasets[0].PALETTE # for segmentors
if hasattr(datasets[0], 'PALETTE') else None) if hasattr(datasets[0], 'PALETTE') else None)
# add an attribute for visualization convenience # add an attribute for visualization convenience
model.CLASSES = datasets[0].CLASSES model.CLASSES = datasets[0].CLASSES
custom_train_model( custom_train_model(
model, model,
datasets, datasets,
cfg, cfg,
eval_model=eval_model, eval_model=eval_model,
distributed=distributed, distributed=distributed,
validate=(not args.no_validate), validate=(not args.no_validate),
timestamp=timestamp, timestamp=timestamp,
meta=meta) meta=meta)
if __name__ == '__main__': if __name__ == '__main__':
main() main()
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import argparse import argparse
import numpy as np
import warnings import warnings
from mmcv import Config, DictAction, mkdir_or_exist, track_iter_progress
from os import path as osp from os import path as osp
import numpy as np
from mmcv import Config, DictAction, mkdir_or_exist, track_iter_progress
from mmdet3d.core.bbox import (Box3DMode, CameraInstance3DBoxes, Coord3DMode, from mmdet3d.core.bbox import (Box3DMode, CameraInstance3DBoxes, Coord3DMode,
DepthInstance3DBoxes, LiDARInstance3DBoxes) DepthInstance3DBoxes, LiDARInstance3DBoxes)
from mmdet3d.core.visualizer import (show_multi_modality_result, show_result, from mmdet3d.core.visualizer import (show_multi_modality_result, show_result,
...@@ -35,17 +35,17 @@ def parse_args(): ...@@ -35,17 +35,17 @@ def parse_args():
'--online', '--online',
action='store_true', action='store_true',
help='Whether to perform online visualization. Note that you often ' help='Whether to perform online visualization. Note that you often '
'need a monitor to do so.') 'need a monitor to do so.')
parser.add_argument( parser.add_argument(
'--cfg-options', '--cfg-options',
nargs='+', nargs='+',
action=DictAction, action=DictAction,
help='override some settings in the used config, the key-value pair ' help='override some settings in the used config, the key-value pair '
'in xxx=yyy format will be merged into config file. If the value to ' 'in xxx=yyy format will be merged into config file. If the value to '
'be overwritten is a list, it should be like key="[a,b]" or key=a,b ' 'be overwritten is a list, it should be like key="[a,b]" or key=a,b '
'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ' 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" '
'Note that the quotation marks are necessary and that no white space ' 'Note that the quotation marks are necessary and that no white space '
'is allowed.') 'is allowed.')
args = parser.parse_args() args = parser.parse_args()
return args return args
...@@ -203,8 +203,8 @@ def main(): ...@@ -203,8 +203,8 @@ def main():
if dataset_type in ['KittiDataset', 'WaymoDataset']: if dataset_type in ['KittiDataset', 'WaymoDataset']:
data_path = data_info['point_cloud']['velodyne_path'] data_path = data_info['point_cloud']['velodyne_path']
elif dataset_type in [ elif dataset_type in [
'ScanNetDataset', 'SUNRGBDDataset', 'ScanNetSegDataset', 'ScanNetDataset', 'SUNRGBDDataset', 'ScanNetSegDataset',
'S3DISSegDataset', 'S3DISDataset' 'S3DISSegDataset', 'S3DISDataset'
]: ]:
data_path = data_info['pts_path'] data_path = data_info['pts_path']
elif dataset_type in ['NuScenesDataset', 'LyftDataset']: elif dataset_type in ['NuScenesDataset', 'LyftDataset']:
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import argparse import argparse
import torch import torch
from mmcv.runner import save_checkpoint from mmcv.runner import save_checkpoint
from torch import nn as nn
from mmdet.apis import init_model from mmdet.apis import init_model
from torch import nn as nn
def fuse_conv_bn(conv, bn): def fuse_conv_bn(conv, bn):
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import argparse import argparse
from mmcv import Config, DictAction from mmcv import Config, DictAction
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import argparse import argparse
import mmcv import mmcv
from mmcv import Config from mmcv import Config
from mmdet3d.datasets import build_dataset from mmdet3d.datasets import build_dataset
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import argparse import argparse
import tempfile import tempfile
import torch import torch
from mmcv import Config from mmcv import Config
from mmcv.runner import load_state_dict from mmcv.runner import load_state_dict
from mmdet3d.models import build_detector from mmdet3d.models import build_detector
...@@ -104,13 +104,13 @@ def main(): ...@@ -104,13 +104,13 @@ def main():
EXTRACT_KEYS = { EXTRACT_KEYS = {
'bbox_head.conv_pred.conv_cls.weight': 'bbox_head.conv_pred.conv_cls.weight':
('bbox_head.conv_pred.conv_out.weight', [(0, 2), (-NUM_CLASSES, -1)]), ('bbox_head.conv_pred.conv_out.weight', [(0, 2), (-NUM_CLASSES, -1)]),
'bbox_head.conv_pred.conv_cls.bias': 'bbox_head.conv_pred.conv_cls.bias':
('bbox_head.conv_pred.conv_out.bias', [(0, 2), (-NUM_CLASSES, -1)]), ('bbox_head.conv_pred.conv_out.bias', [(0, 2), (-NUM_CLASSES, -1)]),
'bbox_head.conv_pred.conv_reg.weight': 'bbox_head.conv_pred.conv_reg.weight':
('bbox_head.conv_pred.conv_out.weight', [(2, -NUM_CLASSES)]), ('bbox_head.conv_pred.conv_out.weight', [(2, -NUM_CLASSES)]),
'bbox_head.conv_pred.conv_reg.bias': 'bbox_head.conv_pred.conv_reg.bias':
('bbox_head.conv_pred.conv_out.bias', [(2, -NUM_CLASSES)]) ('bbox_head.conv_pred.conv_out.bias', [(2, -NUM_CLASSES)])
} }
# Delete some useless keys # Delete some useless keys
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import argparse import argparse
import subprocess import subprocess
import torch import torch
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
import argparse import argparse
import torch
from collections import OrderedDict from collections import OrderedDict
import torch
def convert_stem(model_key, model_weight, state_dict, converted_names): def convert_stem(model_key, model_weight, state_dict, converted_names):
new_key = model_key.replace('stem.conv', 'conv1') new_key = model_key.replace('stem.conv', 'conv1')
......
...@@ -4,24 +4,23 @@ ...@@ -4,24 +4,23 @@
# Modified by Xiaoyu Tian # Modified by Xiaoyu Tian
# --------------------------------------------- # ---------------------------------------------
import argparse import argparse
import mmcv
import os import os
import sys import os.path as osp
import torch import time
import warnings import warnings
import torch
from mmcv import Config, DictAction from mmcv import Config, DictAction
from mmcv.cnn import fuse_conv_bn from mmcv.cnn import fuse_conv_bn
from mmcv.parallel import MMDataParallel, MMDistributedDataParallel from mmcv.parallel import MMDistributedDataParallel
from mmcv.runner import (get_dist_info, init_dist, load_checkpoint, from mmcv.runner import (get_dist_info, init_dist, load_checkpoint,
wrap_fp16_model) wrap_fp16_model)
from mmdet3d.datasets import build_dataset from mmdet3d.datasets import build_dataset
from projects.mmdet3d_plugin.datasets.builder import build_dataloader
from mmdet3d.models import build_model from mmdet3d.models import build_model
from mmdet.apis import set_random_seed from mmdet.apis import set_random_seed
from projects.mmdet3d_plugin.bevformer.apis.test import custom_multi_gpu_test
from mmdet.datasets import replace_ImageToTensor from mmdet.datasets import replace_ImageToTensor
import time from projects.mmdet3d_plugin.bevformer.apis.test import custom_multi_gpu_test
import os.path as osp from projects.mmdet3d_plugin.datasets.builder import build_dataloader
def parse_args(): def parse_args():
...@@ -38,19 +37,19 @@ def parse_args(): ...@@ -38,19 +37,19 @@ def parse_args():
'--fuse-conv-bn', '--fuse-conv-bn',
action='store_true', action='store_true',
help='Whether to fuse conv and bn, this will slightly increase' help='Whether to fuse conv and bn, this will slightly increase'
'the inference speed') 'the inference speed')
parser.add_argument( parser.add_argument(
'--format-only', '--format-only',
action='store_true', action='store_true',
help='Format the output results without perform evaluation. It is' help='Format the output results without perform evaluation. It is'
'useful when you want to format the result to a specific format and ' 'useful when you want to format the result to a specific format and '
'submit it to the test server') 'submit it to the test server')
parser.add_argument( parser.add_argument(
'--eval', '--eval',
type=str, type=str,
nargs='+', nargs='+',
help='evaluation metrics, which depends on the dataset, e.g., "bbox",' help='evaluation metrics, which depends on the dataset, e.g., "bbox",'
' "segm", "proposal" for COCO, and "mAP", "recall" for PASCAL VOC') ' "segm", "proposal" for COCO, and "mAP", "recall" for PASCAL VOC')
parser.add_argument('--show', action='store_true', help='show results') parser.add_argument('--show', action='store_true', help='show results')
parser.add_argument( parser.add_argument(
'--show-dir', help='directory where results will be saved') '--show-dir', help='directory where results will be saved')
...@@ -61,7 +60,7 @@ def parse_args(): ...@@ -61,7 +60,7 @@ def parse_args():
parser.add_argument( parser.add_argument(
'--tmpdir', '--tmpdir',
help='tmp directory used for collecting results from multiple ' help='tmp directory used for collecting results from multiple '
'workers, available when gpu-collect is not specified') 'workers, available when gpu-collect is not specified')
parser.add_argument('--seed', type=int, default=0, help='random seed') parser.add_argument('--seed', type=int, default=0, help='random seed')
parser.add_argument( parser.add_argument(
'--deterministic', '--deterministic',
...@@ -72,24 +71,24 @@ def parse_args(): ...@@ -72,24 +71,24 @@ def parse_args():
nargs='+', nargs='+',
action=DictAction, action=DictAction,
help='override some settings in the used config, the key-value pair ' help='override some settings in the used config, the key-value pair '
'in xxx=yyy format will be merged into config file. If the value to ' 'in xxx=yyy format will be merged into config file. If the value to '
'be overwritten is a list, it should be like key="[a,b]" or key=a,b ' 'be overwritten is a list, it should be like key="[a,b]" or key=a,b '
'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ' 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" '
'Note that the quotation marks are necessary and that no white space ' 'Note that the quotation marks are necessary and that no white space '
'is allowed.') 'is allowed.')
parser.add_argument( parser.add_argument(
'--options', '--options',
nargs='+', nargs='+',
action=DictAction, action=DictAction,
help='custom options for evaluation, the key-value pair in xxx=yyy ' help='custom options for evaluation, the key-value pair in xxx=yyy '
'format will be kwargs for dataset.evaluate() function (deprecate), ' 'format will be kwargs for dataset.evaluate() function (deprecate), '
'change to --eval-options instead.') 'change to --eval-options instead.')
parser.add_argument( parser.add_argument(
'--eval-options', '--eval-options',
nargs='+', nargs='+',
action=DictAction, action=DictAction,
help='custom options for evaluation, the key-value pair in xxx=yyy ' help='custom options for evaluation, the key-value pair in xxx=yyy '
'format will be kwargs for dataset.evaluate() function') 'format will be kwargs for dataset.evaluate() function')
parser.add_argument( parser.add_argument(
'--launcher', '--launcher',
choices=['none', 'pytorch', 'slurm', 'mpi'], choices=['none', 'pytorch', 'slurm', 'mpi'],
...@@ -193,7 +192,7 @@ def main(): ...@@ -193,7 +192,7 @@ def main():
# build the dataloader # build the dataloader
dataset = build_dataset(cfg.data.test) dataset = build_dataset(cfg.data.test)
if args.eval_fscore: if args.eval_fscore:
dataset.eval_fscore=True dataset.eval_fscore = True
data_loader = build_dataloader( data_loader = build_dataloader(
dataset, dataset,
samples_per_gpu=samples_per_gpu, samples_per_gpu=samples_per_gpu,
...@@ -242,7 +241,7 @@ def main(): ...@@ -242,7 +241,7 @@ def main():
if args.out: if args.out:
print(f'\nwriting results to {args.out}') print(f'\nwriting results to {args.out}')
assert False assert False
#mmcv.dump(outputs['bbox_results'], args.out) # mmcv.dump(outputs['bbox_results'], args.out)
kwargs = {} if args.eval_options is None else args.eval_options kwargs = {} if args.eval_options is None else args.eval_options
kwargs['jsonfile_prefix'] = osp.join('test', args.config.split( kwargs['jsonfile_prefix'] = osp.join('test', args.config.split(
'/')[-1].split('.')[-2], time.ctime().replace(' ', '_').replace(':', '_')) '/')[-1].split('.')[-2], time.ctime().replace(' ', '_').replace(':', '_'))
...@@ -253,13 +252,13 @@ def main(): ...@@ -253,13 +252,13 @@ def main():
eval_kwargs = cfg.get('evaluation', {}).copy() eval_kwargs = cfg.get('evaluation', {}).copy()
# hard-code way to remove EvalHook args # hard-code way to remove EvalHook args
for key in [ for key in [
'interval', 'tmpdir', 'start', 'gpu_collect', 'save_best', 'interval', 'tmpdir', 'start', 'gpu_collect', 'save_best',
'rule','begin','end' 'rule', 'begin', 'end'
]: ]:
eval_kwargs.pop(key, None) eval_kwargs.pop(key, None)
eval_kwargs.update(dict(metric=args.eval, **kwargs)) eval_kwargs.update(dict(metric=args.eval, **kwargs))
dataset.evaluate_miou(outputs,show_dir=args.show_dir, **eval_kwargs) dataset.evaluate_miou(outputs, show_dir=args.show_dir, **eval_kwargs)
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -3,31 +3,30 @@ ...@@ -3,31 +3,30 @@
# --------------------------------------------- # ---------------------------------------------
# Modified by Zhiqi Li # Modified by Zhiqi Li
# --------------------------------------------- # ---------------------------------------------
from __future__ import division from __future__ import division
import argparse import argparse
import copy import copy
import mmcv
import os import os
import time import time
import torch
import warnings import warnings
from mmcv import Config, DictAction
from mmcv.runner import get_dist_info, init_dist
from os import path as osp from os import path as osp
import mmcv
import torch
from mmcv import Config, DictAction
from mmcv.runner import get_dist_info, init_dist
from mmcv.utils import TORCH_VERSION, digit_version
from mmdet import __version__ as mmdet_version from mmdet import __version__ as mmdet_version
from mmdet3d import __version__ as mmdet3d_version from mmdet3d import __version__ as mmdet3d_version
#from mmdet3d.apis import train_model
from mmdet3d.datasets import build_dataset from mmdet3d.datasets import build_dataset
from mmdet3d.models import build_model from mmdet3d.models import build_model
from mmdet3d.utils import collect_env, get_root_logger from mmdet3d.utils import collect_env, get_root_logger
from mmdet.apis import set_random_seed from mmdet.apis import set_random_seed
from mmseg import __version__ as mmseg_version from mmseg import __version__ as mmseg_version
from mmcv.utils import TORCH_VERSION, digit_version # from mmdet3d.apis import train_model
def parse_args(): def parse_args():
...@@ -45,13 +44,13 @@ def parse_args(): ...@@ -45,13 +44,13 @@ def parse_args():
'--gpus', '--gpus',
type=int, type=int,
help='number of gpus to use ' help='number of gpus to use '
'(only applicable to non-distributed training)') '(only applicable to non-distributed training)')
group_gpus.add_argument( group_gpus.add_argument(
'--gpu-ids', '--gpu-ids',
type=int, type=int,
nargs='+', nargs='+',
help='ids of gpus to use ' help='ids of gpus to use '
'(only applicable to non-distributed training)') '(only applicable to non-distributed training)')
parser.add_argument('--seed', type=int, default=0, help='random seed') parser.add_argument('--seed', type=int, default=0, help='random seed')
parser.add_argument( parser.add_argument(
'--deterministic', '--deterministic',
...@@ -62,18 +61,18 @@ def parse_args(): ...@@ -62,18 +61,18 @@ def parse_args():
nargs='+', nargs='+',
action=DictAction, action=DictAction,
help='override some settings in the used config, the key-value pair ' help='override some settings in the used config, the key-value pair '
'in xxx=yyy format will be merged into config file (deprecate), ' 'in xxx=yyy format will be merged into config file (deprecate), '
'change to --cfg-options instead.') 'change to --cfg-options instead.')
parser.add_argument( parser.add_argument(
'--cfg-options', '--cfg-options',
nargs='+', nargs='+',
action=DictAction, action=DictAction,
help='override some settings in the used config, the key-value pair ' help='override some settings in the used config, the key-value pair '
'in xxx=yyy format will be merged into config file. If the value to ' 'in xxx=yyy format will be merged into config file. If the value to '
'be overwritten is a list, it should be like key="[a,b]" or key=a,b ' 'be overwritten is a list, it should be like key="[a,b]" or key=a,b '
'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ' 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" '
'Note that the quotation marks are necessary and that no white space ' 'Note that the quotation marks are necessary and that no white space '
'is allowed.') 'is allowed.')
parser.add_argument( parser.add_argument(
'--launcher', '--launcher',
choices=['none', 'pytorch', 'slurm', 'mpi'], choices=['none', 'pytorch', 'slurm', 'mpi'],
...@@ -134,7 +133,8 @@ def main(): ...@@ -134,7 +133,8 @@ def main():
print(_module_path) print(_module_path)
plg_lib = importlib.import_module(_module_path) plg_lib = importlib.import_module(_module_path)
from projects.mmdet3d_plugin.bevformer.apis.train import custom_train_model from projects.mmdet3d_plugin.bevformer.apis.train import \
custom_train_model
# set cudnn_benchmark # set cudnn_benchmark
if cfg.get('cudnn_benchmark', False): if cfg.get('cudnn_benchmark', False):
torch.backends.cudnn.benchmark = True torch.backends.cudnn.benchmark = True
...@@ -155,7 +155,7 @@ def main(): ...@@ -155,7 +155,7 @@ def main():
else: else:
cfg.gpu_ids = range(1) if args.gpus is None else range(args.gpus) cfg.gpu_ids = range(1) if args.gpus is None else range(args.gpus)
if digit_version(TORCH_VERSION) == digit_version('1.8.1') and cfg.optimizer['type'] == 'AdamW': if digit_version(TORCH_VERSION) == digit_version('1.8.1') and cfg.optimizer['type'] == 'AdamW':
cfg.optimizer['type'] = 'AdamW2' # fix bug in Adamw cfg.optimizer['type'] = 'AdamW2' # fix bug in Adamw
if args.autoscale_lr: if args.autoscale_lr:
# apply the linear scaling rule (https://arxiv.org/abs/1706.02677) # apply the linear scaling rule (https://arxiv.org/abs/1706.02677)
cfg.optimizer['lr'] = cfg.optimizer['lr'] * len(cfg.gpu_ids) / 8 cfg.optimizer['lr'] = cfg.optimizer['lr'] * len(cfg.gpu_ids) / 8
......
import open3d as o3d import math
import pickle
import numpy as np import numpy as np
import open3d as o3d
import torch import torch
import math
from pathlib import Path
import os
from glob import glob
LINE_SEGMENTS = [ LINE_SEGMENTS = [
[4, 0], [3, 7], [5, 1], [6, 2], # lines along x-axis [4, 0], [3, 7], [5, 1], [6, 2], # lines along x-axis
[5, 4], [5, 6], [6, 7], [7, 4], # lines along x-axis [5, 4], [5, 6], [6, 7], [7, 4], # lines along x-axis
[0, 1], [1, 2], [2, 3], [3, 0]] # lines along y-axis [0, 1], [1, 2], [2, 3], [3, 0]] # lines along y-axis
colors_map = np.array( colors_map = np.array(
[ [
# [0, 0, 0, 255], # 0 undefined # [0, 0, 0, 255], # 0 undefined
[255, 158, 0, 255], # 1 car orange [255, 158, 0, 255], # 1 car orange
[0, 0, 230, 255], # 2 pedestrian Blue [0, 0, 230, 255], # 2 pedestrian Blue
[47, 79, 79, 255], # 3 sign Darkslategrey [47, 79, 79, 255], # 3 sign Darkslategrey
[220, 20, 60, 255], # 4 CYCLIST Crimson [220, 20, 60, 255], # 4 CYCLIST Crimson
[255, 69, 0, 255], # 5 traiffic_light Orangered [255, 69, 0, 255], # 5 traiffic_light Orangered
[255, 140, 0, 255], # 6 pole Darkorange [255, 140, 0, 255], # 6 pole Darkorange
[233, 150, 70, 255], # 7 construction_cone Darksalmon [233, 150, 70, 255], # 7 construction_cone Darksalmon
[255, 61, 99, 255], # 8 bycycle Red [255, 61, 99, 255], # 8 bycycle Red
[112, 128, 144, 255],# 9 motorcycle Slategrey [112, 128, 144, 255], # 9 motorcycle Slategrey
[222, 184, 135, 255],# 10 building Burlywood [222, 184, 135, 255], # 10 building Burlywood
[0, 175, 0, 255], # 11 vegetation Green [0, 175, 0, 255], # 11 vegetation Green
[165, 42, 42, 255], # 12 trunk nuTonomy green [165, 42, 42, 255], # 12 trunk nuTonomy green
[0, 207, 191, 255], # 13 curb, road, lane_marker, other_ground [0, 207, 191, 255], # 13 curb, road, lane_marker, other_ground
[75, 0, 75, 255], # 14 walkable, sidewalk [75, 0, 75, 255], # 14 walkable, sidewalk
[255, 0, 0, 255], # 15 unobsrvd [255, 0, 0, 255], # 15 unobsrvd
]) ])
color = colors_map[:, :3] / 255 color = colors_map[:, :3] / 255
...@@ -48,42 +46,46 @@ def voxel2points(voxel, voxelSize, range=[-40.0, -40.0, -1.0, 40.0, 40.0, 5.4], ...@@ -48,42 +46,46 @@ def voxel2points(voxel, voxelSize, range=[-40.0, -40.0, -1.0, 40.0, 40.0, 5.4],
occIdx[2][:, None] * voxelSize[2] + voxelSize[2] / 2 + range[2]), dim=1) occIdx[2][:, None] * voxelSize[2] + voxelSize[2] / 2 + range[2]), dim=1)
return points, voxel[occIdx] return points, voxel[occIdx]
def voxel_profile(voxel, voxel_size): def voxel_profile(voxel, voxel_size):
centers = torch.cat((voxel[:, :2], voxel[:, 2][:, None] - voxel_size[2] / 2), dim=1) centers = torch.cat((voxel[:, :2], voxel[:, 2][:, None] - voxel_size[2] / 2), dim=1)
# centers = voxel # centers = voxel
wlh = torch.cat((torch.tensor(voxel_size[0]).repeat(centers.shape[0])[:, None], wlh = torch.cat((torch.tensor(voxel_size[0]).repeat(centers.shape[0])[:, None],
torch.tensor(voxel_size[1]).repeat(centers.shape[0])[:, None], torch.tensor(voxel_size[1]).repeat(centers.shape[0])[:, None],
torch.tensor(voxel_size[2]).repeat(centers.shape[0])[:, None]), dim=1) torch.tensor(voxel_size[2]).repeat(centers.shape[0])[:, None]), dim=1)
yaw = torch.full_like(centers[:, 0:1], 0) yaw = torch.full_like(centers[:, 0:1], 0)
return torch.cat((centers, wlh, yaw), dim=1) return torch.cat((centers, wlh, yaw), dim=1)
def rotz(t): def rotz(t):
"""Rotation about the z-axis.""" """Rotation about the z-axis."""
c = torch.cos(t) c = torch.cos(t)
s = torch.sin(t) s = torch.sin(t)
return torch.tensor([[c, -s, 0], return torch.tensor([[c, -s, 0],
[s, c, 0], [s, c, 0],
[0, 0, 1]]) [0, 0, 1]])
def my_compute_box_3d(center, size, heading_angle): def my_compute_box_3d(center, size, heading_angle):
h, w, l = size[:, 2], size[:, 0], size[:, 1] h, w, l = size[:, 2], size[:, 0], size[:, 1]
heading_angle = -heading_angle - math.pi / 2 heading_angle = -heading_angle - math.pi / 2
center[:, 2] = center[:, 2] + h / 2 center[:, 2] = center[:, 2] + h / 2
#R = rotz(1 * heading_angle) # R = rotz(1 * heading_angle)
l, w, h = (l / 2).unsqueeze(1), (w / 2).unsqueeze(1), (h / 2).unsqueeze(1) l, w, h = (l / 2).unsqueeze(1), (w / 2).unsqueeze(1), (h / 2).unsqueeze(1)
x_corners = torch.cat([-l, l, l, -l, -l, l, l, -l], dim=1)[..., None] x_corners = torch.cat([-l, l, l, -l, -l, l, l, -l], dim=1)[..., None]
y_corners = torch.cat([w, w, -w, -w, w, w, -w, -w], dim=1)[..., None] y_corners = torch.cat([w, w, -w, -w, w, w, -w, -w], dim=1)[..., None]
z_corners = torch.cat([h, h, h, h, -h, -h, -h, -h], dim=1)[..., None] z_corners = torch.cat([h, h, h, h, -h, -h, -h, -h], dim=1)[..., None]
#corners_3d = R @ torch.vstack([x_corners, y_corners, z_corners]) # corners_3d = R @ torch.vstack([x_corners, y_corners, z_corners])
corners_3d = torch.cat([x_corners, y_corners, z_corners], dim=2) corners_3d = torch.cat([x_corners, y_corners, z_corners], dim=2)
corners_3d[..., 0] += center[:, 0:1] corners_3d[..., 0] += center[:, 0:1]
corners_3d[..., 1] += center[:, 1:2] corners_3d[..., 1] += center[:, 1:2]
corners_3d[..., 2] += center[:, 2:3] corners_3d[..., 2] += center[:, 2:3]
return corners_3d return corners_3d
def generate_the_ego_car(): def generate_the_ego_car():
ego_range = [-2, -1, 0, 2, 1, 1.5] ego_range = [-2, -1, 0, 2, 1, 1.5]
ego_voxel_size=[0.1, 0.1, 0.1] ego_voxel_size = [0.1, 0.1, 0.1]
ego_xdim = int((ego_range[3] - ego_range[0]) / ego_voxel_size[0]) ego_xdim = int((ego_range[3] - ego_range[0]) / ego_voxel_size[0])
ego_ydim = int((ego_range[4] - ego_range[1]) / ego_voxel_size[1]) ego_ydim = int((ego_range[4] - ego_range[1]) / ego_voxel_size[1])
ego_zdim = int((ego_range[5] - ego_range[2]) / ego_voxel_size[2]) ego_zdim = int((ego_range[5] - ego_range[2]) / ego_voxel_size[2])
...@@ -96,13 +98,16 @@ def generate_the_ego_car(): ...@@ -96,13 +98,16 @@ def generate_the_ego_car():
ego_point_y = (ego_xyz[:, 1:2] + 0.5) / ego_ydim * (ego_range[4] - ego_range[1]) + ego_range[1] ego_point_y = (ego_xyz[:, 1:2] + 0.5) / ego_ydim * (ego_range[4] - ego_range[1]) + ego_range[1]
ego_point_z = (ego_xyz[:, 2:3] + 0.5) / ego_zdim * (ego_range[5] - ego_range[2]) + ego_range[2] ego_point_z = (ego_xyz[:, 2:3] + 0.5) / ego_zdim * (ego_range[5] - ego_range[2]) + ego_range[2]
ego_point_xyz = np.concatenate((ego_point_y, ego_point_x, ego_point_z), axis=-1) ego_point_xyz = np.concatenate((ego_point_y, ego_point_x, ego_point_z), axis=-1)
ego_points_label = (np.ones((ego_point_xyz.shape[0]))*16).astype(np.uint8) ego_points_label = (np.ones((ego_point_xyz.shape[0])) * 16).astype(np.uint8)
ego_dict = {} ego_dict = {}
ego_dict['point'] = ego_point_xyz ego_dict['point'] = ego_point_xyz
ego_dict['label'] = ego_points_label ego_dict['label'] = ego_points_label
return ego_point_xyz return ego_point_xyz
def show_point_cloud(points: np.ndarray, colors=True, points_colors=None, obj_bboxes=None, voxelize=False, bbox_corners=None, linesets=None, ego_pcd=None, scene_idx=0, frame_idx=0, large_voxel=True, voxel_size=0.4) -> None:
def show_point_cloud(points: np.ndarray, colors=True, points_colors=None, obj_bboxes=None, voxelize=False,
bbox_corners=None, linesets=None, ego_pcd=None, scene_idx=0, frame_idx=0, large_voxel=True,
voxel_size=0.4) -> None:
vis = o3d.visualization.VisualizerWithKeyCallback() vis = o3d.visualization.VisualizerWithKeyCallback()
vis.create_window(str(scene_idx)) vis.create_window(str(scene_idx))
...@@ -136,13 +141,14 @@ def show_point_cloud(points: np.ndarray, colors=True, points_colors=None, obj_bb ...@@ -136,13 +141,14 @@ def show_point_cloud(points: np.ndarray, colors=True, points_colors=None, obj_bb
vis.update_renderer() vis.update_renderer()
return vis return vis
def vis_nuscene(): def vis_nuscene():
voxelSize = [0.4, 0.4, 0.4] voxelSize = [0.4, 0.4, 0.4]
point_cloud_range = [-40.0, -40.0, -1.0, 40.0, 40.0, 5.4] point_cloud_range = [-40.0, -40.0, -1.0, 40.0, 40.0, 5.4]
ignore_labels = [17, 255] ignore_labels = [17, 255]
vis_voxel_size = 0.4 vis_voxel_size = 0.4
file = "data/29796060110c4163b07f06eff4af0753/labels.npz" file = 'data/29796060110c4163b07f06eff4af0753/labels.npz'
data = np.load(file) data = np.load(file)
semantics, mask_lidar, mask_camera = data['semantics'], data['mask_lidar'], data['mask_camera'] semantics, mask_lidar, mask_camera = data['semantics'], data['mask_lidar'], data['mask_camera']
...@@ -158,13 +164,15 @@ def vis_nuscene(): ...@@ -158,13 +164,15 @@ def vis_nuscene():
ego_pcd.points = o3d.utility.Vector3dVector(ego_points) ego_pcd.points = o3d.utility.Vector3dVector(ego_points)
bboxes_corners = my_compute_box_3d(bboxes[:, 0:3], bboxes[:, 3:6], bboxes[:, 6:7]) bboxes_corners = my_compute_box_3d(bboxes[:, 0:3], bboxes[:, 3:6], bboxes[:, 6:7])
bases_ = torch.arange(0, bboxes_corners.shape[0] * 8, 8) bases_ = torch.arange(0, bboxes_corners.shape[0] * 8, 8)
edges = torch.tensor([[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6, 7], [7, 4], [0, 4], [1, 5], [2, 6], [3, 7]]) # lines along y-axis edges = torch.tensor([[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6, 7], [7, 4], [0, 4], [1, 5], [2, 6],
[3, 7]]) # lines along y-axis
edges = edges.reshape((1, 12, 2)).repeat(bboxes_corners.shape[0], 1, 1) edges = edges.reshape((1, 12, 2)).repeat(bboxes_corners.shape[0], 1, 1)
edges = edges + bases_[:, None, None] edges = edges + bases_[:, None, None]
vis = show_point_cloud(points=points, colors=True, points_colors=pcd_colors, voxelize=True, obj_bboxes=None, vis = show_point_cloud(points=points, colors=True, points_colors=pcd_colors, voxelize=True, obj_bboxes=None,
bbox_corners=bboxes_corners.numpy(), linesets=edges.numpy(), ego_pcd=ego_pcd, large_voxel=True, voxel_size=vis_voxel_size) bbox_corners=bboxes_corners.numpy(), linesets=edges.numpy(), ego_pcd=ego_pcd,
large_voxel=True, voxel_size=vis_voxel_size)
# control view # control view
# view_control = vis.get_view_control() # view_control = vis.get_view_control()
# view_control.set_zoom(args.zoom) # view_control.set_zoom(args.zoom)
# view_control.set_up(args.up_vec) # view_control.set_up(args.up_vec)
...@@ -179,5 +187,6 @@ def vis_nuscene(): ...@@ -179,5 +187,6 @@ def vis_nuscene():
vis.destroy_window() vis.destroy_window()
del vis del vis
if __name__ == '__main__': if __name__ == '__main__':
vis_nuscene() vis_nuscene()
\ No newline at end of file
<div id="top" align="center"> <div id="top" align="center">
# OpenLane-Huawei # OpenLane-Huawei
**全球首个自动驾驶道路结构感知和推理基准。**
**全球首个自动驾驶道路结构感知和推理基准。**
<a href="#数据">
<img alt="OpenLane-v2: v1.0" src="https://img.shields.io/badge/OpenLane--V2-v1.0-blueviolet"/> <a href="#数据">
</a> <img alt="OpenLane-v2: v1.0" src="https://img.shields.io/badge/OpenLane--V2-v1.0-blueviolet"/>
<a href="#开发工具"> </a>
<img alt="devkit: v0.1.0" src="https://img.shields.io/badge/devkit-v0.1.0-blueviolet"/> <a href="#开发工具">
</a> <img alt="devkit: v0.1.0" src="https://img.shields.io/badge/devkit-v0.1.0-blueviolet"/>
<a href="#许可说明"> </a>
<img alt="License: Apache2.0" src="https://img.shields.io/badge/license-Apache%202.0-blue.svg"/> <a href="#许可说明">
</a> <img alt="License: Apache2.0" src="https://img.shields.io/badge/license-Apache%202.0-blue.svg"/>
</a>
**中文 | [English](./README.md)**
**中文 | [English](./README.md)**
<img src="./imgs/poster.gif" width="696px"> <img src="./imgs/poster.gif" width="696px">
</div> </div>
## 目录
## 目录
- [关键](#特色---我们为什么是独一无二的)
- [关键](#特色---我们为什么是独一无二的) - [任务](#任务)
- [任务](#任务) - [3D车道线检测🛣️](#3d车道线检测-%EF%B8%8F)
- [3D车道线检测🛣️](#3d车道线检测-%EF%B8%8F) - [交通标志检测🚥](#交通标志检测-)
- [交通标志检测🚥](#交通标志检测-) - [拓扑认知🕸️](#拓扑认知-%EF%B8%8F)
- [拓扑认知🕸️](#拓扑认知-%EF%B8%8F) - [信息发布](#信息发布)
- [信息发布](#信息发布) - [数据](#数据)
- [数据](#数据) - [开发工具](#开发工具)
- [开发工具](#开发工具) - [入门指南](#入门指南)
- [入门指南](#入门指南) - [训练模型](#训练模型)
- [训练模型](#训练模型) - [基准和排行榜](#基准和排行榜)
- [基准和排行榜](#基准和排行榜) - [引用](#引用)
- [引用](#引用) - [许可说明](#许可说明)
- [许可说明](#许可说明)
## 特色 - 我们为什么是独一无二的?
## 特色 - 我们为什么是独一无二的?
### 三维场景,3D车道 ### 三维场景,3D车道
道路环境需要怎样的建模才能满足车辆自动驾驶功能的需求? 道路环境需要怎样的建模才能满足车辆自动驾驶功能的需求?
以往的数据集一般都在2D图像上标注车道,但在实际应用中,由于缺乏高度信息,2D车道数据无法支持车辆在上下坡、路面不平整等场景行驶,因此**3D车道**数据是不可或缺的。 以往的数据集一般都在2D图像上标注车道,但在实际应用中,由于缺乏高度信息,2D车道数据无法支持车辆在上下坡、路面不平整等场景行驶,因此**3D车道**数据是不可或缺的。
同我们之前的工作 [OpenLane](https://github.com/OpenDriveLab/OpenLane) 一致,OpenLane-Huawei 提供三维车道标注。 同我们之前的工作 [OpenLane](https://github.com/OpenDriveLab/OpenLane) 一致,OpenLane-Huawei 提供三维车道标注。
### 关注交通要素,确保行车规范
在道路上平稳的行驶只是第一步,驾驶汽车还需要遵循环境中的**交通要素**(交通灯,路标)信息指示,确保不违反当地交通法规,因此 OpenLane-Huawei 也提供了2D交通要素标注。 ### 关注交通要素,确保行车规范
交通要素在2D图像上尺寸大多都较小,检测领域中小目标检测一直是个热点,这也是该基准的挑战之一。 在道路上平稳的行驶只是第一步,驾驶汽车还需要遵循环境中的**交通要素**(交通灯,路标)信息指示,确保不违反当地交通法规,因此 OpenLane-Huawei 也提供了2D交通要素标注。
### 拓扑关系支撑场景结构化 交通要素在2D图像上尺寸大多都较小,检测领域中小目标检测一直是个热点,这也是该基准的挑战之一。
环境中交通要素应仅对其特定的车道有指示作用,遵循错误的信号将造成灾难性的后果,因此需要明确车道与交通要素的关系。环境中的车道也不应是割裂存在的,车道与车道的关系也同样重要。
### 拓扑关系支撑场景结构化
OpenLane-Huawei 提供车道与车道、车道与交通要素之间的拓扑关系,打造结构化场景。
环境中交通要素应仅对其特定的车道有指示作用,遵循错误的信号将造成灾难性的后果,因此需要明确车道与交通要素的关系。环境中的车道也不应是割裂存在的,车道与车道的关系也同样重要。
自动驾驶汽车需要通过**推理**捕捉正确的**拓扑关系**以正确的方式行驶。
我们希望这个数据集的建立可以促进**道路场景感知和推理**任务的发展。 OpenLane-Huawei 提供车道与车道、车道与交通要素之间的拓扑关系,打造结构化场景。
### 多元大规模数据,搭建超赞数据集 自动驾驶汽车需要通过**推理**捕捉正确的**拓扑关系**以正确的方式行驶。 我们希望这个数据集的建立可以促进**道路场景感知和推理**任务的发展。
对于机器学习任务,数据是必备的基石。
我们提供从奥斯汀到新加坡,从波士顿到迈阿密等各个城市收集的数据的标注, ### 多元大规模数据,搭建超赞数据集
支撑数据的**多元性**
对于机器学习任务,数据是必备的基石。 我们提供从奥斯汀到新加坡,从波士顿到迈阿密等各个城市收集的数据的标注, 支撑数据的**多元性**
<p align="right">(<a href="#top">回到顶部</a>)</p>
<p align="right">(<a href="#top">回到顶部</a>)</p>
## 任务 ## 任务
数据集的首要任务是**场景结构感知和推理**,这需要模型能够识别周围环境中车道的可行驶状态。 数据集的首要任务是**场景结构感知和推理**,这需要模型能够识别周围环境中车道的可行驶状态。 该数据集的任务不仅包括车道中心线和交通要素检测,还包括检测到的对象的拓扑关系识别。 我们定义了[**OpenLane-V2 Score (
该数据集的任务不仅包括车道中心线和交通要素检测,还包括检测到的对象的拓扑关系识别。 OLS)**](./docs/metrics.md#openlane-v2-score),该指标为各个子任务指标的平均值:
我们定义了[**OpenLane-V2 Score (OLS)**](./docs/metrics.md#openlane-v2-score),该指标为各个子任务指标的平均值:
$$ \\text{OLS} = \\frac{1}{4} \\bigg\[ \\text{DET}_{l} + \\text{DET}_{t} + f(\\text{TOP}_{ll}) + f(\\text{TOP}_{lt})
$$ \\bigg\]. $$
\text{OLS} = \frac{1}{4} \bigg[ \text{DET}_{l} + \text{DET}_{t} + f(\text{TOP}_{ll}) + f(\text{TOP}_{lt}) \bigg].
$$ 子任务的指标如下所述:
子任务的指标如下所述: ### 3D车道线检测 🛣️
### 3D车道线检测 🛣️ [OpenLane](https://github.com/OpenDriveLab/OpenLane) 数据集是迄今为止第一个真实世界和规模最大的 3D 车道数据集,提供 3D 空间下的车道线标注。 在OpenLane基础上,我们将 3D
车道检测的任务定义如下:从覆盖整个水平 FOV(视场角-Field Of View) 的多视图中检测带方向的 3D 车道中心线。 用平均精度 $mAP\_{LC}$ 指标评估车道中心线的检测性能。
[OpenLane](https://github.com/OpenDriveLab/OpenLane) 数据集是迄今为止第一个真实世界和规模最大的 3D 车道数据集,提供 3D 空间下的车道线标注。
在OpenLane基础上,我们将 3D 车道检测的任务定义如下:从覆盖整个水平 FOV(视场角-Field Of View) 的多视图中检测带方向的 3D 车道中心线。 <p align="center">
用平均精度 $mAP_{LC}$ 指标评估车道中心线的检测性能。 <img src="./imgs/lane.gif" width="696px" >
</p>
<p align="center">
<img src="./imgs/lane.gif" width="696px" > ### 交通标志检测 🚥
</p>
现有的数据集很少关注交通标志的检测及其语义,但是交通标志是自动驾驶汽车中关键信息。 该属性表示交通要素的语义,例如交通灯的红色。 在这个子任务中,在给定的前视图图像上,要求同时感知交通要素(交通灯和路标)的位置及其属性。 与典型的 2D
### 交通标志检测 🚥 检测数据集相比,挑战在于由于室外环境的大规模,交通要素的尺寸很小。 与典型的多分类 2D 检测任务类似, $mAP\_{TE}$ 用于衡量交通要素 (TE)综合的检测性能。
现有的数据集很少关注交通标志的检测及其语义,但是交通标志是自动驾驶汽车中关键信息。 <p align="center">
该属性表示交通要素的语义,例如交通灯的红色。 <img src="./imgs/traffic_element.gif" width="696px" >
在这个子任务中,在给定的前视图图像上,要求同时感知交通要素(交通灯和路标)的位置及其属性。 </p>
与典型的 2D 检测数据集相比,挑战在于由于室外环境的大规模,交通要素的尺寸很小。
与典型的多分类 2D 检测任务类似, $mAP_{TE}$ 用于衡量交通要素 (TE)综合的检测性能。 ### 拓扑认知 🕸️
我们首先定义在自动驾驶领域识别拓扑关系的任务。 给定多视图图像,该模型学习识别车道中心线之间以及车道中心线与交通要素之间的拓扑关系。 最相似的任务是图领域的连通性预测,其中顶点是给定的,模型只预测边。
<p align="center"> 在我们的例子中,模型的顶点和边都是未知的。 因此,首先需要检测车道中心线和交通要素,然后建立拓扑关系。 参照连通性预测任务, 我们用 $mAP\_{LCLC}$ 评估车道中心线(LCLC)之间的拓扑表现, 用 $mAP\_{LCTE}$
<img src="./imgs/traffic_element.gif" width="696px" > 评估车道中心线和交通要素(LCTE)之间的拓扑表现。
</p>
<p align="center">
<img src="./imgs/topology.gif" width="696px" >
### 拓扑认知 🕸️ </p>
我们首先定义在自动驾驶领域识别拓扑关系的任务。
给定多视图图像,该模型学习识别车道中心线之间以及车道中心线与交通要素之间的拓扑关系。 <p align="right">(<a href="#top">回到顶部</a>)</p>
最相似的任务是图领域的连通性预测,其中顶点是给定的,模型只预测边。
在我们的例子中,模型的顶点和边都是未知的。 ## 信息发布
因此,首先需要检测车道中心线和交通要素,然后建立拓扑关系。
参照连通性预测任务, - \[2023/02\]
我们用 $mAP_{LCLC}$ 评估车道中心线(LCLC)之间的拓扑表现, - 数据集 `v1.0`: `subset_A` 数据发布。
用 $mAP_{LCTE}$ 评估车道中心线和交通要素(LCTE)之间的拓扑表现。 - 基模型发布。
- \[2023/01\]
<p align="center"> - 数据集 `v0.1`: OpenLane-Huawei 数据集样本发布。
<img src="./imgs/topology.gif" width="696px" > - 开发工具 `v0.1.0`: OpenLane-Huawei 开发工具发布。
</p>
<p align="right">(<a href="#top">回到顶部</a>)</p>
<p align="right">(<a href="#top">回到顶部</a>)</p>
## 数据
OpenLane-Huawei 数据集是自动驾驶领域用于道路结构感知和推理的大规模数据集。 与 [OpenLane](https://github.com/OpenDriveLab/OpenLane)
数据集一致,我们提供三维空间中的车道真值。与之有区别的是,OpenLane-Huawei 提供的是车道中心线的3D标注,而OpenLane提供的是车道分割线3D标注。此外,我们还提供了交通标志(交通灯和路标)
## 信息发布 及其属性的2D框标注,和车道中心线之间以及车道中心线与交通要素之间的拓扑关系标注。
- [2023/02]
* 数据集 `v1.0`: `subset_A` 数据发布。 数据集分为两个子集。
* 基模型发布。 **`subset_A`作为主要子集,服务于即将到来的比赛和排行榜,比赛中不允许任何外部数据,包括本数据集其他子集**
- [2023/01] `subset_B`可以用来测试模型的泛化能力。 更多信息请参考对应的页面:[使用数据](./data/README.md)[标注文档](./docs/annotation.md)[数据统计](./docs/statistics.md)
* 数据集 `v0.1`: OpenLane-Huawei 数据集样本发布。
* 开发工具 `v0.1.0`: OpenLane-Huawei 开发工具发布。
现在就[下载](./data/README.md#download)我们的数据集来发现更多!
<p align="right">(<a href="#top">回到顶部</a>)</p>
<p align="right">(<a href="#top">回到顶部</a>)</p>
## 数据 ## 开发工具
OpenLane-Huawei 数据集是自动驾驶领域用于道路结构感知和推理的大规模数据集。 我们提供了一个开发工具来方便社区熟悉并使用 OpenLane-Huawei 数据集。 可以通过 `openlanv2` 的API实现数据集的使用,例如加载图像、加载元数据和评估结果。
[OpenLane](https://github.com/OpenDriveLab/OpenLane) 数据集一致,我们提供三维空间中的车道真值。与之有区别的是,OpenLane-Huawei 提供的是车道中心线的3D标注,而OpenLane提供的是车道分割线3D标注。此外,我们还提供了交通标志(交通灯和路标)及其属性的2D框标注,和车道中心线之间以及车道中心线与交通要素之间的拓扑关系标注。 更多开发工具信息请参考[开发工具](./docs/devkit.md)
数据集分为两个子集。 <p align="right">(<a href="#top">回到顶部</a>)</p>
**`subset_A`作为主要子集,服务于即将到来的比赛和排行榜,比赛中不允许任何外部数据,包括本数据集其他子集**
`subset_B`可以用来测试模型的泛化能力。 ## 入门指南
更多信息请参考对应的页面:[使用数据](./data/README.md)[标注文档](./docs/annotation.md)[数据统计](./docs/statistics.md)
按照以下步骤熟悉 OpenLane-Huawei 数据集:
现在就[下载](./data/README.md#download)我们的数据集来发现更多!
1. 运行以下命令安装必要的工具包,完成研究环境准备:
<p align="right">(<a href="#top">回到顶部</a>)</p>
```sh
git clone https://github.com/OpenDriveLab/OpenLane-V2.git
## 开发工具 cd OpenLane-V2
conda create -n openlanev2 python=3.8 -y
我们提供了一个开发工具来方便社区熟悉并使用 OpenLane-Huawei 数据集。 conda activate openlanev2
可以通过 `openlanv2` 的API实现数据集的使用,例如加载图像、加载元数据和评估结果。 pip install -r requirements.txt
更多开发工具信息请参考[开发工具](./docs/devkit.md) python setup.py develop
```
<p align="right">(<a href="#top">回到顶部</a>)</p> 2. 点击[链接](./data/README.md#download)从合适的渠道下载数据:
## 入门指南 - <img src="https://user-images.githubusercontent.com/29263416/222076048-21501bac-71df-40fa-8671-2b5f8013d2cd.png" alt="OpenDataLab" width="18"/> OpenDataLab,
- <img src="https://ssl.gstatic.com/docs/doclist/images/drive_2022q3_32dp.png" alt="Google Drive" width="18"/> Google Drive,
按照以下步骤熟悉 OpenLane-Huawei 数据集: - <img src="https://nd-static.bdstatic.com/m-static/v20-main/favicon-main.ico" alt="百度云" width="18"/> 百度云。
1. 运行以下命令安装必要的工具包,完成研究环境准备: 并将它们移动至 `data/OpenLane-V2/` 文件夹下解压。 生成的目录结构应[如下](./data/README.md#hierarchy)所示。 或者用这些命令来下载数据集样本:
```sh ```sh
git clone https://github.com/OpenDriveLab/OpenLane-V2.git cd data/OpenLane-V2
cd OpenLane-V2 wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=1Ni-L6u1MGKJRAfUXm39PdBIxdk_ntdc6' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=1Ni-L6u1MGKJRAfUXm39PdBIxdk_ntdc6" -O OpenLane-V2_sample.tar
conda create -n openlanev2 python=3.8 -y md5sum -c openlanev2.md5
conda activate openlanev2 tar -xvf *.tar
pip install -r requirements.txt cd ../..
python setup.py develop ```
```
3. 在 jupyter notebook 上运行 [tutorial](./tutorial.ipynb) 来熟悉数据集与对应的开发工具。
2. 点击[链接](./data/README.md#download)从合适的渠道下载数据:
<p align="right">(<a href="#top">回到顶部</a>)</p>
- <img src="https://user-images.githubusercontent.com/29263416/222076048-21501bac-71df-40fa-8671-2b5f8013d2cd.png" alt="OpenDataLab" width="18"/> OpenDataLab,
- <img src="https://ssl.gstatic.com/docs/doclist/images/drive_2022q3_32dp.png" alt="Google Drive" width="18"/> Google Drive, ## 训练模型
- <img src="https://nd-static.bdstatic.com/m-static/v20-main/favicon-main.ico" alt="百度云" width="18"/> 百度云。
我们提供不同神经网络训练框架的插件来支持在我们的数据集上训练模型。 如果缺少你常用的训练框架,我们欢迎你的提议或对插件的共同维护。
并将它们移动至 `data/OpenLane-V2/` 文件夹下解压。
生成的目录结构应[如下](./data/README.md#hierarchy)所示。 ### mmdet3d
或者用这些命令来下载数据集样本:
这个[插件](./plugin/mmdet3d/)
```sh 基于 [mmdet3d v1.0.0rc6](https://github.com/open-mmlab/mmdetection3d/tree/v1.0.0rc6),并且在以下的环境中进行过测试:
cd data/OpenLane-V2
wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=1Ni-L6u1MGKJRAfUXm39PdBIxdk_ntdc6' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=1Ni-L6u1MGKJRAfUXm39PdBIxdk_ntdc6" -O OpenLane-V2_sample.tar - Python 3.8.15
md5sum -c openlanev2.md5 - PyTorch 1.9.1
tar -xvf *.tar - CUDA 11.1
cd ../.. - GCC 5.4.0
``` - mmcv-full==1.5.2
- mmdet==2.26.0
3. 在 jupyter notebook 上运行 [tutorial](./tutorial.ipynb) 来熟悉数据集与对应的开发工具。 - mmsegmentation==0.29.1
请按照 mmdet3d 的[指引](https://github.com/open-mmlab/mmdetection3d/blob/v1.0.0rc6/docs/en/getting_started.md)来安装这个训练框架。
<p align="right">(<a href="#top">回到顶部</a>)</p> 假设这个数据集安装在 `OpenLane-V2/` 目录下,并且 mmdet3d 安装在 `mmdetection3d/` 目录下,你可以通过软连接的方式将该插件引入到训练框架中:
## 训练模型 ```
我们提供不同神经网络训练框架的插件来支持在我们的数据集上训练模型。 └── mmdetection3d
如果缺少你常用的训练框架,我们欢迎你的提议或对插件的共同维护。 └── projects
├── example_project
### mmdet3d └── openlanev2 -> OpenLane-V2/plugin/mmdet3d
```
这个[插件](./plugin/mmdet3d/)基于 [mmdet3d v1.0.0rc6](https://github.com/open-mmlab/mmdetection3d/tree/v1.0.0rc6),并且在以下的环境中进行过测试:
- Python 3.8.15 在将数据路径换成你的本地路径之后,你可以使用我们提供的 config 文件 `mmdetection3d/projects/openlanev2/configs/baseline.py` 来进行模型训练和各种 mmdet3d 中支持的操作。
- PyTorch 1.9.1 并且可以通过在对模型进行推理时输入不同的选项来获取不同的功能,已经实现的功能有:`--eval-options dump=True dump_dir=/PATH/TO/DUMP`
- CUDA 11.1 来存储用于上传测试集结果的文件;`--eval-options visualization=True visualization_dir=/PATH/TO/VIS` 来对模型输出进行可视化。
- GCC 5.4.0
- mmcv-full==1.5.2 <p align="right">(<a href="#top">回到顶部</a>)</p>
- mmdet==2.26.0
- mmsegmentation==0.29.1 ## 基准和排行榜
请按照 mmdet3d 的[指引](https://github.com/open-mmlab/mmdetection3d/blob/v1.0.0rc6/docs/en/getting_started.md)来安装这个训练框架。 我们将提供 OpenLane-Huawei 数据集的初始基准测试,欢迎您在这里添加您的工作!
假设这个数据集安装在 `OpenLane-V2/` 目录下,并且 mmdet3d 安装在 `mmdetection3d/` 目录下,你可以通过软连接的方式将该插件引入到训练框架中: 基准和排行榜将在不久后发布,请持续关注。
```
└── mmdetection3d | Method | OLS (main metric) (%) | $mAP\_{LC}$ (%) | $mAP\_{TE}$ (%) | $mAP\_{LCLC}$ (%) | $mAP\_{LCTE}$ (%) | F-Score\* (%) |
└── projects | -------- | --------------------- | --------------- | --------------- | ----------------- | ----------------- | ------------- |
├── example_project | Baseline | 0.29 | 0.08 | 0.31 | 0.00 | 0.01 | 8.56 |
└── openlanev2 -> OpenLane-V2/plugin/mmdet3d
``` <sub>\*在比赛和排行榜中不考虑车道中心线检测的 F-Score。
在将数据路径换成你的本地路径之后,你可以使用我们提供的 config 文件 `mmdetection3d/projects/openlanev2/configs/baseline.py` 来进行模型训练和各种 mmdet3d 中支持的操作。
并且可以通过在对模型进行推理时输入不同的选项来获取不同的功能,已经实现的功能有:`--eval-options dump=True dump_dir=/PATH/TO/DUMP` 来存储用于上传测试集结果的文件;`--eval-options visualization=True visualization_dir=/PATH/TO/VIS` 来对模型输出进行可视化。 <p align="right">(<a href="#top">回到顶部</a>)</p>
<p align="right">(<a href="#top">回到顶部</a>)</p> ## 引用
## 基准和排行榜 使用 OpenLane-Huawei 时请使用如下引用:
我们将提供 OpenLane-Huawei 数据集的初始基准测试,欢迎您在这里添加您的工作!
基准和排行榜将在不久后发布,请持续关注。 ```bibtex
@misc{ openlanev2_dataset,
| Method | OLS (main metric) (%) | $mAP_{LC}$ (%) | $mAP_{TE}$ (%) | $mAP_{LCLC}$ (%) | $mAP_{LCTE}$ (%) | F-Score* (%) | author = {{OpenLane-V2 Dataset Contributors}},
| - | - | - | - | - | - | - | title = {{OpenLane-V2: The World's First Perception and Reasoning Benchmark for Scene Structure in Autonomous Driving}},
| Baseline | 0.29 | 0.08 | 0.31 | 0.00 | 0.01 | 8.56 | url = {https://github.com/OpenDriveLab/OpenLane-V2},
license = {Apache-2.0},
<sub>*在比赛和排行榜中不考虑车道中心线检测的 F-Score。 year = {2023}
}
<p align="right">(<a href="#top">回到顶部</a>)</p> ```
我们的数据集是基于[NuScenes](https://www.nuscenes.org/nuscenes)
## 引用 [Argoverse](https://www.argoverse.org/av2.html)数据集工作拓展而来。如果引用本作,也请使用如下引用:
使用 OpenLane-Huawei 时请使用如下引用: ```bibtex
@article{ nuscenes2019,
```bibtex author = {Holger Caesar and Varun Bankiti and Alex H. Lang and Sourabh Vora and Venice Erin Liong and Qiang Xu and Anush Krishnan and Yu Pan and Giancarlo Baldan and Oscar Beijbom},
@misc{ openlanev2_dataset, title = {nuScenes: A multimodal dataset for autonomous driving},
author = {{OpenLane-V2 Dataset Contributors}}, journal = {arXiv preprint arXiv:1903.11027},
title = {{OpenLane-V2: The World's First Perception and Reasoning Benchmark for Scene Structure in Autonomous Driving}}, year = {2019}
url = {https://github.com/OpenDriveLab/OpenLane-V2}, }
license = {Apache-2.0},
year = {2023} @INPROCEEDINGS { Argoverse2,
} author = {Benjamin Wilson and William Qi and Tanmay Agarwal and John Lambert and Jagjeet Singh and Siddhesh Khandelwal and Bowen Pan and Ratnesh Kumar and Andrew Hartnett and Jhony Kaesemodel Pontes and Deva Ramanan and Peter Carr and James Hays},
``` title = {Argoverse 2: Next Generation Datasets for Self-driving Perception and Forecasting},
booktitle = {Proceedings of the Neural Information Processing Systems Track on Datasets and Benchmarks (NeurIPS Datasets and Benchmarks 2021)},
我们的数据集是基于[NuScenes](https://www.nuscenes.org/nuscenes)[Argoverse](https://www.argoverse.org/av2.html)数据集工作拓展而来。如果引用本作,也请使用如下引用: year = {2021}
}
```bibtex ```
@article{ nuscenes2019,
author = {Holger Caesar and Varun Bankiti and Alex H. Lang and Sourabh Vora and Venice Erin Liong and Qiang Xu and Anush Krishnan and Yu Pan and Giancarlo Baldan and Oscar Beijbom}, <p align="right">(<a href="#top">回到顶部</a>)</p>
title = {nuScenes: A multimodal dataset for autonomous driving},
journal = {arXiv preprint arXiv:1903.11027}, ## 许可说明
year = {2019}
} 使用 OpenLane-Huawei 数据集时,您需要在网站上注册并同意 [nuScenes](https://www.nuscenes.org/nuscenes)
[Argoverse 2](https://www.argoverse.org/av2.html) 数据集的使用条款。
@INPROCEEDINGS { Argoverse2,
author = {Benjamin Wilson and William Qi and Tanmay Agarwal and John Lambert and Jagjeet Singh and Siddhesh Khandelwal and Bowen Pan and Ratnesh Kumar and Andrew Hartnett and Jhony Kaesemodel Pontes and Deva Ramanan and Peter Carr and James Hays}, 本项目的发布受 [Apache License 2.0](./LICENSE)许可认证。
title = {Argoverse 2: Next Generation Datasets for Self-driving Perception and Forecasting},
booktitle = {Proceedings of the Neural Information Processing Systems Track on Datasets and Benchmarks (NeurIPS Datasets and Benchmarks 2021)}, <p align="right">(<a href="#top">回到顶部</a>)</p>
year = {2021}
}
```
<p align="right">(<a href="#top">回到顶部</a>)</p>
## 许可说明
使用 OpenLane-Huawei 数据集时,您需要在网站上注册并同意 [nuScenes](https://www.nuscenes.org/nuscenes)[Argoverse 2](https://www.argoverse.org/av2.html) 数据集的使用条款。
本项目的发布受 [Apache License 2.0](./LICENSE)许可认证。
<p align="right">(<a href="#top">回到顶部</a>)</p>
## InternImage-based Baseline for CVPR23 OpenLane-V2 Challenge!!!! ## InternImage-based Baseline for CVPR23 OpenLane-V2 Challenge!!!!
We improve our baseline with a more powerful image backbone: **InternImage**, which shows its excellent ability within a series of leaderboards and benchmarks, such as *COCO* and *nuScenes*. We improve our baseline with a more powerful image backbone: **InternImage**, which shows its excellent ability within a
series of leaderboards and benchmarks, such as *COCO* and *nuScenes*.
#### 1. Requirements #### 1. Requirements
```bash ```bash
python>=3.8 python>=3.8
torch==1.11 torch==1.11
...@@ -13,8 +14,8 @@ mmsegmentation==0.29.1 ...@@ -13,8 +14,8 @@ mmsegmentation==0.29.1
timm timm
``` ```
### 2. Install DCNv3 for InternImage ### 2. Install DCNv3 for InternImage
```bash ```bash
cd plugin/mmdet3d/baseline/models/backbones/ops_dcnv3 cd plugin/mmdet3d/baseline/models/backbones/ops_dcnv3
bash make.sh bash make.sh
...@@ -28,11 +29,10 @@ bash make.sh ...@@ -28,11 +29,10 @@ bash make.sh
Notes: InternImage provides abundant pre-trained model weights that can be used!!! Notes: InternImage provides abundant pre-trained model weights that can be used!!!
### 4. Performance compared to baseline ### 4. Performance compared to baseline
| | OpenLane-V2 Score | DET<sub>l</sub> | DET<sub>t</sub> | TOP<sub>ll</sub> | TOP<sub>lt</sub> | F-Score | | | OpenLane-V2 Score | DET<sub>l</sub> | DET<sub>t</sub> | TOP<sub>ll</sub> | TOP<sub>lt</sub> | F-Score |
|-------------|-------------------|-----------------|-----------------|------------------|------------------|---------| | ----------- | ----------------- | --------------- | --------------- | ---------------- | ---------------- | ------- |
| base r50 | 0.292 | 0.183 | 0.457 | 0.022 | 0.143 | 0.215 | | base r50 | 0.292 | 0.183 | 0.457 | 0.022 | 0.143 | 0.215 |
| InternImage | 0.325 | 0.194 | 0.537 | 0.02 | 0.17 | 0.224 | | InternImage | 0.325 | 0.194 | 0.537 | 0.02 | 0.17 | 0.224 |
...@@ -40,12 +40,14 @@ Notes: InternImage provides abundant pre-trained model weights that can be used! ...@@ -40,12 +40,14 @@ Notes: InternImage provides abundant pre-trained model weights that can be used!
InternImage-S: [download](https://drive.google.com/file/d/1PsyVOEkCdo-q-jxeDKGRjw28_kWWm1d1/view?usp=sharing) InternImage-S: [download](https://drive.google.com/file/d/1PsyVOEkCdo-q-jxeDKGRjw28_kWWm1d1/view?usp=sharing)
## Leaderboard ## Leaderboard
To be released. To be released.
<div id="top" align="center"> <div id="top" align="center">
# OpenLane-V2 # OpenLane-V2
**The World's First Perception and Reasoning Benchmark for Scene Structure in Autonomous Driving.** **The World's First Perception and Reasoning Benchmark for Scene Structure in Autonomous Driving.**
<a href="#data"> <a href="#data">
...@@ -62,7 +64,6 @@ To be released. ...@@ -62,7 +64,6 @@ To be released.
_In terms of ambiguity, the English version shall prevail._ _In terms of ambiguity, the English version shall prevail._
<img src="./imgs/poster.gif" width="696px"> <img src="./imgs/poster.gif" width="696px">
</div> </div>
...@@ -72,6 +73,7 @@ _In terms of ambiguity, the English version shall prevail._ ...@@ -72,6 +73,7 @@ _In terms of ambiguity, the English version shall prevail._
> The dataset name OpenLane-V2, is termed as **RoadGenome** at Huawei. > The dataset name OpenLane-V2, is termed as **RoadGenome** at Huawei.
## Table of Contents ## Table of Contents
- [News](#news) - [News](#news)
- [Benchmark and Leaderboard](#benchmark-and-leaderboard) - [Benchmark and Leaderboard](#benchmark-and-leaderboard)
- [Highlight](#highlight---why-we-are-exclusive) - [Highlight](#highlight---why-we-are-exclusive)
...@@ -87,90 +89,106 @@ _In terms of ambiguity, the English version shall prevail._ ...@@ -87,90 +89,106 @@ _In terms of ambiguity, the English version shall prevail._
- [License](#license) - [License](#license)
## News ## News
- [2023/03]
* We are hosting a Challenge at the [CVPR 2023 Workshop](https://opendrivelab.com/AD23Challenge.html) :star:. - \[2023/03\]
- [2023/02] - We are hosting a Challenge at the [CVPR 2023 Workshop](https://opendrivelab.com/AD23Challenge.html) :star:.
* Dataset `v1.0`: Data of `subset_A` released. - \[2023/02\]
* Baseline model released. - Dataset `v1.0`: Data of `subset_A` released.
- [2023/01] - Baseline model released.
* Dataset `v0.1`: Initial OpenLane-V2 dataset sample released. - \[2023/01\]
* Devkit `v0.1.0`: Initial OpenLane-V2 devkit released. - Dataset `v0.1`: Initial OpenLane-V2 dataset sample released.
- Devkit `v0.1.0`: Initial OpenLane-V2 devkit released.
<p align="right">(<a href="#top">back to top</a>)</p> <p align="right">(<a href="#top">back to top</a>)</p>
## Benchmark and Leaderboard ## Benchmark and Leaderboard
We will provide an initial benchmark on the OpenLane-V2 dataset, please stay tuned for the release.
Currently, we are maintaining leaderboards on the [*val*](https://paperswithcode.com/sota/3d-lane-detection-on-openlane-v2-2) and [*test*](https://eval.ai/web/challenges/challenge-page/1925/leaderboard/4549) split of `subset_A`. We will provide an initial benchmark on the OpenLane-V2 dataset, please stay tuned for the release.
Currently, we are maintaining leaderboards on the [\*
val\*](https://paperswithcode.com/sota/3d-lane-detection-on-openlane-v2-2) and [\*
test\*](https://eval.ai/web/challenges/challenge-page/1925/leaderboard/4549) split of `subset_A`.
<p align="right">(<a href="#top">back to top</a>)</p> <p align="right">(<a href="#top">back to top</a>)</p>
## Highlight - why we are exclusive? ## Highlight - why we are exclusive?
### The world is three-dimensional - Introducing 3D lane ### The world is three-dimensional - Introducing 3D lane
Previous datasets annotate lanes on images in the perspective view. Such a type of 2D annotation is insufficient to fulfill real-world requirements.
Following the [OpenLane](https://github.com/OpenDriveLab/OpenLane) dataset, we annotate **lanes in 3D space** to reflect their properties in the real world. Previous datasets annotate lanes on images in the perspective view. Such a type of 2D annotation is insufficient to
fulfill real-world requirements. Following the [OpenLane](https://github.com/OpenDriveLab/OpenLane) dataset, we
annotate **lanes in 3D space** to reflect their properties in the real world.
### Be aware of traffic signals - Recognizing Extremely Small road elements ### Be aware of traffic signals - Recognizing Extremely Small road elements
Not only preventing collision but also facilitating efficiency is essential.
Vehicles follow predefined traffic rules for self-disciplining and cooperating with others to ensure a safe and efficient traffic system. Not only preventing collision but also facilitating efficiency is essential. Vehicles follow predefined traffic rules
for self-disciplining and cooperating with others to ensure a safe and efficient traffic system.
**Traffic elements** on the roads, such as traffic lights and road signs, provide practical and real-time information. **Traffic elements** on the roads, such as traffic lights and road signs, provide practical and real-time information.
### Beyond perception - Topology Reasoning between lane and road elements ### Beyond perception - Topology Reasoning between lane and road elements
A traffic element is only valid for its corresponding lanes.
Following the wrong signals would be catastrophic. A traffic element is only valid for its corresponding lanes. Following the wrong signals would be catastrophic. Also,
Also, lanes have their predecessors and successors to build the map. lanes have their predecessors and successors to build the map. Autonomous vehicles are required to **reason** about
Autonomous vehicles are required to **reason** about the **topology relationships** to drive in the right way. the **topology relationships** to drive in the right way. In this dataset, we hope to shed light on the task of **scene
In this dataset, we hope to shed light on the task of **scene structure perception and reasoning**. structure perception and reasoning**.
### Data scale and diversity matters - building on Top of Awesome Benchmarks ### Data scale and diversity matters - building on Top of Awesome Benchmarks
Experience from the sunny day does not apply to the dancing snowflakes.
For machine learning, data is the must-have food. Experience from the sunny day does not apply to the dancing snowflakes. For machine learning, data is the must-have
We provide annotations on data collected in various cities, from Austin to Singapore and from Boston to Miami. food. We provide annotations on data collected in various cities, from Austin to Singapore and from Boston to Miami.
The **diversity** of data enables models to generalize in different atmospheres and landscapes. The **diversity** of data enables models to generalize in different atmospheres and landscapes.
<p align="right">(<a href="#top">back to top</a>)</p> <p align="right">(<a href="#top">back to top</a>)</p>
## Task ## Task
The primary task of the dataset is **scene structure perception and reasoning**, which requires the model to recognize the dynamic drivable states of lanes in the surrounding environment.
The challenge of this dataset includes not only detecting lane centerlines and traffic elements but also recognizing the attribute of traffic elements and topology relationships on detected objects.
We define the **[OpenLane-V2 Score (OLS)](./docs/metrics.md#openlane-v2-score)**, which is the average of various metrics covering different aspects of the primary task:
$$ The primary task of the dataset is **scene structure perception and reasoning**, which requires the model to recognize
\text{OLS} = \frac{1}{4} \bigg[ \text{DET}_{l} + \text{DET}_{t} + f(\text{TOP}_{ll}) + f(\text{TOP}_{lt}) \bigg]. the dynamic drivable states of lanes in the surrounding environment. The challenge of this dataset includes not only
$$ detecting lane centerlines and traffic elements but also recognizing the attribute of traffic elements and topology
relationships on detected objects. We define the **[OpenLane-V2 Score (OLS)](./docs/metrics.md#openlane-v2-score)**,
which is the average of various metrics covering different aspects of the primary task:
$$ \\text{OLS} = \\frac{1}{4} \\bigg\[ \\text{DET}_{l} + \\text{DET}_{t} + f(\\text{TOP}_{ll}) + f(\\text{TOP}_{lt})
\\bigg\]. $$
The metrics of different subtasks are described below. The metrics of different subtasks are described below.
### 3D Lane Detection 🛣️ ### 3D Lane Detection 🛣️
The [OpenLane](https://github.com/OpenDriveLab/OpenLane) dataset, which is the first real-world and the largest scaled 3D lane dataset to date, provides lane line annotations in 3D space.
Similarly, we annotate 3D lane centerlines and include the F-Score for evaluating predicted results of undirected lane centerlines. The [OpenLane](https://github.com/OpenDriveLab/OpenLane) dataset, which is the first real-world and the largest scaled
Furthermore, we define the subtask of 3D lane detection as detecting directed 3D lane centerlines from the given multi-view images covering the whole horizontal FOV. 3D lane dataset to date, provides lane line annotations in 3D space. Similarly, we annotate 3D lane centerlines and
The instance-level evaluation metric of average precision $\text{DET}_{l}$ is utilized to measure the detection performance on lane centerlines (l). include the F-Score for evaluating predicted results of undirected lane centerlines. Furthermore, we define the subtask
of 3D lane detection as detecting directed 3D lane centerlines from the given multi-view images covering the whole
horizontal FOV. The instance-level evaluation metric of average precision $\\text{DET}\_{l}$ is utilized to measure the
detection performance on lane centerlines (l).
<p align="center"> <p align="center">
<img src="./imgs/lane.gif" width="696px" > <img src="./imgs/lane.gif" width="696px" >
</p> </p>
### Traffic Element Recognition 🚥 ### Traffic Element Recognition 🚥
Traffic elements and their attribute provide crucial information for autonomous vehicles.
The attribute represents the semantic meaning of a traffic element, such as the red color of a traffic light. Traffic elements and their attribute provide crucial information for autonomous vehicles. The attribute represents the
In this subtask, on the given image in the front view, the location of traffic elements (traffic lights and road signs) and their attributes are demanded to be perceived simultaneously. semantic meaning of a traffic element, such as the red color of a traffic light. In this subtask, on the given image in
Compared to typical 2D detection datasets, the challenge is that the size of traffic elements is tiny due to the large scale of outdoor environments. the front view, the location of traffic elements (traffic lights and road signs) and their attributes are demanded to be
Similar to the typical 2D detection task, the metric of $\text{DET}_{t}$ is utilized to measure the performance of traffic elements (t) detection averaged over different attributes. perceived simultaneously. Compared to typical 2D detection datasets, the challenge is that the size of traffic elements
is tiny due to the large scale of outdoor environments. Similar to the typical 2D detection task, the metric of
$\\text{DET}\_{t}$ is utilized to measure the performance of traffic elements (t) detection averaged over different
attributes.
<p align="center"> <p align="center">
<img src="./imgs/traffic_element.gif" width="696px" > <img src="./imgs/traffic_element.gif" width="696px" >
</p> </p>
### Topology Recognition 🕸️ ### Topology Recognition 🕸️
We first define the task of recognizing topology relationships in the field of autonomous driving.
Given multi-view images, the model learns to recognize the topology relationships among lane centerlines and between lane centerlines and traffic elements. We first define the task of recognizing topology relationships in the field of autonomous driving. Given multi-view
The most similar task is link prediction in the field of graph, in which the vertices are given and only edges are predicted by models. images, the model learns to recognize the topology relationships among lane centerlines and between lane centerlines and
In our case, both vertices and edges are unknown for the model. traffic elements. The most similar task is link prediction in the field of graph, in which the vertices are given and
Thus, lane centerlines and traffic elements are needed to be detected first, and then the topology relationships are built. only edges are predicted by models. In our case, both vertices and edges are unknown for the model. Thus, lane
Adapted from the task of link prediction, $\text{TOP}$ is used for topology among lane centerlines (ll) and between lane centerlines and traffic elements (lt). centerlines and traffic elements are needed to be detected first, and then the topology relationships are built. Adapted
from the task of link prediction, $\\text{TOP}$ is used for topology among lane centerlines (ll) and between lane
centerlines and traffic elements (lt).
<p align="center"> <p align="center">
<img src="./imgs/topology.gif" width="696px" > <img src="./imgs/topology.gif" width="696px" >
...@@ -179,72 +197,79 @@ Adapted from the task of link prediction, $\text{TOP}$ is used for topology amon ...@@ -179,72 +197,79 @@ Adapted from the task of link prediction, $\text{TOP}$ is used for topology amon
<p align="right">(<a href="#top">back to top</a>)</p> <p align="right">(<a href="#top">back to top</a>)</p>
## Data ## Data
The OpenLane-V2 dataset is a large-scale dataset for scene structure perception and reasoning in the field of autonomous driving.
Following [OpenLane](https://github.com/OpenDriveLab/OpenLane), the first 3D lane dataset, we provide lane annotations in 3D space.
The difference is that instead of lane lines, we annotate lane centerlines, which can be served as the trajectory for autonomous vehicles.
Besides, we provide annotations on traffic elements (traffic lights and road signs) and their attribute, and the topology relationships among lane centerlines and between lane centerlines and traffic elements.
The dataset is divided into two subsets. The OpenLane-V2 dataset is a large-scale dataset for scene structure perception and reasoning in the field of autonomous
**The `subset_A` serves as the primary subset and is utilized for the coming challenges and leaderboard, in which no external data, including the other subset, is allowed**. driving. Following [OpenLane](https://github.com/OpenDriveLab/OpenLane), the first 3D lane dataset, we provide lane
The `subset_B` can be used to test the generalization ability of the model. annotations in 3D space. The difference is that instead of lane lines, we annotate lane centerlines, which can be served
For more details, please refer to the corresponding pages: [use of data](./data/README.md), [notes of annotation](./docs/annotation.md), and [dataset statistics](./docs/statistics.md). as the trajectory for autonomous vehicles. Besides, we provide annotations on traffic elements (traffic lights and road
signs) and their attribute, and the topology relationships among lane centerlines and between lane centerlines and
traffic elements.
The dataset is divided into two subsets.
**The `subset_A` serves as the primary subset and is utilized for the coming challenges and leaderboard, in which no
external data, including the other subset, is allowed**. The `subset_B` can be used to test the generalization ability
of the model. For more details, please refer to the corresponding pages: [use of data](./data/README.md)
, [notes of annotation](./docs/annotation.md), and [dataset statistics](./docs/statistics.md).
[Download](./data/README.md#download) now to discover our dataset! [Download](./data/README.md#download) now to discover our dataset!
<p align="right">(<a href="#top">back to top</a>)</p> <p align="right">(<a href="#top">back to top</a>)</p>
## Devkit ## Devkit
We provide a devkit for easy access to the OpenLane-V2 dataset.
After installing the package, the use of the dataset, such as loading images, loading meta data, and evaluating results, can be accessed through the API of `openlanv2`.
For more details on the API, please refer to [devkit](./docs/devkit.md).
<p align="right">(<a href="#top">back to top</a>)</p> We provide a devkit for easy access to the OpenLane-V2 dataset. After installing the package, the use of the dataset,
such as loading images, loading meta data, and evaluating results, can be accessed through the API of `openlanv2`. For
more details on the API, please refer to [devkit](./docs/devkit.md).
<p align="right">(<a href="#top">back to top</a>)</p>
## Get Started ## Get Started
Please follow the steps below to get familiar with the OpenLane-V2 dataset. Please follow the steps below to get familiar with the OpenLane-V2 dataset.
1. Run the following commands to install the environment for setting up the dataset: 1. Run the following commands to install the environment for setting up the dataset:
```sh ```sh
git clone https://github.com/OpenDriveLab/OpenLane-V2.git git clone https://github.com/OpenDriveLab/OpenLane-V2.git
cd OpenLane-V2 cd OpenLane-V2
conda create -n openlanev2 python=3.8 -y conda create -n openlanev2 python=3.8 -y
conda activate openlanev2 conda activate openlanev2
pip install -r requirements.txt pip install -r requirements.txt
python setup.py develop python setup.py develop
``` ```
2. Use [links](./data/README.md#download) to download data manually from 2. Use [links](./data/README.md#download) to download data manually from
- <img src="https://user-images.githubusercontent.com/29263416/222076048-21501bac-71df-40fa-8671-2b5f8013d2cd.png" alt="OpenDataLab" width="18"/> OpenDataLab, - <img src="https://user-images.githubusercontent.com/29263416/222076048-21501bac-71df-40fa-8671-2b5f8013d2cd.png" alt="OpenDataLab" width="18"/> OpenDataLab,
- <img src="https://ssl.gstatic.com/docs/doclist/images/drive_2022q3_32dp.png" alt="Google Drive" width="18"/> Google Drive, - <img src="https://ssl.gstatic.com/docs/doclist/images/drive_2022q3_32dp.png" alt="Google Drive" width="18"/> Google Drive,
- <img src="https://nd-static.bdstatic.com/m-static/v20-main/favicon-main.ico" alt="Baidu Yun" width="18"/> Baidu Yun. - <img src="https://nd-static.bdstatic.com/m-static/v20-main/favicon-main.ico" alt="Baidu Yun" width="18"/> Baidu Yun.
Then put them into the `data/OpenLane-V2/` folder and unzip them. Then put them into the `data/OpenLane-V2/` folder and unzip them. The resulting folder hierarchy is
The resulting folder hierarchy is described [here](./data/README.md#hierarchy). described [here](./data/README.md#hierarchy). Or use the following commands to download example data for a quick
Or use the following commands to download example data for a quick glance at the dataset: glance at the dataset:
```sh ```sh
cd data/OpenLane-V2 cd data/OpenLane-V2
wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=1Ni-L6u1MGKJRAfUXm39PdBIxdk_ntdc6' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=1Ni-L6u1MGKJRAfUXm39PdBIxdk_ntdc6" -O OpenLane-V2_sample.tar wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=1Ni-L6u1MGKJRAfUXm39PdBIxdk_ntdc6' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=1Ni-L6u1MGKJRAfUXm39PdBIxdk_ntdc6" -O OpenLane-V2_sample.tar
md5sum -c openlanev2.md5 md5sum -c openlanev2.md5
tar -xvf *.tar tar -xvf *.tar
cd ../.. cd ../..
``` ```
3. Run the [tutorial](./tutorial.ipynb) on jupyter notebook to get familiar with the dataset and devkit. 3. Run the [tutorial](./tutorial.ipynb) on jupyter notebook to get familiar with the dataset and devkit.
<p align="right">(<a href="#top">back to top</a>)</p> <p align="right">(<a href="#top">back to top</a>)</p>
## Train a Model ## Train a Model
Plug-ins to prevail deep learning frameworks for training models are provided to start training models on the OpenLane-V2 dataset.
We appreciate your valuable feedback and contributions to plug-ins on different frameworks. Plug-ins to prevail deep learning frameworks for training models are provided to start training models on the
OpenLane-V2 dataset. We appreciate your valuable feedback and contributions to plug-ins on different frameworks.
### mmdet3d ### mmdet3d
The [plug-in](./plugin/mmdet3d/) to MMDetection3d is built on top of [mmdet3d v1.0.0rc6](https://github.com/open-mmlab/mmdetection3d/tree/v1.0.0rc6) and tested under: The [plug-in](./plugin/mmdet3d/) to MMDetection3d is built on top
of [mmdet3d v1.0.0rc6](https://github.com/open-mmlab/mmdetection3d/tree/v1.0.0rc6) and tested under:
- Python 3.8.15 - Python 3.8.15
- PyTorch 1.9.1 - PyTorch 1.9.1
- CUDA 11.1 - CUDA 11.1
...@@ -253,22 +278,26 @@ The [plug-in](./plugin/mmdet3d/) to MMDetection3d is built on top of [mmdet3d v1 ...@@ -253,22 +278,26 @@ The [plug-in](./plugin/mmdet3d/) to MMDetection3d is built on top of [mmdet3d v1
- mmdet==2.26.0 - mmdet==2.26.0
- mmsegmentation==0.29.1 - mmsegmentation==0.29.1
Please follow the [instruction](https://github.com/open-mmlab/mmdetection3d/blob/v1.0.0rc6/docs/en/getting_started.md) to install mmdet3d. Please follow the [instruction](https://github.com/open-mmlab/mmdetection3d/blob/v1.0.0rc6/docs/en/getting_started.md)
Assuming OpenLane-V2 is installed under `OpenLane-V2/` and mmdet3d is built under `mmdetection3d/`, create a soft link to the plug-in file: to install mmdet3d. Assuming OpenLane-V2 is installed under `OpenLane-V2/` and mmdet3d is built under `mmdetection3d/`,
create a soft link to the plug-in file:
``` ```
└── mmdetection3d └── mmdetection3d
└── projects └── projects
├── example_project ├── example_project
└── openlanev2 -> OpenLane-V2/plugin/mmdet3d └── openlanev2 -> OpenLane-V2/plugin/mmdet3d
``` ```
Then you can train or evaluate a model using the config `mmdetection3d/projects/openlanev2/configs/baseline.py`, whose path is replaced accordingly.
Options can be passed to enable supported functions during evaluation, such as `--eval-options dump=True dump_dir=/PATH/TO/DUMP` to save pickle file for submission and `--eval-options visualization=True visualization_dir=/PATH/TO/VIS` for visualization.
Then you can train or evaluate a model using the config `mmdetection3d/projects/openlanev2/configs/baseline.py`, whose
path is replaced accordingly. Options can be passed to enable supported functions during evaluation, such
as `--eval-options dump=True dump_dir=/PATH/TO/DUMP` to save pickle file for submission
and `--eval-options visualization=True visualization_dir=/PATH/TO/VIS` for visualization.
<p align="right">(<a href="#top">back to top</a>)</p> <p align="right">(<a href="#top">back to top</a>)</p>
## Citation ## Citation
Please use the following citation when referencing OpenLane-V2: Please use the following citation when referencing OpenLane-V2:
```bibtex ```bibtex
...@@ -285,10 +314,13 @@ Please use the following citation when referencing OpenLane-V2: ...@@ -285,10 +314,13 @@ Please use the following citation when referencing OpenLane-V2:
## License ## License
Before using the dataset, you should register on the website and agree to the terms of use of the [nuScenes](https://www.nuscenes.org/nuscenes). Before using the dataset, you should register on the website and agree to the terms of use of
the [nuScenes](https://www.nuscenes.org/nuscenes).
Our dataset is built on top of the [nuScenes](https://www.nuscenes.org/nuscenes) and [Argoverse 2](https://www.argoverse.org/av2.html) datasets. Our dataset is built on top of the [nuScenes](https://www.nuscenes.org/nuscenes)
Before using the OpenLane-V2 dataset, you should agree to the terms of use of the [nuScenes](https://www.nuscenes.org/nuscenes) and [Argoverse 2](https://www.argoverse.org/av2.html) datasets respectively. and [Argoverse 2](https://www.argoverse.org/av2.html) datasets. Before using the OpenLane-V2 dataset, you should agree
to the terms of use of the [nuScenes](https://www.nuscenes.org/nuscenes)
and [Argoverse 2](https://www.argoverse.org/av2.html) datasets respectively.
All code within this repository is under [Apache License 2.0](./LICENSE). All code within this repository is under [Apache License 2.0](./LICENSE).
......
{ {
"train": { "train": {
"00492": [ "00492": [
"315970272249927212.json", "315970272249927212.json",
"315970273249927208.json", "315970273249927208.json",
"315970277249927220.json", "315970277249927220.json",
"315970282749927222.json", "315970282749927222.json",
"315970283249927220.json", "315970283249927220.json",
"315970284749927218.json", "315970284749927218.json",
"315970270749927221.json", "315970270749927221.json",
"315970275749927218.json", "315970275749927218.json",
"315970277749927214.json", "315970277749927214.json",
"315970279749927222.json", "315970279749927222.json",
"315970275249927215.json", "315970275249927215.json",
"315970278249927213.json", "315970278249927213.json",
"315970271249927219.json", "315970271249927219.json",
"315970274749927217.json", "315970274749927217.json",
"315970281749927215.json", "315970281749927215.json",
"315970273749927222.json", "315970273749927222.json",
"315970272749927210.json", "315970272749927210.json",
"315970269249927220.json", "315970269249927220.json",
"315970284249927211.json", "315970284249927211.json",
"315970280249927220.json", "315970280249927220.json",
"315970283749927209.json", "315970283749927209.json",
"315970276249927212.json", "315970276249927212.json",
"315970282249927217.json", "315970282249927217.json",
"315970271749927213.json", "315970271749927213.json",
"315970279249927218.json", "315970279249927218.json",
"315970270249927208.json", "315970270249927208.json",
"315970278749927211.json", "315970278749927211.json",
"315970269749927218.json", "315970269749927218.json",
"315970280749927221.json", "315970280749927221.json",
"315970281249927219.json", "315970281249927219.json",
"315970276749927222.json", "315970276749927222.json",
"315970274249927212.json" "315970274249927212.json"
], ],
"00556": [ "00556": [
"315969900049927216.json", "315969900049927216.json",
"315969913049927216.json", "315969913049927216.json",
"315969910049927218.json", "315969910049927218.json",
"315969912049927218.json", "315969912049927218.json",
"315969907549927221.json", "315969907549927221.json",
"315969911549927216.json", "315969911549927216.json",
"315969906549927214.json", "315969906549927214.json",
"315969908049927220.json", "315969908049927220.json",
"315969905549927209.json", "315969905549927209.json",
"315969904549927220.json", "315969904549927220.json",
"315969901549927216.json", "315969901549927216.json",
"315969899549927217.json", "315969899549927217.json",
"315969913549927214.json", "315969913549927214.json",
"315969902049927218.json", "315969902049927218.json",
"315969902549927213.json", "315969902549927213.json",
"315969909549927216.json", "315969909549927216.json",
"315969907049927209.json", "315969907049927209.json",
"315969909049927221.json", "315969909049927221.json",
"315969899049927218.json", "315969899049927218.json",
"315969910549927209.json", "315969910549927209.json",
"315969908549927214.json", "315969908549927214.json",
"315969900549927214.json", "315969900549927214.json",
"315969903549927214.json", "315969903549927214.json",
"315969904049927221.json", "315969904049927221.json",
"315969912549927218.json", "315969912549927218.json",
"315969906049927216.json", "315969906049927216.json",
"315969911049927216.json", "315969911049927216.json",
"315969901049927213.json", "315969901049927213.json",
"315969898549927216.json", "315969898549927216.json",
"315969898049927213.json", "315969898049927213.json",
"315969903049927216.json", "315969903049927216.json",
"315969905049927210.json" "315969905049927210.json"
] ]
} }
} }
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
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