Author: Li Yang
Official repository for the MapModEX map modification companion code for the WACV 2025 paper Mind the map! Accounting for existing map information when estimating online HDMaps from sensor and codebase
This is a pre-release of the code to elucidate any questions regarding the implementation that arise after publication of MapEX at WACV 2025
A proper full release with minimal running examples, installation instructions and cleaner code notations will be released as soon as possible!
A more complex MapModEX 2.0 library is in development. It will allow for more complex element-wise perturbations and create map files readable by a nuscenes-like api for applications like trajectory forecasting.
For the time being, libraries should be installed by following installation instructions of MapTRv2 code, precisely this commit from August 31, 2023. Much like the main MapEX code, it is worth noting this code heavily builds upon the original MapTRv2 code.
The main running file is: custom_nusc_map_converter_copy.py.
To check your installation, download the NuScenes V1.0-data and can_bus data. You should then modify the following parameters according to your local installation:
parser.add_argument(
'--root-path',
type=str,
default='/path/to/nuscenes/data',
help='specify the root path of dataset')
parser.add_argument(
'--canbus',
type=str,
default='/path/to/nuscenes/data',
help='specify the root path of nuScenes canbus')
parser.add_argument(
'--out-dir',
type=str,
default='/path/to/output/directory',
required=False,
help='name of info pkl')
The output will be two .pkl files: nuscenes_map_infos_temporal_train.pkl and nuscenes_map_infos_temporal_val.pkl
more parameters may be needed in future studies:
parser.add_argument(
'--version',
type=str,
default='v1.0',
required=False,
help='specify the dataset version, no need for kitti')
'--version' the version of nuscenes data. If you want to use other versions of NuScenes data, comment the version = 'v1.0-mini' block and uncommit the upper two blocks: train_version and test_version. And set the version to '--version'
if __name__ == '__main__':
# train_version = f'{args.version}-trainval'
# create_nuscenes_infos(
# root_path=args.root_path,
# out_path=args.out_dir,
# can_bus_root_path=args.canbus,
# info_prefix=args.extra_tag,
# version=train_version,
# max_sweeps=args.max_sweeps)
# test_version = f'{args.version}-test'
# create_nuscenes_infos(
# root_path=args.root_path,
# out_path=args.out_dir,
# can_bus_root_path=args.canbus,
# info_prefix=args.extra_tag,
# version=test_version,
# max_sweeps=args.max_sweeps)
version = 'v1.0-mini'
create_nuscenes_infos(
root_path=args.root_path,
out_path=args.out_dir,
can_bus_root_path=args.canbus,
info_prefix=args.extra_tag,
version=version,
max_sweeps=args.max_sweeps)
Perturbation configure can be changed in the perturbation.py file.
In the function obtain_perturb_vectormap(), by setting the perturbation parameters, you can create pertubated annotation versions to add to info.
# ------peturbation------
trans_args = PerturbParameters(del_ped=[1, 0.5, None],
add_ped=[1, 0.25, None],
del_div=[0, 0.5, None],
# trigonometric warping
def_pat_tri=[1, None, [1., 1., 3.]],
# Gaussian warping
def_pat_gau=[1, None, [0, 0.1]],
int_num=0, # 0 means no interpolation, default is 0
int_ord='before', # before the perturbation or after it, default is 'before'
int_sav=False,
visual=True, # switch for the visualization
vis_show=False, # switch for plot
vis_path='/path/to/vis/directory') # path for saving the visualization) # default is False
You should give your annotation a name, such as "annotation_1". After running you will have a perturbation annotation in your info.
Since the Gaussian warp used generates noise randomly each time, you can create a loop to generate multiple perturbation annotations as shown below.
# the pertubated map
# w/o loop
info = perturb_map(vector_map, lidar2global_translation,
lidar2global_rotation, trans_args, info, 'annotation_1', visual, trans_dic)
# w/ loop
loop = asyncio.get_event_loop() # Have a new event loop
looper = asyncio.gather(*[perturb_map(vector_map, lidar2global_translation,
lidar2global_rotation, trans_args, info, 'annotation_{}'.format(i), visual, trans_dic) for i in range(10)]) # Run the loop
results = loop.run_until_complete(looper)
In addition to the one-shot and loop methods above, to create multiple different versions of the perturbation annotation, you can also create different trans_args for each version.
# the first perturbed map
map_version = 'annotation_1'
trans_args = PerturbParameters(del_ped=[1, 0.1, None],
shi_ped=[1, 0.1, [5, 5]],
add_ped=[1, 0.1, None])
info = perturb_map(vector_map, lidar2global_translation,
lidar2global_rotation, trans_args, info, map_version, visual)
# the second perturbed map
map_version = 'annotation_2'
trans_args = PerturbParameters(del_div=[1, 0.1, None],
shi_div=[1, 0.1, [5, 5]])
info = perturb_map(vector_map, lidar2global_translation,
lidar2global_rotation, trans_args, info, map_version, visual)
The default parameters in the trans_args() class include all perturbation types, and value is a list containing 3 elements
[Boolean: whether to perform this perturbation,
Float: perturbation ratio: 0-1, or None - for patch transformations
Variable type: additional perturbation parameters]
Each sample in each scene, corresponding to the annotation, has multiple perturbation versions annotation_* and its corresponding list of the original image annotation_*_correspondence .
In the perturbation.py file, before the perturbation parameter setting block.
- visual: whether to visualize
- vis_show: whether to display
- vis_path: save path. If not saving side set to None.
trans_args = PerturbParameters(
visual=True, vis_show=False, vis_path='/path/to/viz/directory')
visual = RenderMap(info, vector_map, trans_args)