Análisis del código de preprocesamiento de conjuntos de datos en BEVerse

Análisis del código de preprocesamiento de conjuntos de datos en BEVerse

Analiza principalmente la parte de preprocesamiento del conjunto de datos de Nuscenes en el proyecto BEVerse.

1. Script de generación de conjuntos de datos

Referencia detallada:BEVerse/docs/data_preparation.md

  • 1.1 Estructura de datos
BEVerse
├── mmdet3d
├── tools
├── configs
├── projects
├── data
│   ├── nuscenes
│   │   ├── maps
│   │   ├── samples
│   │   ├── sweeps
│   │   ├── v1.0-test
|   |   ├── v1.0-trainval
  • 1.2 script de generación de data_info
python tools/create_data.py nuscenes --root-path ./data/nuscenes --out-dir ./data/nuscenes --extra-tag nuscenes

2. Mirada en profundidad al script generado

Ubicación del archivo :BEVerse/tools/create_data.py

Procesamiento principal : en la función principal, de acuerdo con los diferentes tipos de datos del conjunto de datos, como 'kitti', 'nuscenes', etc., se realizan diferentes preprocesamientos de datos y se empaquetan en un archivo de información de pares clave-valor y almacenado. Este artículo se centra principalmente en el análisis de la función nuscenes_data_prep().

Código principal :

def nuscenes_data_prep(root_path,
                       info_prefix,
                       version,
                       dataset_name,
                       out_dir,
                       max_sweeps=10):
    """Prepare data related to nuScenes dataset.

    Related data consists of '.pkl' files recording basic infos,
    2D annotations and groundtruth database.

    Args:
        root_path (str): Path of dataset root.
        info_prefix (str): The prefix of info filenames.
        version (str): Dataset version.
        dataset_name (str): The dataset class name.
        out_dir (str): Output directory of the groundtruth database info.
        max_sweeps (int): Number of input consecutive frames. Default: 10
    """

    import os
    info_save_path = 'data/nuscenes_infos'
    os.makedirs(info_save_path, exist_ok=True)

    nuscenes_converter.create_nuscenes_infos(
        root_path, info_prefix, version=version, max_sweeps=max_sweeps, info_save_path=info_save_path)

    if version == 'v1.0-test':
        info_test_path = osp.join(
            info_save_path, f'{info_prefix}_infos_test.pkl')
        nuscenes_converter.export_2d_annotation(
            root_path, info_test_path, version=version)
        return

    info_train_path = osp.join(
        info_save_path, f'{info_prefix}_infos_train.pkl')
    info_val_path = osp.join(info_save_path, f'{info_prefix}_infos_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)

El preprocesamiento de datos de Nuscenes incluye principalmente establecer rutas de almacenamiento, establecer información de datos (create_nuscenes_infos), exportar anotaciones 2D (export_2d_annotation), etc.

3. Funciones básicas

3.1 Crear información de datos

1.
Ubicación del archivo prototipo de función:BEVerse/tools/data_converter/nuscenes_converter.py

def create_nuscenes_infos(root_path,
                          info_prefix,
                          version='v1.0-trainval',
                          max_sweeps=10,
                          info_save_path=None):
    """Create info file of nuscene dataset.

    Given the raw data, generate its related info file in pkl format.

    Args:
        root_path (str): Path of the data root.
        info_prefix (str): Prefix of the info file to be generated.
        version (str): Version of the data.
            Default: 'v1.0-trainval'
        max_sweeps (int): Max number of sweeps.
            Default: 10
    """
    ## 1. 利用Nuscenes工具导入scene场景
    from nuscenes.nuscenes import NuScenes
    nusc = NuScenes(version=version, dataroot=root_path, verbose=True)
    from nuscenes.utils import splits
    available_vers = ['v1.0-trainval', 'v1.0-test', 'v1.0-mini']
    assert version in available_vers
    if version == 'v1.0-trainval':
        train_scenes = splits.train
        val_scenes = splits.val
    elif version == 'v1.0-test':
        train_scenes = splits.test
        val_scenes = []
    elif version == 'v1.0-mini':
        train_scenes = splits.mini_train
        val_scenes = splits.mini_val
    else:
        raise ValueError('unknown')
    
    # 2. filter existing scenes.
    available_scenes = get_available_scenes(nusc)
    available_scene_names = [s['name'] for s in available_scenes]
    train_scenes = list(
        filter(lambda x: x in available_scene_names, train_scenes))
    val_scenes = list(filter(lambda x: x in available_scene_names, val_scenes))
    train_scenes = set([
        available_scenes[available_scene_names.index(s)]['token']
        for s in train_scenes
    ])
    val_scenes = set([
        available_scenes[available_scene_names.index(s)]['token']
        for s in val_scenes
    ])

    test = 'test' in version
    if test:
        print('test scene: {}'.format(len(train_scenes)))
    else:
        print('train scene: {}, val scene: {}'.format(
            len(train_scenes), len(val_scenes)))
    
    ## 3. 填充训练集验证集信息
    train_nusc_infos, val_nusc_infos = _fill_trainval_infos(
        nusc, train_scenes, val_scenes, test, max_sweeps=max_sweeps)

    info_save_path = info_save_path if info_save_path else root_path

    metadata = dict(version=version)
    if test:
        print('test sample: {}'.format(len(train_nusc_infos)))
        data = dict(infos=train_nusc_infos, metadata=metadata)
        info_path = osp.join(info_save_path,
                             '{}_infos_test.pkl'.format(info_prefix))
        mmcv.dump(data, info_path)
    else:
        print('train sample: {}, val sample: {}'.format(
            len(train_nusc_infos), len(val_nusc_infos)))
        # train infos
        data = dict(infos=train_nusc_infos, metadata=metadata)
        info_path = osp.join(info_save_path,
                             '{}_infos_train.pkl'.format(info_prefix))
        mmcv.dump(data, info_path)
        # val infos
        data['infos'] = val_nusc_infos
        info_val_path = osp.join(info_save_path,
                                 '{}_infos_val.pkl'.format(info_prefix))
        mmcv.dump(data, info_val_path)
        # trainval infos
        trainval_nusc_infos = train_nusc_infos + val_nusc_infos
        data['infos'] = trainval_nusc_infos
        info_trainval_path = osp.join(info_save_path,
                                      '{}_infos_trainval.pkl'.format(info_prefix))
        mmcv.dump(data, info_trainval_path)

2. Análisis del proceso
1) Tomando el mini conjunto de datos como ejemplo, primero use las herramientas integradas de Nuscenes para generar train_scenes (8 escenas de entrenamiento) y val_scenes (2 escenas de verificación).
2) Luego filtre las escenas existentes, extraiga tokens de las escenas de entrenamiento y verificación existentes, recomponga el conjunto y guárdelos en train_scenesy respectivamente val_scenes.
3) Generar información del conjunto de entrenamiento y del conjunto de verificación (_fill_trainval_infos) a partir de los datos originales, extraer varios datos y atributos, y almacenarlos en forma de train_nusc_infospares clave-valor val_nusc_infos.
4) Finalmente, empaque train_nusc_infos/val_nusc_infos y los metadatos (pares clave-valor de la versión), colóquelos datay guárdelos como archivos pkl a través de mmcv.dump.

3.2 Exportar anotaciones 2D

1. Prototipo de función

def export_2d_annotation(root_path, info_path, version, mono3d=True):
    """Export 2d annotation from the info file and raw data.

    Args:
        root_path (str): Root path of the raw data.
        info_path (str): Path of the info file.
        version (str): Dataset version.
        mono3d (bool): Whether to export mono3d annotation. Default: True.
    """
    # get bbox annotations for camera
    camera_types = [
        'CAM_FRONT',
        'CAM_FRONT_RIGHT',
        'CAM_FRONT_LEFT',
        'CAM_BACK',
        'CAM_BACK_LEFT',
        'CAM_BACK_RIGHT',
    ]
    nusc_infos = mmcv.load(info_path)['infos']
    nusc = NuScenes(version=version, dataroot=root_path, verbose=True)
    # info_2d_list = []
    cat2Ids = [
        dict(id=nus_categories.index(cat_name), name=cat_name)
        for cat_name in nus_categories
    ]
    coco_ann_id = 0
    coco_2d_dict = dict(annotations=[], images=[], categories=cat2Ids)
    for info in mmcv.track_iter_progress(nusc_infos):
        for cam in camera_types:
            cam_info = info['cams'][cam]
            coco_infos = get_2d_boxes(
                nusc,
                cam_info['sample_data_token'],
                visibilities=['', '1', '2', '3', '4'],
                mono3d=mono3d)
            (height, width, _) = mmcv.imread(cam_info['data_path']).shape
            coco_2d_dict['images'].append(
                dict(
                    file_name=cam_info['data_path'].split('data/nuscenes/')
                    [-1],
                    id=cam_info['sample_data_token'],
                    token=info['token'],
                    cam2ego_rotation=cam_info['sensor2ego_rotation'],
                    cam2ego_translation=cam_info['sensor2ego_translation'],
                    ego2global_rotation=info['ego2global_rotation'],
                    ego2global_translation=info['ego2global_translation'],
                    cam_intrinsic=cam_info['cam_intrinsic'],
                    width=width,
                    height=height))
            for coco_info in coco_infos:
                if coco_info is None:
                    continue
                # add an empty key for coco format
                coco_info['segmentation'] = []
                coco_info['id'] = coco_ann_id
                coco_2d_dict['annotations'].append(coco_info)
                coco_ann_id += 1
    if mono3d:
        json_prefix = f'{info_path[:-4]}_mono3d'
    else:
        json_prefix = f'{info_path[:-4]}'
    mmcv.dump(coco_2d_dict, f'{json_prefix}.coco.json')

2. Análisis del proceso
1) Primero obtenga nusc_infos, que es la información de información almacenada en 3.1.
2) Organice 10 categorías en valores de índice de identificación
3) Recorra la información de información y luego recorra varias cámaras por separado y almacene información de atributos en cada cámara, como sample_data_token, varias matrices de rotación e información de etiquetas en coco_2d_dict.


4. Fichero generado y descripción de su contenido

Artículo de referencia : Conjunto de datos NuScenes de detección de objetos 3D

Para obtener más información, consulte docs/datasets/nuscenes_det.mdel documento en inglés. La estructura de directorios de los datos es la siguiente. Aquí nos centramos principalmente en .pkllos archivos, que se utilizan para métodos que involucran nubes de puntos. .jsones un enfoque basado en imágenes al estilo Coco, como la detección 2D y 3D basada en imágenes.

├── data
│   ├── nuscenes
│   │   ├── maps
│   │   ├── samples
│   │   ├── sweeps
│   │   ├── v1.0-test
|   |   ├── v1.0-trainval
│   │   ├── nuscenes_database
│   │   ├── nuscenes_infos_train.pkl
│   │   ├── nuscenes_infos_val.pkl
│   │   ├── nuscenes_infos_test.pkl
│   │   ├── nuscenes_dbinfos_train.pkl
│   │   ├── nuscenes_infos_train_mono3d.coco.json
│   │   ├── nuscenes_infos_val_mono3d.coco.json
│   │   ├── nuscenes_infos_test_mono3d.coco.json
  • nuscenes_database/xxxxx.bin: datos de nube de puntos contenidos en cada cuadro delimitador 3D del conjunto de datos de entrenamiento.
  • nuscenes_infos_train.pkl: información del conjunto de datos de entrenamiento, contiene dos valores clave: metadata 和 infos. Los metadatos son la información básica del propio conjunto de datos, como {'version': 'v1.0-trainval'}, mientras que infos contiene información detallada.
    • info['lidar_path']: la ruta del archivo de datos de la nube de puntos LIDAR.
    • info['token']: token de datos de muestra.
    • info['sweeps']: información de escaneo. 有别于samples关键帧.
      • info['sweeps'][i]['data_path']: La ruta de datos del i-ésimo escaneo.
      • info['sweeps'][i]['type']: tipo de datos de escaneo, como "lidar".
      • info['sweeps'][i]['sample_data_token']: Token de datos de muestra de barrido.
      • info['sweeps'][i]['sensor2ego_translation']: traducción del sensor actual al vehículo ego (lista 1x3).
      • info['sweeps'][i]['sensor2ego_rotation']: La rotación del sensor actual al vehículo ego (lista 1x4 en formato de cuaternión).
      • info['sweeps'][i]['ego2global_translation']: Traducción del vehículo ego a coordenadas globales (lista 1x3).
      • info['sweeps'][i]['ego2global_rotation']: Rotación del vehículo ego a coordenadas globales (lista 1x4 en formato de cuaternión).
      • info['sweeps'][i]['timestamp']: La marca de tiempo de los datos escaneados.
      • info['sweeps'][i]['sensor2lidar_translation']: traducción (lista 1x3) del sensor actual (utilizado para recopilar datos de escaneo) a lidar.
      • info['sweeps'][i]['sensor2lidar_rotation']: Rotación del sensor actual (utilizado para recopilar datos de escaneo) a lidar (lista 1x4 en formato de cuaternión).
    • info['cams']: Información de calibración de la cámara. Contiene seis valores clave correspondientes a cada cámara: 'CAM_FRONT', 'CAM_FRONT_RIGHT', 'CAM_FRONT_LEFT', 'CAM_BACK', 'CAM_BACK_LEFT', 'CAM_BACK_RIGHT'.
    • info['lidar2ego_translation']: traducción de Lidar a ego (lista 1x3).
    • info['lidar2ego_rotation']: rotación de lidar a vehículo ego (lista 1x4 en formato de cuaternión).
    • info['ego2global_translation']: Traducción de ego a coordenadas globales (lista 1x3).
    • info['ego2global_rotation']: Rotación del vehículo ego a coordenadas globales (lista 1x4 en formato de cuaternión).
    • info['timestamp']: la marca de tiempo de los datos de muestra.
    • info['gt_boxes']: cuadros delimitadores 3D con 7 grados de libertad, una matriz Nx7.
    • info['gt_names']: La categoría del cuadro delimitador 3D, una matriz 1xN.
    • info['gt_velocity']: la velocidad del cuadro delimitador 3D (sin medición vertical debido a la inexactitud), una matriz Nx2.
    • info['num_lidar_pts']: el número de puntos LIDAR contenidos en cada cuadro delimitador 3D.
    • info['num_radar_pts']: el número de puntos de radar contenidos en cada cuadro delimitador 3D.
    • info['valid_flag']: si cada cuadro delimitador es válido. En general, solo consideramos 至少一个cajas 3D que contienen puntos de radar LIDAR o mmWave como cajas válidas

Supongo que te gusta

Origin blog.csdn.net/weixin_36354875/article/details/127127454
Recomendado
Clasificación