南宫NG28如何理解自动驾驶SLAMBEV训练数据源常见术语?(4)实际上是在照片坐标系(uv)上拓展了一个深度Z构成的新坐标系。由于LSS默认是5路摄像头,把5个Frustum送到get_geometry函数里,会输出5路Frustum构成的一个组合笼子南宫NG28,其张量尺寸变为:B x N x D x H x W x 3,其中B是batch_size,默认是4组训练数据,N是相机数量5。
这玩意是干啥的?这跟训练集有关,在深度学习里里,有一种增强现有训练样本的方法,一般叫做Augmentation(其实AR技术里这个A就是Augmentation,增强的意思),通过把现有的训练数据做一些随机的:翻转/平移/缩放/裁减,给样本添加一些随机噪音(Noise)。比如,在不做样本增强前,相机的角度是不变的,训练后的模型只认这个角度的照片,而随机增强后再训练,模型可以学习出一定角度范围变化内的适应性,也就是Robustness。
图30Augmentation技术也是有相关理论和方法的,这里就贴个图不赘述了。数据增强的代码一般都是位于DataLoader内:
回到刚才的get_geometry,数据增强会给照片增加一些随机变化,但相机本身是必须固定的,这样才能让DNN模型学习这些随机变化的规律并去适应它们。所以将5路Frustum的安置到车身坐标系时候要先去掉(undo)这些随机变化。然后通过:
将各路Frustum从相机坐标系转入车辆自身坐标系,注意这里的intrins是相机内参,rots和trans是相机外参,这些都是nuScenes训练集提供的,这里只有intrincs用了逆矩阵,而外参没有,因为nuScenes是先把每个相机放在车身原点,然后按照各路相机的位姿先做偏移trans再做旋转rots,这里就不用做逆运算了。如果换个数据集或者自己架设相机采集数据,要搞清楚这些变换矩阵的定义和计算顺序。四视图大概就是这个样子:
trunk用于同时推理原始的深度和图片特征,depthnet用于将trunk输出的原始数据解释成LSS所需的信息,depthnet虽是卷积网但卷积核(Kernel)尺寸只有1个像素,功能接近一个全连接网FC(Full Connected),FC日常的工作是:分类或者拟合,对图片特征而言,它这里类似分类,对深度特征而言南宫NG28,它这里类似拟合一个深度概率分布。EfficientNet是一种优化过的ResNet,就当做一个高级的卷积网(CNN)看吧。对于这个卷积网而言,图片特征和深度特征在逻辑上没有区别,两者都位于trunk上的同一个维度,只是区分了channel而已。这就引出了另外一个线D图片上是如何推理/提取深度特征的。这类问题一般叫做:Monocular Depth Estimation,单目深度估计。一般这类系统内部分两个阶段:粗加工(Coarse Prediction)和精加工(Refine Prediction),粗加工对整个画面做一个场景级别的简单深度推测,精加工是在这个基础上识别更细小的物体并推测出更精细的深度南宫NG28。这类似画家先用简笔画出场景轮廓,然后再细致勾勒局部画面。除了用卷积网来解决这类深度估计问题,还有用图卷积网(GCN)和Transformer来做的,还有依赖测距设备(RangeFinder)辅助的DNN模型,这个话题先不展开了,庞杂程度不亚于BEV本身。那么LSS这里仅仅采用了一个trunk就搞定深度特征是不是太儿戏了,事实上确实如此。LSS估计出的深度准头和分辨率极差,参看BEVDepth项目里对LSS深度问题的各种测试报告:BEVDepth的测试里发现:如果把LSS深度估计部分的参数换成一个随机数,并且不参与学习过程(Back Propagation),其BEV的总体测试效果只有很小幅度的降低。但必须要说明,Lift的机制本身是很强的,这个突破性的方法本身没问题,只是深度估计这个环节可以再加强。
LSS的训练过程还有另外一个问题:相片上大约有1半的数据对训练的贡献度为0,其实这个问题是大部分BEV算法都存在的:
图32右边的标注数据实际上只描述了照片红线以下的区域,红线上半部都浪费了,你要问LSS里的模型对上半部都计算了些什么,我也不知道,因为没有标注数据可以对应上,而大部分的BEV都是这么训练的,所以这是一个普遍现象。训练时,BEV都会选择一个固定面积范围的周遭标注数据,而照片一般会拍摄到更远的景物,这两者在范围上天生就是不匹配的,另一方面部分训练集只关注路面标注,缺乏建筑,因为眼下BEV主要解决的是驾驶问题,不关心建筑/植被。这也是为什么图17哪里的深度图和LSS内部真实的深度图是不一致的,真实深度图只有接近路面这部分才有有效数据:
图33所以整个BEV的DNN模型势必有部分算力被浪费了。目前没看到任何论文关于这方面的研究。
这里的new_x是把深度概率分布直接乘上了图片纹理特征,为了便于直观理解,我们假设图片特征有3个channel:c1,c2,c3,深度只有3格:d1,d2,d3。我们从图片上取某个像素,那么它们分别代表的意义是:c1:这个像素点有70%的可能性是车子,c2:有20%的可能性是路,c3:有10%的可能性是信号灯, d1:这个像素有80%的可能是在深度1,d2:有15%的可能性是在深度2,d3:有%5的可能性是在深度3上。如果把它们相乘的到:
�=α�⋅�公式的意义,注意它这里把图像特征叫做c(Context), a_d的意义是深度沿视线格子的概率分布,d是深度。new_x就是这个计算结果。前面说过,由于图像特征和深度都是通过trunk训练出来的,它们位于同一维度,只是占用channel不同,深度占用了前self.D(41)个channel,Context占用了后面self.C(64)个channel。由于new_x是分别按照每路相机的Frustum单独计算的,而5个Frustum有重叠区域,须要做作数据融合,所以在voxel_pooling里计算好格子的索引和对应的空间位置,通过这个对应关系,把new_x的内容一一装入指定索引的格子。LSS在voxel_pooling的计算力引入了cumsum这个机制,虽然有很多文章在解释它,但这里不建议花太多功夫,它只是一个计算上的小技巧,对整个LSS是锦上添花的事,不是必要的。