《A Simple Baseline for BEV Perception Without LiDAR》论文笔记

本文介绍了一种不依赖LiDAR的BEV特征提取方法,通过反向投影图像特征到BEV网格并进行双线性插值。分析了数据增广、输入图像分辨率、batchsize、参考相机和相机数量、雷达超参数对性能的影响。实验表明,这些因素对BEV感知性能有显著影响,雷达数据虽然不如LiDAR,但仍有帮助。
部署运行你感兴趣的模型镜像

参考代码:bev_baseline
project page:A Simple Baseline for BEV Perception Without LiDAR

1. 概述

介绍:在这篇文章中提出了一种特别简单但效果不错的bev特征提取方法,也就是通过在构建的bev grid中向图像特征进行反向投影,并在投影点处对图像特征进行双线性插值采样得到图像模态下的bev特征。同时对于lidar和radar这些其它模态的传感器信息输入(若有),直接在编码之后与之前bev特征进行concat操作融合,以此来构建多模态bev特征。除开使用该方式进行bev特征构建之外,文章还仔细分析了在网络训练中batchsize、image augmentation、image resolution等超参数给网络性能带来的影响,并对这些变量做了对应消融实验,可为后续模型训练引入参考。此外,之前radar的结果在bev特征构建过程中是不那么重要的,相比lidar确实差挺多的,但是有好歹聊胜于无。在文章的实验结果中也证实了这些数据都是对bev感知效果提升是有用的。另外,文章的backbone为ResNet-101。

首先对bev特征构建的过程进行回顾,这里作者分析了几种bev构建的方案:
在这里插入图片描述

  • 1)对网络提取金字塔特征(也就是不同cnn网络不同stage输出特征)通过网络映射实现在不同深度范围上bev特征映射,其方法也就是左上角的图,实现可以参考:pyramid.py
  • 2)将深度信息隐式编码到网络特征图中构建视锥,从而得到bev特征图,以LSS方法为代表,见右上角图;
  • 3)将bev特征构建任务转换为width-wise的投影任务,见左下角图;
  • 4)首先构建bev grid,并以此作为transformer的queris,从而通过attention的方式得到最后bev特征;

2. 方法设计

2.1 pipeline

文章的方法如下:
在这里插入图片描述
输入的是多模态传感器,这些传感器的信息经过编码之后会统一准还到bev特征下,之后这些特征使用concat进行融合,从而得到完整bev特征。在此基础上对bev解码器进行优化,这里在进行bev特征优化之前会对bev特征在Y维度上进行压缩投影,从而将一个4D特征变换为3D特征,方便后续CNN网络运算。那么对于特征优化过程使用一个resnet-18网络构建一个U型结构去refine bev特征,之后通过不同的预测头实现bev预测。

对于构建bev特征的过程文章使用的是投影之后双线性采样的形式,也就是如下图中所示:
在这里插入图片描述

2.2 bev投影过程

这部分的核心是较为独立的空间坐标变换操作:

# utils/vox.py#291
def unproject_image_to_mem(self, rgb_camB, pixB_T_camA, camB_T_camA, Z, Y, X, assert_cube=False):
    # rgb_camB is B x C x H x W camera特征
    # pixB_T_camA is B x 4 x 4 到相机坐标到图像坐标——内参
    # pixB_T_camA is B x 4 x 4 世界坐标到相机坐标转换——平移和旋转矩阵

    # rgb lives in B pixel coords
    # we want everything in A memory coords

    # this puts each C-dim pixel in the rgb_camB
    # along a ray in the voxelgrid
    B, C, H, W = list(rgb_camB.shape)

    xyz_memA = utils.basic.gridcloud3d(B, Z, Y, X, norm=False, device=pixB_T_camA.device)  # 构建3D空间网格[B,N,3]

    xyz_camA = self.Mem2Ref(xyz_memA, Z, Y, X, assert_cube=assert_cube)  # 将3D空间点映射到图像对应相机坐标维度

    xyz_camB = utils.geom.apply_4x4(camB_T_camA, xyz_camA)
    z = xyz_camB[:,:,2]

    xyz_pixB = utils.geom.apply_4x4(pixB_T_camA, xyz_camA)  # 相机坐标3D空间点到图像特征的映射
    normalizer = torch.unsqueeze(xyz_pixB[:,:,2], 2)
    EPS=1e-6
    # z = xyz_pixB[:,:,2]
    xy_pixB = xyz_pixB[:,:,:2]/torch.clamp(normalizer, min=EPS)  # 除以深度信息得到XY平面坐标
    # this is B x N x 2
    # this is the (floating point) pixel coordinate of each voxel
    x, y = xy_pixB[:,:,0], xy_pixB[:,:,1]
    # these are B x N

    x_valid = (x>-0.5).bool() & (x<float(W-0.5)).bool()  # 计算投影之后XY平面坐标的有效性
    y_valid = (y>-0.5).bool() & (y<float(H-0.5)).bool()
    z_valid = (z>0.0).bool()
    valid_mem = (x_valid & y_valid & z_valid).reshape(B, 1, Z, Y, X).float()

    if (0):
        # handwritten version
        values = torch.zeros([B, C, Z*Y*X], dtype=torch.float32)
        for b in list(range(B)):
            values[b] = utils.samp.bilinear_sample_single(rgb_camB[b], x_pixB[b], y_pixB[b])
    else:  # 实现在图像特征上双线性插值采样
        # native pytorch version
        y_pixB, x_pixB = utils.basic.normalize_grid2d(y, x, H, W)
        # since we want a 3d output, we need 5d tensors
        z_pixB = torch.zeros_like(x)
        xyz_pixB = torch.stack([x_pixB, y_pixB, z_pixB], axis=2)
        rgb_camB = rgb_camB.unsqueeze(2)
        xyz_pixB = torch.reshape(xyz_pixB, [B, Z, Y, X, 3])
        values = F.grid_sample(rgb_camB, xyz_pixB, align_corners=False)

    values = torch.reshape(values, (B, C, Z, Y, X))  # raw 4D的bev特征
    values = values * valid_mem
    return values

2.3 影响性能的一些方面

2.3.1 数据增广

对于数据增广操作,文章对图片颜色、对比度、模糊这些增广操作进行实验,发现其并不像分类任务中那么有效,甚至会带来负面影响。

2.3.2 输入图像分辨率

在这里插入图片描述
对于分辨率并不是呈现单调线型变化关系,文章给出的解释是ResNet-101是在COCO上做过object detection预训练的,其适应了该数据集下的目标尺寸,因而对bev任务在分辨率上存在一定的先验性。

2.3.3 batchsize

在这里插入图片描述
从上表中看出batchsize和性能之间存在着单调正向关联,这篇文章的代码中也通过了梯度累加的形式增大batch。

# train_nuscenes.py#L405
for internal_step in range(grad_acc):
    ...

2.3.4 reference camera和camera nums对性能的影响

在这里插入图片描述
从上表证实reference camera变换会带来涨点,使用全量camera也能带来涨点。

2.3.5 radar超参数带来的影响

在这里插入图片描述

3. 实验结果

vehicle segmentation on nuScenes:
在这里插入图片描述

时序与传感器数据类型对性能的影响:
在这里插入图片描述

您可能感兴趣的与本文相关的镜像

TensorFlow-v2.9

TensorFlow-v2.9

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

由于提供的引用内容中未涉及论文'A Simple Baseline for Spoken Language to Sign Language Translation with 3D Avatars'的具体信息,所以难以直接给出复现该论文研究的具体步骤。不过一般来说,复现一篇论文的研究可以按照以下通用的方法进行: ### 1. 理解论文 仔细研读论文,明确研究的目标、方法、实验设置和主要结论。确定论文中使用的模型架构、算法、数据集等关键信息。 ### 2. 准备数据集 查看论文中使用的数据集,如果数据集是公开的,下载并进行必要的预处理。如果数据集不公开,可能需要寻找类似的替代数据集。 ### 3. 实现模型 根据论文中描述的模型架构,使用合适的深度学习框架(如PyTorch、TensorFlow等)实现模型。在实现过程中,要确保代码的正确性和可复现性。 ### 4. 训练模型 使用准备好的数据集对模型进行训练。设置合适的训练参数,如学习率、批次大小、训练轮数等。同时,要注意处理可能出现的过拟合、欠拟合等问题。 ### 5. 评估模型 使用测试数据集对训练好的模型进行评估,计算论文中使用的评估指标,如准确率、召回率、F1值等。确保评估结果与论文中的结果相近。 ### 6. 调试和优化 如果复现结果与论文中的结果存在较大差异,需要对代码和模型进行调试和优化。可能的原因包括代码实现错误、数据集不一致、训练参数设置不当等。 以下是一个简单的使用PyTorch实现模型训练的示例代码: ```python import torch import torch.nn as nn import torch.optim as optim # 定义一个简单的模型 class SimpleModel(nn.Module): def __init__(self): super(SimpleModel, self).__init__() self.fc1 = nn.Linear(10, 20) self.fc2 = nn.Linear(20, 1) def forward(self, x): x = torch.relu(self.fc1(x)) x = self.fc2(x) return x # 初始化模型、损失函数和优化器 model = SimpleModel() criterion = nn.MSELoss() optimizer = optim.SGD(model.parameters(), lr=0.01) # 模拟训练数据 inputs = torch.randn(100, 10) labels = torch.randn(100, 1) # 训练模型 for epoch in range(100): optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() if (epoch + 1) % 10 == 0: print(f'Epoch {epoch + 1}, Loss: {loss.item()}') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值