IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> Lift-Splat-Shoot:论文、代码解析 -> 正文阅读

[人工智能]Lift-Splat-Shoot:论文、代码解析

一、文章解决的问题

纵观全文和整个代码,这篇文章解决了一个什么事情:解决了多相机融合的问题,而且最重要的是相机是没有深度信息的,在这种没有深度的情况下,我怎么将多副图像融合在一起,而这篇文章通过训练可以自己学习到深度信息。而且据作者所说,其还能避免一定的标定误差。

二、读懂代码关键

在这里插入图片描述
读懂本文需要特别关注的事情:

1.数据处理流程中维度的变换,以及数据的实际意义。

2.矩阵运算:拼接、扩展、加减法、乘积、差积。

3.栅格坐标和空间坐标是怎么转换的,点云怎样投影到栅格中的。

4.模型自己学习深度,在哪里体现的。

所以纵观全文和整个代码,这篇文章解决了一个什么事情:解决了多相机融合的问题,而且最重要的是相机是没有深度信息的,在这种没有深度的情况下,我怎么将多副图像融合在一起,而这篇文章通过训练可以自己学习到深度信息。而且据作者所说,其还能避免一定的标定误差。

三、模型代码解读

输入:BxNxCxHxW(4x6x3x128x352)幅图像数据,以及相机的内外参数矩阵

for batchi, (imgs, rots, trans, intrins, post_rots, post_trans, binimgs) in enumerate(trainloader):
            t0 = time()
            opt.zero_grad()
            preds = model(imgs.to(device),
                    rots.to(device),
                    trans.to(device),
                    intrins.to(device),
                    post_rots.to(device),
                    post_trans.to(device),
                    )
            binimgs = binimgs.to(device)
            loss = loss_fn(preds, binimgs)
            loss.backward()

步骤一:获得像素点云在车体坐标系中的三维空间位置

1.根据图像像素坐标创建截锥体,截锥体的维度为DxfHxfWx3(fH = H/16, fW = W/16),在这里截锥体的维度是41x8x22x3。

注意!!截锥体里保存的数据是什么,实际上是图像像素坐标在下采样之后的像素坐标。其实际意义就是在一个栅格中的图像坐标和深度(u,v,d)。

    def create_frustum(self):
        # make grid in image plane
        ogfH, ogfW = self.data_aug_conf['final_dim']
        fH, fW = ogfH // self.downsample, ogfW // self.downsample
        ds = torch.arange(*self.grid_conf['dbound'], dtype=torch.float).view(-1, 1, 1).expand(-1, fH, fW)
        D, _, _ = ds.shape
        xs = torch.linspace(0, ogfW - 1, fW, dtype=torch.float).view(1, 1, fW).expand(D, fH, fW)
        ys = torch.linspace(0, ogfH - 1, fH, dtype=torch.float).view(1, fH, 1).expand(D, fH, fW)

        # D x H x W x 3
        frustum = torch.stack((xs, ys, ds), -1)
        return nn.Parameter(frustum, requires_grad=False)

2.结合相机的内外参数将截锥体中图像坐标先转化为相机坐标,再转化为车体坐标系的空间坐标(x,y,z)。geom_feats:6x4x41x8x22x3

注意!!这里面的截锥体就生成了单目相机图像的像素在所有可能深度上的车体坐标系的三维空间位置。

    def get_geometry(self, rots, trans, intrins, post_rots, post_trans):
        """Determine the (x,y,z) locations (in the ego frame)
        of the points in the point cloud.
        Returns B x N x D x H/downsample x W/downsample x 3
        """
        B, N, _ = trans.shape

        # undo post-transformation
        # B x N x D x H x W x 3
        points = self.frustum - post_trans.view(B, N, 1, 1, 1, 3)
        points = torch.inverse(post_rots).view(B, N, 1, 1, 1, 3, 3).matmul(points.unsqueeze(-1))

        # cam_to_ego
        points = torch.cat((points[:, :, :, :, :, :2] * points[:, :, :, :, :, 2:3],
                            points[:, :, :, :, :, 2:3]
                            ), 5)
        combine = rots.matmul(torch.inverse(intrins))
        points = combine.view(B, N, 1, 1, 1, 3, 3).matmul(points).squeeze(-1)
        points += trans.view(B, N, 1, 1, 1, 3)

        return points

步骤二:提取图像特征

1.输入图像经过预训练的efficientnet提取特征:4x6x3x128x352 ==> 24x512x8x22

    def get_eff_depth(self, x):
        # adapted from https://github.com/lukemelas/EfficientNet-PyTorch/blob/master/efficientnet_pytorch/model.py#L231
        endpoints = dict()

        # Stem
        x = self.trunk._swish(self.trunk._bn0(self.trunk._conv_stem(x)))
        prev_x = x

        # Blocks
        for idx, block in enumerate(self.trunk._blocks):
            drop_connect_rate = self.trunk._global_params.drop_connect_rate
            if drop_connect_rate:
                drop_connect_rate *= float(idx) / len(self.trunk._blocks) # scale drop connect_rate
            x = block(x, drop_connect_rate=drop_connect_rate)
            if prev_x.size(2) > x.size(2):
                endpoints['reduction_{}'.format(len(endpoints)+1)] = prev_x
            prev_x = x

        # Head
        endpoints['reduction_{}'.format(len(endpoints)+1)] = x
        x = self.up1(endpoints['reduction_5'], endpoints['reduction_4'])
        return x

2.1x1卷积变换图像维度:24x512x8x22 ==> 24x105x8x22

3.接下来将第二个维度105中的前41个数据经过一个softmax作为最后的深度预测,后64的数据作为图像特征,并作乘积,输出的最终图像特征维度:4x6x41x8x22x64

注意!!这里面为后续的splat打下了基础:注意作为深度预测的前41个数据经过了softmax,再和特征做乘积,这样训练出来的特征就是深度相乘的特征,选的越准确,那么softmax其中的一个位置就更接近于1,其余接近0,这样就说明在四十一个深度中选出了最有可能的那一个深度。

    def get_depth_dist(self, x, eps=1e-20):
        return x.softmax(dim=1)

    def get_depth_feat(self, x):
        x = self.get_eff_depth(x)
        # Depth
        x = self.depthnet(x)

        depth = self.get_depth_dist(x[:, :self.D])
        new_x = depth.unsqueeze(1) * x[:, self.D:(self.D + self.C)].unsqueeze(2)

        return depth, new_x

步骤三:图像特征投影到栅格地图

1.首先将x打平:BNDfHfWx64(173184x64):其实际意义为图像像素所有可能深度的特征。

2.现将点云中的所有点平移到正数(有利于后面投影到栅格的矩阵运算),再将点云中的点的空间坐标(x,y,z)转换成栅格坐标。将点云geom_feats打平,并计算每个点对应的batch:BNDfHfW*4(最后一个维度:x,y,z,batch)。

注意!!空间坐标是以米为单位,范围是长宽都是正负50米,转换成栅格之后,单位就变成了单位1,一个格子代表0.5米。此时geom_feats中的点云坐标就是栅格坐标了。

3.剔除边界范围之外的点

4.cumsum:给每个点赋予一个ranks,ranks相等的点在同一个batch中,也在同一个栅格中,将ranks排序并返回排序的索引以至于x,geom_feats,ranks都是按照ranks排序的。接着进行挑选,在同一个格子的所有点的特征相加,放在栅格中。消除掉z维得到最终输出:x:4x64x200x200,其意义为,所有点云投影到栅格地图中每个栅格的特征。
注意!!超级重要:为什么他敢把所有的点的特征相加?

步骤四:最后用resnet18提取栅格地图特征,模型任务完成。

输出:x:4x1x200x200

    def voxel_pooling(self, geom_feats, x):
        B, N, D, H, W, C = x.shape
        Nprime = B*N*D*H*W

        # flatten x
        x = x.reshape(Nprime, C)

        # flatten indices
        geom_feats = ((geom_feats - (self.bx - self.dx/2.)) / self.dx).long()
        geom_feats = geom_feats.view(Nprime, 3)
        batch_ix = torch.cat([torch.full([Nprime//B, 1], ix,
                             device=x.device, dtype=torch.long) for ix in range(B)])
        geom_feats = torch.cat((geom_feats, batch_ix), 1)

        # filter out points that are outside box
        kept = (geom_feats[:, 0] >= 0) & (geom_feats[:, 0] < self.nx[0])\
            & (geom_feats[:, 1] >= 0) & (geom_feats[:, 1] < self.nx[1])\
            & (geom_feats[:, 2] >= 0) & (geom_feats[:, 2] < self.nx[2])
        x = x[kept]
        geom_feats = geom_feats[kept]

        # get tensors from the same voxel next to each other
        ranks = geom_feats[:, 0] * (self.nx[1] * self.nx[2] * B)\
            + geom_feats[:, 1] * (self.nx[2] * B)\
            + geom_feats[:, 2] * B\
            + geom_feats[:, 3]
        sorts = ranks.argsort()
        x, geom_feats, ranks = x[sorts], geom_feats[sorts], ranks[sorts]

        # cumsum trick
        if not self.use_quickcumsum:
            x, geom_feats = cumsum_trick(x, geom_feats, ranks)
        else:
            x, geom_feats = QuickCumsum.apply(x, geom_feats, ranks)

        # griddify (B x C x Z x X x Y)
        final = torch.zeros((B, C, self.nx[2], self.nx[0], self.nx[1]), device=x.device)
        final[geom_feats[:, 3], :, geom_feats[:, 2], geom_feats[:, 0], geom_feats[:, 1]] = x

        # collapse Z
        final = torch.cat(final.unbind(dim=2), 1)

        return final

    def get_voxels(self, x, rots, trans, intrins, post_rots, post_trans):
        geom = self.get_geometry(rots, trans, intrins, post_rots, post_trans)
        x = self.get_cam_feats(x)

        x = self.voxel_pooling(geom, x)

        return x
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:42:06  更:2022-10-08 20:44:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 22:57:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码