新闻  |   论坛  |   博客  |   在线研讨会
如何理解自动驾驶,SLAM,BEV,训练数据源常见术语?(3)
计算机视觉工坊 | 2023-08-15 21:50:41    阅读:305   发布文章

先提取图像特征和深度(Feature and Depth,LSS里是同时提取的,后面会具体解释),深度图类似:

图片

图17只能说类似,并不准确,后面也会具体说明的,这个深度信息可以构建一个伪3D模型(Point Cloud点云模式),类似图15:

图片

图18看着还行,但把这个3D模型转到BEV俯视角下,估计亲娘都认不出来了:

图片

图19拍扁后结合特征Feature再做一次语义识别,形成:

图片

图20这个就是喜闻乐见的BEV图了。以上是对LSS的直观认知,算法层面是如何实现的?先给单个相机可拍摄的范围构建一个立方体模样的铁丝笼子(高8宽22深41),祭出大杀器Blender:

图片

图21这里是示意图,不要纠结于格子的数量和尺寸。这个3D网格代表的是一路相机的视锥体(Frustum),前面贴过视锥体的形状(图9),这里变形成立方体,在相机空间里看这个照片和这个立体网格的关系就是:

图片

图22右边是个正对着网格立方体的相机示意图,相片提取深度后(深度图的实际像素尺寸是高8宽22):

图片

图23把这个深度图按照每个像素的深度沿着红线方向展开(Lift)后:

图片

图24可以看到,部分深度像素已经超出了视锥体的范围,因为LSS一开始就假设了这么个有限范围的笼子,超出部分直接过滤掉。这里必须提醒一下:LSS并不是直接算出每个像素的深度,而是推理出每个像素可能处于笼子里每个格子的概率,图24是已经通过Softmax提取出每个像素最有可能位于哪个格子,然后把它装进对应格子的示意结果,便于理解,更准确的描述如下:

图片

图25在图25中选取深度图的某个像素(红色格子,事实上LSS的深度图分辨率是很小的,默认只有8*22像素,所以这里可以用一个格子当做一个像素),它隶属于笼子下方边沿的一条深度格子(这条格子其实就代表相机沿着深度看向远方的一条视线):

图片

图26图25中的那个红色的深度像素,沿着图26这条视线格子的概率分布就是:

图片

图27黄线的起伏表示2D深度图像素在Lift后沿着视线3D深度的概率分布(Depth Distribution,我这是示意性得画法,不是严格按照实际数据做的)。等价于LSS论文里的这张图:

图片

图28


LSS中构建立方笼子的代码位于:

class LiftSplatShoot(nn.Module):
   def __init__(self, grid_conf, data_aug_conf, outC):
       self.frustum = self.create_frustum()
   def create_frustum(self):
       # D x H x W x 3
       frustum = torch.stack((xs, ys, ds), -1)
       return nn.Parameter(frustum, requires_grad=False)
   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


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客