<p></p>
讯享网
Pointpillars论文:https://arxiv.org/abs/1812.05784
代码:GitHub - open-mmlab/OpenPCDet: OpenPCDet Toolbox for LiDAR-based 3D Object Detection.
算法复现:基于kitti数据集的3D目标检测算法的训练流程_mini kitti 数据集-CSDN博客
文献理解:PointPillars文献理解_pillar feature net-CSDN博客
复现结果:Pointpillar算法复现结果分析_kitti ap40 results-CSDN博客
参考博客:(三)PointPillars论文的MMDetection3D代码解读——数据处理篇_pointpillars代码-CSDN博客
目录
一、简介
二、配置文件
(一)kitti-3d-3class.py
(二)pointpillars_hv_secfpn_kitti.py
(三)cyclic-40e.py
(四)default_runtime.py
三、kitti数据集处理
(一)kitti_dataset.py
(二)基类Det3DDataset的parse_data_info()函数
(三)KittiDataset的parse_ann_info函数
(四)基类Det3DDataset的parse_ann_info()函数
PointPillars 是一个来自工业界的模型,整体的思想是基于图片的处理框架,直接将点云从俯视图的视角划分为一个个的立方柱体(Pillars),从而构成了伪图片数据,然后再使用2D检测框架进行特征提取和预测得到检测框,从而使得该模型在速度和精度都达到了一个很好的平衡。 PointPillars 的网络结构如图1.1所示。
代码存放于 mmdetection3d/config/_base_/datasets/kitti-3d-3class.py
代码全文如下:
讯享网
以下是分部分解读:
这里是kitti数据集的配置,其中数据类型是kitti的数据集(kittiDataset)、数据根目录在data/kitti、类别名称为“行人、骑行者、汽车”、第四行为点云范围、输入形式为激光雷达【未使用相机视觉】、metainfo是元信息,确定了类别名称。
讯享网
这里是kitti_dbinfos_train.pkl标注文件的读取,data_root定义数据存放的目录、info_path定义信息的路径。
在train_dataloader中定义了数据加载部分的信息,其中Batch_size(批处理大小)设置为6(即一次性处理6位数据),num_workers定义了工作区间的大小为4。
data_root定义数据集的路径、ann_file定义标注文件的路径、data_prefix定义点云文件的路径、pipeline这里用于定义train_pipeline负责读取点云文件和标注文件以及一些数据增强的操作。
train_pipeline定义如下:
讯享网
第一个dict字典用于读取点云文件,第二个dict用于读取标注文件,第三到第九个dict用于点云数据的增强,最后一个dict将点云数据进行打包。
在val_dataloader和test_dataloader中的pipeline都以test_pipeline赋值,下面看test_pipeline定义:
一共三个字典定义,第一个dict用于读取点云文件,第二个dict用于点云数据的增强,第三个dict将点云数据进行打包。
代码路径:mmdetection3d/config/_base_/models/pointpillars_hv_secfpn_kitti.py,全部代码:
讯享网
该代码对应了Pointpillars网络架构的六个步骤:
这一部分对应步骤1,Det3DDataPreprocessor。3D数据的预处理,主要将点云数据进行体素化。
原始点云是三维的,具有(x,y,z)三个坐标轴的坐标,这一步将三维空间中的点云沿着z轴的方向离散到x-y平面上均匀分布的网格中,形成了一组pillars(也就是柱状体),并拥有相对应的索引向量(图中对应的pillar index),引入索引向量之后可以解决点云无序性的问题。需要注意的是:这里pillar是在z轴方向上具有无限范围空间的体素(体积像素 voxel),故而不需要超参数控制z反向的融合/合并。

此时原始点云中的点由三维(x,y,z)扩展成九维(x,y,z,r,xc,yc,zc,xp,yp),其中xyz仍然是空间中的xyz轴坐标,r表示该点的反射强度(reflection),下标c表示该点到整个pillar中所有点的算术平均值的距离,即,x0表示每个点原始的坐标值;下标p表示该点距离pillar中心xy的偏移量。
由于点云的稀疏性,绝大部分的pillar中都是空的,并且非空的pillar中通常也就只有几个点,而作者采用了非常巧妙的方法解决这个问题:通过加强每一个样本(P)中非空pillars的数量和每一个pillar(N)中点数的限制,构造了一个(D,P,N)的密集向量用于减少稀疏性。【即P为样本中非空pillars数量、N为每个pillar中点的数量、D为维度】pillar中点数大于N则随机采样,反之则使用零进行填充来限制点数的数量。
讯享网
这一块对应步骤二,pillarFeatureNet。主要用于提取体素特征、体素编码。
将1中生成的pillars采用简易版的PointNet,对于每一个点使用线性层,接下来是BatchNorm和Relu,生成规格为(C,P,N)的向量,之后再对N个通道进行最大池化操作(maxpooling)生成一个规格为(C,P)的输出向量。线性层可以表示为跨向量的1x1卷积故而可以实现高效率的计算。此时对N个点进行最大池化用于代表整个pillar的信息。
这里对应步骤3,将提取特征的点云形成伪图像。
将1中生成的索引和2中得到的规格为(C,P)的输出向量进行特征向量融合,形成伪图像。
即(P,C)+Pillar_index ——> (H,W,C),得到的是一个通道数位C的伪图像,从而可以使用最经典的图像网络进行处理。H和W分别代表图像的宽度和高度。
讯享网
这一块对应步骤4,主要使用2D bcakbone提取伪图像的特征用于步骤5。
这一块对应步骤5,使用的事SecondFPN结构进行多尺度特征融合。
主干网络有两个子网络:一个自上而下的网络以越来越小的空间分辨率生成特征,第二个网络执行以上采样以及自上而下特征的串联。最终输出的特征将用于检测头的3D边界框的预测。
自顶向下的网络可以用一系列块Block(S,L,F)表征,每个块以步长S(相对于输入伪图像测量)运行,每个块有L个3x3 2D conv层(卷积层)和F个输出通道,每个输出通道后都跟着一个BatchNorm和ReLU。层内第一个卷积步幅为用于确保该快在接受到步幅为的输入blob之后以步幅运行,块中后续卷积的步幅均为1。而最终输出特征是来自不同步长的所有特征的串联。
讯享网
最后这一块对应步骤6,主要使用Anchor3Dhead预测边界框。sizes数组记录了三种anchor,分别为预测的三种类别:行人、骑行者和汽车。loss_cls中分类预测使用的FocalLoss。边界框预测使用的SmoothL1Loss、角度二分类预测使用CrossEntropyLoss【未使用sigmoid作为激活函数,权重为0.2】。
这里定义了模型在训练中采取的策略,assigner中一共三个字典,分别定义了行人、骑行者和汽车三种预测类别的预测框和真实框进行匹配,然后基于匹配预测真值。
讯享网
最后是模型在测试中采用的策略。最后的max_num表示的是测试的时候对NMS的操作,最终只保留50个预测框。
代码存放路径:mmdetection3d/configs/_base_/schedules/cyclic-40e.py,代码如下:
开头的lr表示Learning rate,用于初始化学习率。一共有40个epoch,即运行40轮。
讯享网
这里是优化器的设置。
这里对学习率调度器进行设置,可以看到在前16个epoch中,学习率从0增加到lr*10,而在后24个epoch中,学习率从lr*10下降到lr*1e*-4。
在train_cfg中设置了max_epoch为40,即最大运行轮数为40。
代码存放路径:mmdetection3d/config/_base_/default_runtime.py,代码如下:
讯享网
在default_hooks中主要对默认hook进行设置。
存放路径: mmdetection3d/mmdet3d/datasets/kitti_dataset.py,重点关注kittidataset:
重点解读数据处理的部分:
讯享网
if self.modality['use_lidar']:
首先判断是否采用激光雷达,这里为True故进入第一个if选择结构。
if 'plane' in info:
接着判断原始数据info中是否使用了plane(轨道信息),这里为True故进入第二个if选择结构
plane = np.array(info['plane'])
之后通过np.array(info.[‘plane’])将列表info转换成Numpy数组plane;
lidar2cam = np.array(info['images']['CAM2']['lidar2cam'], dtype=np.float32)
将列表 转换成numpy数组 ;
reverse = np.linalg.inv(lidar2cam)
将Numpy数组lidar2cam进行矩阵求逆得到reverse数组;
(plane_norm_cam, plane_off_cam) = (plane[:3], -plane[:3] * plane[3])
通过Numpy数组plane得到两个新的数组plane_norm_cam和 plane_off_cam;

plane_norm_lidar =
(reverse[:3, :3] @ plane_norm_cam[:, None])[:, 0]
再接下来,通过numpy数组 reverse 的与numpy数组 plane_norm_cam的 矩阵相乘得到一个numpy数组 ,然后再通过索引 [:, 0]取出第0列的数据组成一个新的numpy数组plane_norm_lidar ;
plane_off_lidar = (
reverse[:3, :3] @ plane_off_cam[:, None][:, 0] +
reverse[:3, 3])
通过numpy数组 reverse 的 与numpy数组 plane_off_cam的 矩阵相乘得到一个numpy数组。 ,然后再通过索引 [:, 0]取出第0列的数据组成一个新的numpy数组,再加上numpy数组 reverse 取出第3列的前3个组成的数组,最终得到一个新的numpy数组 plane_off_lidar;
plane_lidar = np.zeros_like(plane_norm_lidar, shape=(4, ))
创建一个形状为 (4, ),类型与 相同的全 0 的numpy数组 ;
plane_lidar[:3] = plane_norm_lidar
通过 plane_norm_lidar 来设置 plane_lidar 的前3个值;
plane_lidar[3] = -plane_norm_lidar.T @ plane_off_lidar
通过负的 plane_off_lidar 转置矩阵 与 plane_norm_lidar 进行矩阵相乘得到的 来设置 plane_lidar 的第4个值;
else:
plane_lidar = None
此处如果我们的 ,所以进入 else 选择结构,将 设置为 None;
info['plane'] = plane_lidar
通过前面得到的 来重新设置 ;
if self.load_type == 'fov_image_based' and self.load_eval_anns:
info['instances'] = info['cam_instances'][self.default_cam_key]
这里我们的 ,if 条件不成立,所以跳过后面的语句;
info = super().parse_data_info(info)
调用基类 Det3DDataset 的 初始化 info 的其它数据。
首先还是,所以进入第一个 if 选择结构;接下来将 设置为 info添加新字段 info添加新字段 ; ,if 条件不成立,所以跳过后面的语句; ,if 条件不成立,所以跳过后面的语句; ,if not 条件成立,所以进入后面的语句;调用派生类 KittiDataset 的 初始化 info[‘ann_info’];
调用基类 Det3DDataset 的 初始化 ann_info;
首先设置一个字典 ;再通过 ,info[‘instances’]是一个字典组成的列表,每个字典包含单个实例的所有标注信息。 ,if 条件不成立,所以跳过 if 后面的语句,进入 else 后面的语句;通过 ;接下来将 ;
之后进入 for 循环,这里以 进行举例,其它的字段以此类推;
- 通过
- ,if 条件不成立,所以跳过 if 后面的语句;
- ,if 条件成立,所以进入 if 后面的语句;
- 通过 ;
- ,if 条件不成立,所以跳过 if 后面的语句;
- ,if 条件成立,所以进入 if 后面的语句;
- 通过 ;
- 在;
遍历完整个 for 循环后,最终得到的
接下来,在 ;
进入 for 循环,;
- ,if 条件成立,所以进入 if 后面的语句;
- 通过 ;
- 将 ,更新前后的值如下图所示;
遍历完整个 for 循环,由于这里第一张图片中只有一个人存在,因此重要 ;最后返回得到的 ann_info 给前面调用的函数中;
之后还会再次返回KittiDataset的parse_ann_info()函数和基类Det3DDataset的parse_ann_info函数中,详细细节可以参考这篇博客:(三)PointPillars论文的MMDetection3D代码解读——数据处理篇_pointpillars代码-CSDN博客

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/182663.html