Apollo 6.0点云检测模型的训练, 基于TensorRT和ROS的推理

本文介绍Apollo6.0中的点云目标检测方法,基于深度学习改进三维点云模型推理,通过PointPillars算法实现自动驾驶场景下的目标检测,并提供ROS环境下模型移植和PyTorch环境下的训练指导。

Apollo6.0点云模型的训练, 基于ROS和TensorRT进行推理

三维点云目标检测


深度学习三维点云模型推理,
为啥需要学习三维点云, 因为可用很好探测三维空间,特别是自动驾驶领域越来越多,
为啥又需要深度学习三维点云,可以更好的分类,基于SVM等点云分类方法,也许只能达到80%的准确率, 深度学习只会高些;

三维点云目标检测思路之一:
如下图所示,先进行点云编码检测网络后处理
CNN包括(backbone、head、neck,loss)
那么PointPillars可如下图所示:

点云编码:前处理和点云特征学习;
检测网络:2D CNN和Head SSD;
后处理:

在这里插入图片描述


1: apollo检测模型简介

根据apllo6.0的代码 , 分成4步对 Lidar 核心逻辑流程进行叙述。
1.1 点云编码

a. 点云前处理, 分柱子

把俯视图分成 H × W个小方格子,再沿着z轴向上拉就成了柱体
每个网格所对应的柱子中的每一个点取:
x, 每个点的真实位置坐标
y, 每个点的真实位置坐标
z, 每个点的真实位置坐标
r, 每个点的真实反射率
x_c,点相对于柱子中心的偏差
y_c,点相对于柱子中心的偏差
z_c,点相对于柱子中心的偏差
x_p,点相对于网格中心的偏差
y_p,点相对于网格中心的偏差
但是,这样完全没有对点云进行编码,需要进一步学习

    def forward(self, pillar_x, pillar_y, pillar_z, pillar_i, num_voxels, x_sub_shaped, y_sub_shaped, mask):
        pillar_xyz =  torch.cat((pillar_x, pillar_y, pillar_z), 1)
        points_mean = pillar_xyz.sum(dim=3, keepdim=True) / num_voxels.view(1, 1, -1, 1)
        f_cluster = pillar_xyz - points_mean
        f_center_offset_0 = pillar_x - x_sub_shaped
        f_center_offset_1 = pillar_y - y_sub_shaped
        f_center_concat = torch.cat((f_center_offset_0, f_center_offset_1), 1)
        pillar_xyzi = torch.cat((pillar_x, pillar_y, pillar_z, pillar_i), 1)
        features_list = [pillar_xyzi, f_cluster, f_center_concat]
        features = torch.cat(features_list, dim=1)
        masked_features = features * mask
        pillar_feature = self.pfn_layers[0](masked_features)
        return pillar_feature

b. 点云前处理, 点云编码

一个简化的PointNet从D维中学出C个channel来最终可以展开成一个伪图像形式,H,W为宽高,C为通道数。
前处理网络思路:
每个柱子中点多于N的进行采样,少于N的进行填充0。于是就形成了(D,P,N)D=9, N为每个pillar的采样点数(设定值),P为pillar总数目,H*W。这样点云数据就表达成了一个(D,P,N)的Tensor.然后卷积,得到一个(C,P,N)的Tensor.在N这个维度上做max operation.得到(C,P)的tensor.变形得(C,H,W)tensor.
至此,
用一个(C,H,W)的tensor完成了点云数据的表达.
也是后续检测网络的前处理部分,
同时移植TensorRT也可生成onnx模型;
在这里插入图片描述

如下简化了VoxelNet的点云编码方式:
采用PFE方式
在这里插入图片描述

由于代码基于VoxelNet修改的,所以onnx输入为 pillar_x, pillar_y, pillar_z, pillar_i,
num_voxels, x_sub_shaped, y_sub_shaped, mask;
最后再转换为pointpillars的输入

    def forward(self, pillar_x, pillar_y, pillar_z, pillar_i, num_voxels, x_sub_shaped, y_sub_shaped, mask):
        pillar_xyz =  torch.cat((pillar_x, pillar_y, pillar_z), 1)
        points_mean = pillar_xyz.sum(dim=3, keepdim=True) / num_voxels.view(1, 1, -1, 1)
        f_cluster = pillar_xyz - points_mean
        f_center_offset_0 = pillar_x - x_sub_shaped
        f_center_offset_1 = pillar_y - y_sub_shaped
        f_center_concat = torch.cat((f_center_offset_0, f_center_offset_1), 1)
        pillar_xyzi = torch.cat((pillar_x, pillar_y, pillar_z, pillar_i), 1)
        features_list = [pillar_xyzi, f_cluster, f_center_concat]
        features = torch.cat(features_list, dim=1)
        masked_features = features * mask
        pillar_feature = self.pfn_layers[0](masked_features)
        return pillar_feature

在这里插入图片描述

在这里插入图片描述

class PFNLayer(nn.Module):
    def __init__(self,
                 in_channels,
                 out_channels,
                 use_norm=True,
                 last_layer=False):
        super().__init__()
        self.name = 'PFNLayer'
        self.last_vfe = last_layer
        if not self.last_vfe:
            out_channels = out_channels // 2
        self.units = out_channels
        self.in_channels = in_channels

        self.linear= nn.Linear(self.in_channels, self.units, bias = False)
        self.norm = nn.BatchNorm2d(self.units, eps=1e-3, momentum=0.01)

        self.conv1 = nn.Conv2d(in_channels=self.in_channels, out_channels=self.units, kernel_size=1, stride=1)
        self.conv2 = nn.Conv2d(in_channels=100, out_channels=1, kernel_size=1, stride=1)

        self.t_conv = nn.ConvTranspose2d(100, 1, (1,8), stride=(1,7))
        self.conv3 = nn.Conv2d(64, 6
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值