本篇博文讲一下mmdetection3d可视化

参考文献:

带你玩转 3D 检测和分割 (三):有趣的可视化 - 知乎 (zhihu.com)

Welcome to MMDetection3D’s documentation! — MMDetection3D 1.0.0rc4 文档

1、介绍

让我们看一下ChatGPT的回答[手动狗头]:

mmdetection3D是基于PyTorch框架的3D目标检测工具包,它是mmdetection的3D扩展版本。它提供了一个灵活且高效的框架,可以训练和测试各种3D目标检测算法,包括点云、体积数据和混合数据。

mmdetection3D的主要特点包括:

灵活的模块化设计:模块化设计使得用户可以轻松地构建自己的检测算法,并且可以很方便地替换各种组件,如骨干网络、头部网络和损失函数等。 高效的训练和推断:mmdetection3D支持分布式训练,可以在多GPU和多机器上进行训练。此外,它还支持多线程数据加载和多进程测试,从而提高了训练和推断的效率。 多样化的数据格式支持:mmdetection3D支持多种3D数据格式,包括点云、体积数据和混合数据。同时,它还支持多种数据增强方法,从而可以生成更多的训练数据,提高模型的鲁棒性。 容易使用的API:mmdetection3D提供了易于使用的API,用户可以轻松地使用它进行模型训练、测试和部署。 总之,mmdetection3D是一个强大且易于使用的3D目标检测工具包,它可以帮助研究人员和工程师快速地开发和部署各种3D目标检测算法。

mmdetection3d也提供了众多预训练模型,可以让我们很容易的了解一下3D目标检测的整个流程

2、需求

本次需求较为简单,主要是使用预训练模型,完成推理,并将结果绘制到图像中,便于可视化

结合实际,我需要得到的结果精度尽可能高,所以我选择了MVXNet这一多模态融合的检测方案

3、API分析

mmdetection3d提供了大量封装好的API,我们可以直接拿来用。本次使用到的API如下所示:

init_model: 通过配置文件、chekpoint_file(可选)构建一个模型 build_datasets:通过配置文件,构建数据集,得到包含所有数据的列表 show_multi_modality_result:将3D bbox投影到图像,并保存 inference_multi_modality_detector:构建多模态检测器,稍后会详细解释各个参数。如果不选用多模态方案,此处可以选择其他的API,有时间会写一下

4、实战

4.1 inference_multi_modality_detector解读

我们先来看一下最关键的inference_multi_modality_detector,它位于mmdet3d/apis/inference.py中,代码我就不贴了,我们看一下它的参数:

Args:

model (nn.Module): The loaded detector.

pcd (str): Point cloud files.

image (str): Image files.

ann_file (str): Annotation files.

Returns:

tuple: Predicted results and data from pipeline.

"""

它接收一个模型、点云文件、图像文件、还有参数文件。模型、点云、图像一眼明白,这个ann_file大家可能会觉得一头雾水,demo/data/kitti下给我们了一个样例注释文件,我们使用下面代码看一下这个参数文件里有什么

import pickle

with open('demo/data/kitti/kitti_000008_infos.pkl', 'rb') as f:

data = pickle.load(f)

print(data)

输出如下,是一个长度为1的列表,列表项为字典,里面记录了图像、点云路径,还有一些内参外参,投影矩阵巴拉巴拉巴拉:

[{'image': {'image_idx': 8, 'image_path': 'training/image_2/000008.png', 'image_shape': array([ 375, 1242])}, 'point_cloud': {'num_features': 4, 'velodyne_path': 'training/velodyne/000008.bin'}, 'calib': {'P0': array([[721.5377, 0. , 609.5593, 0. ],

[ 0. , 721.5377, 172.854 , 0. ],

[ 0. , 0. , 1. , 0. ],

[ 0. , 0. , 0. , 1. ]]), 'P1': array([[ 721.5377, 0. , 609.5593, -387.5744],

[ 0. , 721.5377, 172.854 , 0. ],

[ 0. , 0. , 1. , 0. ],

[ 0. , 0. , 0. , 1. ]]), 'P2': array([[7.215377e+02, 0.000000e+00, 6.095593e+02, 4.485728e+01],

[0.000000e+00, 7.215377e+02, 1.728540e+02, 2.163791e-01],

[0.000000e+00, 0.000000e+00, 1.000000e+00, 2.745884e-03],

[0.000000e+00, 0.000000e+00, 0.000000e+00, 1.000000e+00]]), 'P3': array([[ 7.215377e+02, 0.000000e+00, 6.095593e+02, -3.395242e+02],

[ 0.000000e+00, 7.215377e+02, 1.728540e+02, 2.199936e+00],

[ 0.000000e+00, 0.000000e+00, 1.000000e+00, 2.729905e-03],

[ 0.000000e+00, 0.000000e+00, 0.000000e+00, 1.000000e+00]]), 'R0_rect': array([[ 0.9999239 , 0.00983776, -0.00744505, 0. ],

[-0.0098698 , 0.9999421 , -0.00427846, 0. ],

[ 0.00740253, 0.00435161, 0.9999631 , 0. ],

[ 0. , 0. , 0. , 1. ]]), 'Tr_velo_to_cam': array([[ 7.533745e-03, -9.999714e-01, -6.166020e-04, -4.069766e-03],

[ 1.480249e-02, 7.280733e-04, -9.998902e-01, -7.631618e-02],

[ 9.998621e-01, 7.523790e-03, 1.480755e-02, -2.717806e-01],

[ 0.000000e+00, 0.000000e+00, 0.000000e+00, 1.000000e+00]]), 'Tr_imu_to_velo': array([[ 9.999976e-01, 7.553071e-04, -2.035826e-03, -8.086759e-01],

[-7.854027e-04, 9.998898e-01, -1.482298e-02, 3.195559e-01],

[ 2.024406e-03, 1.482454e-02, 9.998881e-01, -7.997231e-01],

[ 0.000000e+00, 0.000000e+00, 0.000000e+00, 1.000000e+00]])}, 'annos': {'name': array(['Car', 'Car', 'Car', 'Car', 'Car', 'Car', 'DontCare', 'DontCare',

'DontCare', 'DontCare'], dtype='

-1. ]), 'occluded': array([ 3, 1, 3, 1, 0, 0, -1, -1, -1, -1], dtype=int64), 'alpha': array([ -0.69, 2.04, -1.84, -1.33, 1.74, -1.65, -10. , -10. ,

-10. , -10. ]), 'bbox': array([[ 0. , 192.37, 402.31, 374. ],

[ 334.85, 178.94, 624.5 , 372.04],

[ 937.29, 197.39, 1241. , 374. ],

[ 597.59, 176.18, 720.9 , 261.14],

[ 741.18, 168.83, 792.25, 208.43],

[ 884.52, 178.31, 956.41, 240.18],

[ 800.38, 163.67, 825.45, 184.07],

[ 859.58, 172.34, 886.26, 194.51],

[ 801.81, 163.96, 825.2 , 183.59],

[ 826.87, 162.28, 845.84, 178.86]]), 'dimensions': array([[ 3.23, 1.6 , 1.57],

[ 3.68, 1.57, 1.5 ],

[ 3.08, 1.39, 1.44],

[ 3.66, 1.47, 1.6 ],

[ 4.08, 1.7 , 1.63],

[ 2.47, 1.59, 1.59],

[-1. , -1. , -1. ],

[-1. , -1. , -1. ],

[-1. , -1. , -1. ],

[-1. , -1. , -1. ]]), 'location': array([[ -2.7 , 1.74, 3.68],

[ -1.17, 1.65, 7.86],

[ 3.81, 1.64, 6.15],

[ 1.07, 1.55, 14.44],

[ 7.24, 1.55, 33.2 ],

[ 8.48, 1.75, 19.96],

[-1000. , -1000. , -1000. ],

[-1000. , -1000. , -1000. ],

[-1000. , -1000. , -1000. ],

[-1000. , -1000. , -1000. ]]), 'rotation_y': array([ -1.29, 1.9 , -1.31, -1.25, 1.95, -1.25, -10. , -10. ,

-10. , -10. ]), 'score': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]), 'index': array([ 0, 1, 2, 3, 4, 5, -1, -1, -1, -1]), 'group_ids': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), 'difficulty': array([-1, 1, -1, 1, 1, 0, -1, -1, -1, -1]), 'num_points_in_gt': array([1325, 1900, 881, 659, 55, 162, -1, -1, -1, -1])}}]

4.2 获取ann_file

要想使用inference_multi_modality_detector进行推理,就必须获取这个关键的ann_file,我们使用mmdetection3d中搭建完环境后,就必须使用其提供的tools组织数据集,最后会生成若干pkl文件(适用于点云)和json(适用于图像)。我们基于KITTI数据集,获取组织好的pkl文件,这里使用训练集kitti_infos_train.pkl,用上面查看pkl文件的代码看一下,大同小异,只不过是列表的长度变长了,为了便于inference_multi_modality_detector使用,我们把列表拆分,逐个存储,下面代码说明如何获取每个点云/图像对应的ann_file:

import pickle

# 读取KITTI数据集训练组织文件

with open('pkl/kitti_infos_train.pkl', 'rb') as f:

data = pickle.load(f)

print("训练集长度:", len(data))

use_num = 50 # 取训练集的前50条数据(根据自己需求定)

print(data[0]['image']['image_path'].split('/')[-1].split('.')[0]) # 拆分出文件名来

for i in range(0, use_num, 1):

list = []

list.append(data[i])

cur_data = list # 将当前注释存储到列表

print(cur_data)

file_name = data[i]['image']['image_path'].split('/')[-1].split('.')[0]

save_path = 'kitti_pkl_output/'

# 保存文件

with open(save_path + 'kitti_' + file_name + '_infos.pkl', "wb") as f:

pickle.dump(cur_data, f)

最终得到一系列pkl文件:

4.3 构建模型并完成推理

构建模型 from mmdet3d.apis import init_model

# 构建预训练模型

config_file = '/home/wistful/work/mmdetection3d/configs/my_config/my_dv_mvx-fpn_second_secfpn_adamw_2x8_80e_kitti-3d-3class.py'

chekpoint_file = '/home/wistful/ResultDir/my_pth/mxvnet/dv_mvx-fpn_second_secfpn_adamw_2x8_80e_kitti-3d-3class_20210831_060805-83442923.pth'

model = init_model(config_file, chekpoint_file, device='cuda:0')

构建数据集 # 构建数据集,此处选用KITTI多模态数据,便于可视化

from mmdet3d.datasets import build_dataset

from mmcv import Config

import os

os.chdir('/home/wistful/work/mmdetection3d/')

config_file = 'configs/_base_/datasets/kitti-3d-3class-multi.py'

cfg = Config.fromfile(config_file)

datasets = [build_dataset(cfg.data.train)]

为什么要使用配置文件这样构建数据集,因为4.1中也提到了,inference_multi_modality_detector需要同时接收点云和图像文件作为输入,使用上述方案构建数据集,可以很方便的获取,每一项数据都包含了图像信息、点云、图像、地面真相等信息,我们只需要遍历就可以了 推理并保存可视化图像 # 遍历n条数据用于可视化

from mmdet3d.core.visualizer import show_multi_modality_result

from mmdet3d.apis import inference_multi_modality_detector

out_dir = "/home/wistful/work/mmdetection3d/visual_img/kitti/"

pkl_dir = '/home/wistful/work/mmdetection3d/data/kitti/kitti_pkl_output/'

num = 50

for i in range(0, num, 1):

cur_data = datasets[0][i] # 遍历数据集

img_metas = cur_data.get('img_metas').data # 获取图像原始信息

pts_file = img_metas.get('pts_filename') # 获取点云

img = cur_data.get('img').data # 获取图像

img_file_path = img_metas.get('filename') # 获取图像文件名

name = img_file_path.split('/')[-1].split('.')[0] # 分离名称

ann_file = pkl_dir + 'kitti_' + name + '_infos.pkl' # 得到对应ann_file

project_mat = img_metas.get('lidar2img') # 获取投影矩阵

result, data = inference_multi_modality_detector(model, pts_file, img_file_path, ann_file) # 推理

bboxes_data = result[0]['pts_bbox']['boxes_3d'] # 提取结果中的3D bbox

# 保存可视化图像

show_multi_modality_result(img=image,

box_mode='lidar',

gt_bboxes=None,

img_metas=img_metas,

pred_bboxes=bboxes_data,

proj_mat=project_mat,

out_dir="/home/wistful/work/mmdetection3d/visual_img/kitti/",

filename=name,

show=False)

我还对show_multi_modality_result做了下修改,只产生预测,并将结果保存在同一个文件夹中,这个很简单,就不展开了

5、结果

相关文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: