Advertisement

自动驾驶~BEV和SLAM

阅读量:

Birds-Eyes-View(BEV): 这个术语在一般情况下没有特殊含义。随着自动驾驶技术的发展而逐渐成为行业内使用的术语。

Simultaneous Location and Mapping (SLAM):相较于基于BEV的另一种感知手段而言,并行定位与地图绘制是一种重要的实时三维位置估计技术

Perception: 感知技术为自动驾驶系统提供实时信息以识别周围环境中的障碍物和车辆位置,并确定这些障碍物是否静态或移动以及它们的具体方位和距离等关键数据。通过这些信息的准确获取和分析,在后续的驾驶决策中能够实现安全可靠的行驶操作。

SLAM与BEV的比较:基于多种传感器收集周边环境中的物体结构信息,并通过三维数据表征这些信息;同样依赖于传感器收集周边环境的状态信息,并以二维数据表征这些状态信息。从应用领域来看目前SLAM的应用范围更为广泛,在深度学习尚未普及之前主要应用于VR/AR等场景中;而BEV则主要集中在自动驾驶相关领域中。从技术实现的角度而言更多依赖于传统的数学工具包括几何学、概率论、图论以及群论等领域的软件包;其中DNN则是其主流的技术架构。两者不应被简单对立看待在许多情况下能够相互补充作用

以下将侧重于BEV的基础介绍。

SLAM和BEV作为最核心的传感器技术主要依靠相机(Camera),因此在计算过程中对算力的需求主要集中在图像信息提取、识别以及空间变换计算上。SLAM技术主要依赖于图像中的基础特征点(Feature)进行定位与建图,在此基础上实现场景结构与相机自身位姿的估计。相比之下,BEV技术则更加注重对车辆、道路、行人以及障碍物等高级特征信息的感知与处理

相机具有两个基本数据参数:内参数(Instrinsics)与外参数(Extristics)。其中内参数详细说明了相机的CCD或CMOS感光元件尺寸、分辨率以及镜头光学特性等关键参数;而外参数则具体指出了相机在世界坐标系中的放置位置及其指向方向。

其中内参的常见矩阵是:

其中fx和fy分别代表光学镜头的横向(horizontal)和纵向(vertical)焦距长度(focus)。通常情况下,在无特殊说明时这些焦距值在各个方向上是相同的。然而由于CCD/CMOS传感器上的像素单元并非完美对称,在实际应用中即使是一个绝对标准的正方形像素单元也无法保证其在所有方向上的几何特性完全一致。因此当满足特定条件时比如一个完美的正方形像素单元此时fx将严格等于fy;但实际上由于制造工艺和技术限制这种完全一致的情况难以实现存在微小的差异程度因此相机模块制造商会测定这一差异并提供相应的fx和fy参数供开发者使用或者通过标定过程精确测定这些参数。

另外,在传统光学领域中,默认使用毫米作为fx和fy的单位:mm;而在该领域的实践中,默认使用像素作为单位:Pixel;这让许多拥有摄影经验的人感到困惑——因为这些数值往往显得非常大(often reaching thousands),甚至超过了业余天文望远镜的能力范围:这使得许多人感到难以理解。那么为何这里采用像素作为单位?为了更好地理解这一现象(phenomenon),我们可以利用相机内参参数计算其视场角(Field of View)。

图3

这里fy代表纵向焦距值(pixels),而h代表照片的高度(pixels)。由于h具有pixel级别的分辨率,则为了确保一致性与便于后续操作,默认将f y设定为pixels。因此,在图像处理中,默认使用pixel作为基本单位进行计算与转换操作较为方便;实际上,并不需要等到计算机进行相关计算这一步;CCD/CMOS传感器通常需要集成一块额外的芯片(如Image Signal Processor),用于将模拟信号转换为数字图像数据;在这种情况下,则可以直接采用pixel作为基本单位进行处理。

注:以上改写遵循以下原则:

  1. 仅对表达方式进行调整未改变原意
  2. 使用了同义词替换(如"居中"→"中心区域")
  3. 调整了句式结构(如将主动句改为被动句)
  4. 保持了所有技术术语和技术指标的原样
  5. 未添加任何额外信息或解释
  6. 未进行任何语言翻译

三维空间中描述旋转计算方式主要有两种:一种基于矩阵运算的方法(Matrix),另一种采用四元数(Quaternion)来进行表示与变换。为了避免矩阵方法所带来的万向节死锁(Gimbal Lock)问题,在相关领域中通常倾向于选择四元数作为旋转计算的核心工具。然而,在自动驾驶(AD)领域中却鲜见这种做法:由于车载相机通常固定安装于车辆顶部并垂直于地面(一般取Z轴方向),因此仅会在垂直方向上实现360度自由度运动而不涉及万向节问题;因此无需强迫用户在存在翻车风险的情况下坚持实现自动驾驶功能这一苛刻需求。因此,在贝视图(BEV)代码中通常仍采用矩阵形式进行处理;而SLAM算法由于还应用于AR和其他领域,在这些场景下相机不再是相对固定的装置;因此会采用四元数来进行建模与计算以提高精度与稳定性。值得注意的是,在自动驾驶相关研究中外参参数多以仿射矩阵(Affine Matrix)的形式表示;这与计算机图形学(CG)领域中的三维重建方法存在显著差异

另外,在一般文章中介绍内参时还会涉及旋转偏差。这是因为CCD/CMOS感光片在工厂生产过程中会被机器调校不正导致的误差存在;不过,在AD领域通常忽略这一误差是因为其对最终结果的影响微乎其微;而当相机安装于车辆上时自身产生的外参变化与前者的差异较大;这种情况下建议一并解决以避免后续处理中的干扰;而DNN学习算法可以通过数据过滤有效地消除这些干扰项;相反地,在AR领域中的SLAM技术则需要主动计算外参从而避免上述问题

掌握内外参数之后,在理解几何关系的基础上开始学习相机标定是更为高效的方式

该世界坐标系(World Coordinate)代表真实世界空间中车辆的位置与方向角。传统的定位手段通常是通过全球导航卫星系统(GNSS)来实现的。其中GNSS包括美国GPS、中国BDS、欧洲Galileo、日本QZSS以及印度IRNSS等多个系统共同作用。通常将标称精度定义为:在理想条件下即车辆处于空旷地区拥有多颗定位卫星覆盖并具备足够坚固的大天线且无其他干扰信号源的情形下进行测试所达到的效果。

在城市内周遭矗立着 numerous tall buildings, 各种电磁干扰源不断干扰信号传输, 卫星时而出现时而消失于天际, 车速维持在较高水平的情况下, 偏移几十米仍能勉强满足定位精度要求。针对这一问题, 常见的解决方案包括差分基站校正与基于道路网络的大规模数据辅助定位。这种定位方式看似精确无误, 实则存在一定的误差范围: 无论采取何种方法, 最终所得的位置坐标均为经纬度数值表示, 然而与常规GIS系统的球面坐标系不同, AD系统的经纬度采用平面直角坐标系展开呈现, 这种差异主要体现在投影方式上的不同选择上。例如, Google Maps会将WGS84椭球面坐标转换为其自家地图使用的矩形切片编码系统; 安卓平台上的Uber公司采用的是六边形切片的hexagonal cell-based indexing系统; 而百度地图则是在火星坐标的基础上叠加了一个BD09扩展的矩形切片坐标系方案等

这些是基于绝对坐标的确定位置,并且基于高精度地图的数据框架,在此基础上还引入了一些相对定位信息。无论如何,最终在代码中仅记录了车辆的位置坐标X和Y值。然而,这些系统无法直接测定车辆的行进方向。因此,在AD系统中所记录的角度数据是指车辆运动轨迹的方向指向。通过计算当前位置与上一状态的位置差值来确定车辆运动的方向向量。当然在高精度地图的支持下,从而可以用SLAM技术计算出车辆实时所在方位角。当GPS信号受到影响无法使用时,比如在隧道这样的特殊环境中,则需要用IMU等惯性测量单元芯片进行辅助定位。这些数值表示的是相对于当前位置的一个偏移量,并且随着时间推移这种误差会逐渐累积增大。因此,在长时间没有GPS信号支持的情况下,这种辅助导航方法的效果也会逐渐减弱

2、BEV训练数据集的世界坐标系(nuScenes World Coordination, 其它训练集就不特别说明了),这个跟GNSS的绝对坐标系就不同了:

图5

这个nuScenes地图中,默认设置下其世界坐标系与图片坐标系一致;其中的世界坐标系以图片左下角为原点,默认单位为米;在这种情况下,在使用训练数据集进行分析或建模时,默认无需考虑地理经纬度信息;该数据集通过时间序列提供车辆在各个瞬间的位置信息;即对应于该图片中的XY坐标。

3、以车为基准的坐标系(Ego Coordinate System),在贝雷特坐标系(BEBV)中该系统特指安装于车辆上的设备。这些设备包括摄像头、激光雷达(Lidar, 简称LiDAR)以及毫米波雷达(通常用Radar表示)。这些传感器的安装位置均以米为单位,并且有明确的朝向方向。其中坐标原点通常位于车身几何中心位置,并按照统一方向进行定位与计算;其朝向方向如图所示

图6

因此车头正放的相机默认设置为Yaw(Z轴)为0度角的位置,并通过Extrinsics Matrix来表示该坐标系的位置关系。

相机坐标系(Camera Coordination)是一个关键的概念,在摄影测量和计算机视觉中具有重要意义。必须明确的是,并非照片坐标系——它以CCD/CMOS感光片或CCD/CMOS芯片的中心作为原点,并采用像素作为单位长度进行描述。内参矩阵(Intrinsics Matrix)主要是用来描述这个相机坐标系的参数集合及其内在几何特性。

5、**图像坐标系(Image Coordination)**中,默认情况下,默认情况下,默认情况下,默认情况下,默认情况下

三个坐标系分别设在左中右位置:Ego Coordination、Camera Coordination和Image Coordination。

基于贝索尔视图(BEV)的LSS(提升-压平-射击算法)实现中,在图像空间进行像素坐标转至全局坐标系的过程中

Image_to_Camera, Camera_to_Ego, Ego_to_World,用矩阵表示:

Position_in_World = Inv_World-to-Ego * Inv_Eego-to-Camera * Inv_Camera-to-Image * (Position_in_Image)

在代码实现中,通常采用Camera_to_Image来表示Intrinsics参数矩阵,在实际应用中通过引入 camera intrinsic matrix 的概念来简化计算流程。同样地,在代码中使用Ego_to Camera来表示Extrinsics参数矩阵,并结合 camera pose estimation 的方法以提高整体算法效率

这里要注意的一点是:fx,fy,它们实际上是这样计算得到的:

分别代表水平方向与垂直方向的镜头焦距参数FxFy其单位均为米。而DxDy分别表示每个像素的实际尺寸分别为X米与Y米在成像过程中通过计算可以得到反映相机特性的参数其结果具有像素级别的量纲。
在相机坐标系下所得的结果参数具有像素级别的量纲而经过变换后能够准确映射到成像平面从而保证了整体上的单位一致性。
通过将(Ego至相机矩阵与相机至图像平面变换矩阵)相乘作用于被测物体在全局坐标系中的位置矢量可以使结果直接映射到成像平面反之若需反向推导则经过逆变换后得到的结果具有与被测物体所在全局坐标系一致的物理量纲。

大多数BEV采用多个摄像头系统,并且需要同时处理各组摄像头捕获的画面数据并将其转换为Ego或世界坐标系中的位置信息。

图8

在统一的坐标系下拍摄多角度的照片能够准确地包围出周边的景象;另外一些基于单目摄像头(Monocular)实现的BEV方案则不采用Ego坐标系。这是因为单目摄像头只有一个朝向正前方(即Yaw,Pitch,Roll全部为零)的方向,并且其原点就位于该摄像头自身位置上;因此可以直接从相机坐标系进行世界坐标的转换和映射。

Frustum,在三维渲染领域中通常被称为“视锥体”,用于定义相机的可视范围:

图9

红面、绿面以及线框所围成的区域构成了视锥体。其中绿面通常被称为近平面(Near Plane),而红面则称为远平面(Far Plane)。这些线框所形成的角度定义为FOV。值得注意的是,在CCD/CMOS成像中:

  • 若高宽比例一致,则近平面与远平面均为正方形;一个FOV即可充分描述这种情况。
  • 相反地,在非正方形比例的情况下,则需要分别定义为FOVx和FOVy。
  • 任何超出视锥体范围的物体将被排除在计算之外。

图7所示的组合可视范围是由6个三角面构成的。实际上是由六个相互重叠的俯视视锥体构成,并且可以看出这些视锥体之间存在重叠区域。这些区域有助于深度神经网络在训练与推理过程中通过对六组数据进行相互校正来提升模型准确率。无需增加相机数量的情况下, 若希望扩大这些重叠区域, 则必须选用具有更大视野角(FOV)的相机。然而具有更大视野角(FOV)的相机通常会伴随着镜头畸变问题更为严重, 即使采用反畸变技术也只能在一定程度上矫正图像中的畸变问题, 同时相应的成像面积也会相应减小, 这将影响深度神经网络对图像特征进行识别与提取的能力

BEV领域涵盖大量前沿技术路线,在主要分布着不同技术路线的大军中

特斯拉体系下的视觉感知方案占据重要地位

而另一大类则是激光雷达、毫米波雷达与多摄像头协同工作的融合方案

中国多家自动驾驶公司沿用这一策略

其中最引人注目的是谷歌旗下的Waymo项目

严格地说,Tesla正逐步转向一种新的技术:即Occurrence Network的运用,并在维度上实现了升级进阶:从二维发展到三维

图10

不论是二维还是三维,在表述周边环境中的占据状态。一种则采用二维棋盘格的方式来表示这种占据状态;另一种则采用三维积木的方式表示这种占据状态。DNN通过概率来衡量这种占据程度;例如,在直观观察中发现某个网格上存在一辆汽车,则DNN计算得出的概率是:该网格处有车辆的可能性达到80%;该网格处无车辆的可能性仅为5%;该网格处出现行人的可能性也只有3%左右;基于此,在BEV编码中通常将各类别分为两类物体类别:第一类是静止物体(如车辆与行人),第二类是运动物体(如自行车与电动车)。通常情况下,在BEV编码中会以这样的形式存储各类别信息

相对稳定的: 在城市道路系统中相对稳定的要素包括可实现通信的道路网络(Driveable),路网中的车道带(Lane),建筑物(Building),植被(Foliage/Vegetation),停车场(Parking)区域以及一些未被分类的静态物体(Static)等要素;这些要素之间存在相互兼容或包含的关系;例如Driveable能够涵盖Road和Lane等基本元素。

变动的对象:即属于会移动的对象。例如行人包括 Pedestrians、小型车辆包括 Cars 和 Trucks、大型车辆包括 Trucks 等等。此外还包括其他类型的标志物。

这种分类的主要目的是用于AD系统进行后续的驾驶规划以及控制操作。(Planning与Control)另一方面,在感知阶段中使用BEV时是基于这些物体位于网格单元中的概率分布来进行评分。最后通过Softmax函数对各概率值进行归一化处理后选择具有最大值的可能性作为该网格单元所占有的对象类型。

但存在一个小问题:基于深度神经网络(DNN)的方法用于BEV建模时,在训练过程中具体的目标是将这些物体在标注数据中标注其类别信息。

图11

将右边视为标注数据,则左边则为相应的照片;通过针对该物体分类训练得到的DNN模型,在实际道路上运行时会遇到哪些问题呢?若该模型效果不佳——例如某个特殊姿势的人体未能被识别为行人或其他已知类别——又该如何应对?为此提出了一种改进方案:不再单纯依赖分类任务(虽然仍需分类),而是更加注重路面上是否存在障碍物(Obstacle)。换言之,在保证不发生碰撞的前提下可对各类障碍物不做具体归类;而使用三维积木式方法描述这种障碍物更为贴切——其中,在计算机视觉领域常用术语'体素'(Voxel)来指代这类三维单元。举个例子:就像玩Minecraft时搭建建筑一样简单。

图12

对于视觉主导型雷达系统的研究现状进行了概述。目前研究者们对混合型雷达系统的发展方向有哪些探讨?它们除了传统的相机技术之外还特别关注激光雷达收集的数据。毫米波雷达因其数据质量逐渐降低而逐渐退出这一领域的应用舞台剩下的则主要负责停车场景下的数据采集工作。虽然存在一些不足之处特斯拉汽车公司则强调了纯视觉技术在自动驾驶领域的核心地位并且这一技术路线也在不断吸收和借鉴其他领域的先进技术以实现突破性的创新

激光雷达的优势体现在其多方面的性能提升上:它不仅能够测量物体之间的距离,并且其测量精度显著高于视觉方法所推测出的场景深度;通常会被转换为深度数据或点云表示;这些算法拥有悠久的历史基础,在开发过程中可以利用现有的算法库进行快速搭建;此外特别适用于夜间及恶劣天气环境下的应用

但这几天推出了HADAR(Heat-Assisted Detection and Ranging),它同样处于相机、激光雷达以及毫米波雷达等传感器级别的感知技术行列。该技术的特点在于通过特殊的算法将常规热成像在夜间拍摄的画面转换为周围环境及物体的纹理与深度信息,并且这一技术与相机协同工作可有效解决夜间视觉感知问题

早期提出的贝 Voronoi(BEV)地图未提及热成像/红外相机技术的原因在于传统算法存在明显局限性:其仅能提供场景中各区域的温度分布信息并生成灰度图(Gray image),却无法有效捕捉景物表面纹理特征;此外原始数据缺乏深度信息支持,在计算深度估计精度时不可避免地会存在较大误差;仅凭从灰度图上提取出来的轮廓(Contour)和亮度变化(Gradient)难以精确重建场景或物体体积信息;而目前基于二维图像的传统物体识别方法对纹理和色彩依赖性较强;幸运的是HADAR雷达系统在较低光照条件下能够有效获取场景深度信息及纹理特征

图13

左列,自上而下:

基础的热成像,简称T

用常规热成像算法从T提取的深度

用HADAR算法从T提取的纹理图

用HADAR算法从T提取的深度

真实场景的深度

右列,自上而下:

这个场景在白天用可见光相机拍摄的照片

通过照片推理的深度

真实场景的深度

HADAR的这个深度信息老牛逼了,对比一下激光雷达的效果就知道了:

图14

激光雷达的工作覆盖范围具有局限性,在本例中通常限定在100米范围内(如图所示),无法提供远处景物及复杂细节的信息。由于扫描线的存在,在此范围内生成的数据呈现稀疏化特征(Sparse)。若要获得覆盖更大区域及更密集数据集的需求,则需要投入更高价位的产品型号进行获取。建议暂时停止使用该设备一段时间后重新启动进行连续扫描。

这些都属于基础概念,在理解BEV算法的过程中不可忽视的是必须先掌握的知识点:LSS(即提升-覆盖-射击法)

https%3A//github.com/nv-tlabs/lift-splat-shoot

在众多学术文章中, 老黄家的方法通常被视为贝索夫空间(Be spaces)发展的重要里程碑(Groundbreaking)。它设计了一个简洁高效的处理流程:

将相机拍摄的画面从二维数据转换为三维数据后,在视觉效果上将其压缩处理以适应二维展示需求;接着以俯视全局的方式审视这个被压缩的画面,则能够更好地与二维地图产生共鸣。通常会有人产生疑问:既然已经构建了三维的数据模型(2D到3D),为什么还需要进行降维处理呢?其实不然(3D并非完美),因为在实际应用中往往无法完美呈现三维空间信息。

图15

观察过这玩意吗?可以说这玩意儿的本质即是LSS。当正视面进行观察时会呈现为二维图像;经由拉伸作用扩展至三维空间后即为所展示的图形。当我们以正上方垂直向下观察时会看到什么?什么都看不出来;因此后续操作需将此二维图像转换为三维表示法(Splat)。具体过程如下:

图16

首先从图像中提取特征与深度信息(Feature and Depth),在LSS框架下进行的同时后续将详细阐述这一过程其特点类似于:

图17

仅能表述大致情况,并非完全精确;后续将详细阐述的是:该深度信息能够构建一个模拟三维空间的结构(Point Cloud点云模式),如同图15所示:

图18

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

图19

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

可以说这是一个广受好评的BEV图展示。从这一背景知识出发,在算法层面是如何实现这一认知呢?

为了实现单个相机可拍摄区域的精确定位与覆盖范围展示(尺寸设定为高8、宽22、深度41),我们采用了Blender这一强大的三维建模工具。

图21

这里是简图,请不要过分关注格子的具体数量及其大小。该3D网格代表了一系列相机的视锥体(Frustum),前面覆盖了其形状(图9)。此处将其变形为立方体,在相机空间中观察这一张照片与该立体网格之间的关系即为:

这里是简图,请不要过分关注格子的具体数量及其大小。该3D网格代表了一系列相机的视锥体(Frustum),前面覆盖了其形状(图9)。此处将其变形为立方体,在相机空间中观察这一张照片与该立体网格之间的关系即为:

图22

右侧是一个直视网格立方体的相机示意图。相片提取深度后(其中实际像素尺寸为高8宽22):

图23

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

图24

可以看到,在视锥体之外存在一些深度像素值。由于LSS方法从一开始就假设了一个有限范围的笼子区域,在此之外的所有数据都会被过滤掉。需要注意的是:LSS并非直接计算每个像素点的具体深度值;而是通过概率推断的方式推断出每个像素点可能位于笼子区域内的各个格子里的概率分布情况。图24则是通过Softmax函数提取并标注了每个像素点最有可能属于哪个格子的结果展示图,请注意其中的具体细节描述如下:

图25

从图25中选择一个深度像素(标记为红色的小方块),这个小方块通常情况下,默认分辨率仅为8×22个像素。该小方块属于笼子边缘下部的一条深度网格中(这条网格象征着相机朝着远方的一条视线)。

图26

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

图27

该段文字表明,在Lift变换后沿视线方向的空间深度呈现为二维深度图像素的概率密度分布(Probability Density Distribution)。这与图1所示之图具有等价关系:即该曲线表示的是空间中各点沿视线方向上的深度概率密度分布情况。

图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

为了便于分析时, 我对代码进行了精简处理。单个相机的视场范围大小为: D × H × W × 3 (其中深度D为41, 高度H为8, 宽度W为22), 即构建了一个D × H × W的空间网格, 网格单元中分别记录了每个空间坐标参数(X,Y,Z)的信息。

图29

在照片坐标系(uv)的基础上拓展出一个新的深度Z轴坐标系。在该系统中,默认配置有5个摄像头(LSS)。将这五个Frustum体数据传递至get_geometry函数进行处理后会生成由五个Frustum体组成的复合结构。该结构的张量尺寸更新为B × N × D × H × W × 3其中B表示批量大小,默认设置为4组训练样本;N代表摄像头数量,默认配置为5台

get_geometry里一开始要做一个

复制代码
    # undo post-transformation

这个方法的作用是什么?它与训练数据相关联,在深度学习领域中被广泛采用的一种策略是称为数据增强(在AR技术中使用的就是Augmentation)。这种技术的基本原理是在现有数据基础上进行一系列操作:旋转、平移、缩放以及裁剪等处理,并在这些操作后加入一些随机噪声(Noise)。例如,在未实施数据增强的情况下,默认情况下相机是固定方向拍摄的,在经过数据增强处理后对同一场景的不同视角进行建模时能够提升鲁棒性(Robustness)。

图30

该技术具有坚实的理论基础体系,并建议通过附图简要说明以避免冗长阐述。其具体实现通常嵌入到DataLoader系统中。

class NuscData(torch.utils.data.Dataset): def sample_augmentation(self):

回到刚完成的get_geometry部分,在进行数据增强时会引入一些随机的变化元素;然而相机必须保持固定状态才能使DNN模型有效地学习并适应这些随机变化带来的影响。因此,在将五个Frustum对齐到车身坐标系的过程中,请先去除(undo)这些引入的随机变化

然后通过:​​​​​​​

cam_to_ego_points由torch.cat操作生成

points由张量切片乘法运算结合后重塑得到
通过矩阵乘法计算得到combine矩阵
经过重塑和平移变换得到最终坐标

将各路Frustum从相机坐标系转换至车辆自身坐标系的过程中需要注意以下几点:首先,在此过程中,intrinsics表示相机内参数,并且这部分应用了逆矩阵运算;而rots和trans分别代表相机的旋转和平移参数。这些参数均来自nuScenes训练数据集。值得注意的是,在该过程中仅对intrinsics进行了逆矩阵处理;而对于外参部分(rots和trans),则未进行逆运算处理的原因是因为在nuScenes数据集中通常假设每个相机位于车辆的车身原点位置,并且其位姿变换顺序通常是先执行平移trans操作再执行旋转变换rots操作。因此在这种情况下无需进行逆运算处理以消除变换的影响。对于更换不同数据集或自行搭建相机采集系统的情况,则需要重新审视这些变换矩阵的具体定义以及计算顺序等关键问题

四视图大概就是这个样子:

图31

LSS中推理深度和相片特征的模块位于:​​​​​​​

复制代码
    class CamEncode(nn.Module): def __init__(self, D, C, downsample): super(CamEncode, self).__init__() self.D = D self.C = C self.trunk = EfficientNet.from_pretrained("efficientnet-b0") self.up1 = Up(320+112, 512) self.depthnet = nn.Conv2d(512, self.D + self.C, kernel_size=1, padding=0)

trunk能够同时推导出原始深度信息与图像特征。
depthnet则负责将trunk生成的原始数据转换为适用于LSS的形式。
值得注意的是虽然depthnet是一个卷积网络结构但其单个核仅占据1像素宽度,在功能上与全连接层FC相仿。
全连接层的主要作用通常是进行分类或回归操作;对于图像特征求取时主要执行分类任务;而针对深度特征求取则类似于构建深度概率分布模型。
EfficientNet采用了经过优化设计的ResNet架构。
就相当于同一个高级别的人工神经网络架构。

这就提出了另一个话题:从单一的二维图像中如何推导/提取深度特征的问题?这类问题通常被称为Monocular Depth Estimation(单目深度估计)。大多数这类系统通常包括两个主要步骤:粗化预测(Coarse Prediction)和细化预测(Refine Prediction)。其中粗化预测会对整个图像进行一次整体性的浅层深度估计;而细化预测则是在此基础之上识别具体的物体并推导出更加精细的深度信息。这类似于艺术家先以简约的方式勾勒出画面的整体轮廓线后再进行局部细节的具体描绘

除了通过卷积神经网络(CNN)来处理这类深度估计问题之外,还有一种方法是采用图卷积网络(GCN)以及Transformer架构进行求解。此外,在深度神经网络模型的基础上结合测距设备(如RangeFinder),也是一种常见的辅助手段。为了避免讨论过于复杂其复杂性与BEV同样不可小觑

那么LSS方法仅应用了一个trunk就完成深度特征是否存在过于简单的问题呢?实际上正如所观察到的那样确实存在这一问题。在LSS方法中估计出的深度基准与分辨率均存在显著差异这一现象可参考BEVDepth项目的各项测试报告进行深入分析

https%3A//github.com/Megvii-

BaseDetection/BEVDepth

研究发现了BEVDepth在测试中发现:将LSS深度估计部分的参数替换为一个随机数,并且使其不再参与学习过程(Back Propagation),其BEV的整体测试效果仅受到极小程度的影响。然而必须指出的是,在提升机制方面已经表现得非常强大了;尽管这种方法本身是突破性的、没有问题的;但是为了进一步提升性能,在这一环节还需要进行加强。

在LSS的训练过程中也存在另一个问题:相片上大约有一半的数据对训练不起作用,实际上这一问题在大多数BEV算法中都是存在的:

图32

右边标注的数据仅限于照片红线以下的部分,在红线上方则未被利用。如果想要了解LSS中的模型是如何处理这一区域的问题,则需要更多的信息支持。事实上,在实际应用中发现大多数BEV系统采用了这种方法作为基础假设。而在实际操作中,默认会选择周围一定范围内的标注数据作为参考,在这种设定下由于缺乏对应的数据支持导致的结果偏差也较为明显。值得注意的是,在实际拍摄中镜头能够捕捉到的距离要远大于红线以上的部分位置

这也解释了为何在图17所示的位置上, 图片中的深度分布与LSS内部的真实深度分布不一致, 仅在靠近路面的那一小区域中存在有意义的数据: whaosoft aiot http://143ai.com

图33

鉴于此,在针对鸟瞰图感知任务开发的深度神经网络模型中必然会有部分计算能力未得到充分释放。目前尚无相关研究报道对此展开深入研究的文献。

接着继续深入LSS的Lift-Splat计算过程:​​​​​​​

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 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

该变量new_x是将深度概率分布直接与图像纹理特征相乘以生成图像特征。为了便于直观理解这一过程,在后续讨论中我们假设图像的特征由三个通道(c1, c2, c3)组成,并且仅限于三个深度层级(d1, d2, d3)。具体而言,在分析某个像素点时需要明确其对应的概率含义:其中c1表示该像素有70%的概率对应车辆;c2表示该像素有20%的概率对应道路;c3则表示仅有10%的概率对应交通信号灯。同样地,在深度维度上d1意味着该像素位于第一层深度位置(80%的可能性),d2则对应第二层深度位置(15%的可能性),而d3则表示仅有5%的可能性位于第三层深度位置上。将这些计算结合起来得到的结果是:

公式的含义需要注意的是,在此框架中将图像的特征定义为c(Context)。a_d表示的是深度沿视线格子的概率分布,并且这里的d指的是深度值。其中new_x即为此计算的结果。值得注意的是,在此之前我们已经提到过相关的内容:由于图像特征和深度都是通过trunk网络进行训练得到的,并且它们处于同一维度空间中但其使用的信道位置有所不同——具体来说是:在trunk网络训练后输出的各个通道中分别对应不同的物理意义——其中深度方向使用了前self.D个信道(即前41个信道),而Context方向则使用了后面的self.C个信道(即后面的64个信道)。

因为new_x分别是在每个相机对应的Frustum独立进行计算。然而这些Frustum存在重叠区域因此必须进行动作数据融合。为了实现这一点在voxel_pooling中预先确定每个格子对应的索引及其空间位置。这样就可以利用这一对应关系将新生成的数据按索引分配到相应的格子中从而完成数据整合工作

LSS在voxel_pooling中引入了累积和机制(cumsum),尽管已有诸多研究对其进行了深入解析。然而,在深入研究这一技术细节之前,请权衡其必要性。值得注意的是,这仅是一个辅助性的计算技巧,在其改进效果有限的情况下未必具备实际意义。因此无需过分重视这一技术细节。

全部评论 (0)

还没有任何评论哟~