self_drive car_学习笔记--第5课:动态环境感知与3D detection

2024-02-13 22:30

本文主要是介绍self_drive car_学习笔记--第5课:动态环境感知与3D detection,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:这节课,主要是介绍激光雷达点云处理算法。处理基本思想就是,将3d点云信息转为2d信息,然后根据上一节课的图片处理算法常规操作即可。是不是挺简单的,哈哈哈。但,比较遗憾,本地环境问题还没有解决,还没有复现。这里记录的是,算法相关的论文以及GitHub开源的项目里面部分代码解析。好了,这一篇也仅供各位参考,欢迎大佬批评指正。

1 雷达激光点云基础及相关知识

1.1 激光雷达点云的认识

1)激光产生的
–机械式lidar:TOF(利用飞行时间计算距离)、N个独立激光单元、旋转产生360度视场
–MEMS式lidar:不旋转(但是内部有个组件在旋转)

2)数据特点:
–简单:x y z i(i表示强度)
–稀疏:7%(相对图片来说)
–无序:N!(角度不同、震动、扫描顺序不同)
–精确:±2cm

3)图像VS点云
–点云:简单精准,适合几何感知
–图像:丰富多变,适合语义感知

1.2常用数据集

1)3D点云数据来源:
–CAD模型:一般分类问题的数据集是CAD
–Lidar传感器
–RGBD相机

2)常用数据集
–Classification(Feature Representation)(分类数据集)
–ModelNet40/10
–ShapeNet Part

–无人驾驶场景数据集(detection检测;segmentation分割;tracking跟踪;….)
–http://www.cvlibs.net/datasets/kitti/【经典无人驾驶学习数据集】
–https://www.cityscapes-dataset.com/
–https://bdd-data.berkeley.edu/
–http://apolloscape.auto/【百度阿波罗项目】
在这里插入图片描述
3)无人驾驶入门级数据集:kitti

1.3 点云基础

1)点云处理:
–点云数据集
–相片vs点云坐标系【图1,2中涉及点云坐标系到图片坐标系的转换】
–创建点云鸟瞰图(涉及点云坐标系与图片坐标系的转换)【图1右侧就是鸟瞰图成像】
–创建360度全景视野
–使用Mayavi实现3D可视化交互
–使用Matplotlib实现3D可视化交互
在这里插入图片描述
在这里插入图片描述
注意,激光点云转换时候,选择鸟瞰图(上)还是前视图(下)或者其他视图,应该根据检测对象来定的,一般情况下,我们选择鸟瞰图;不过,但检测的是人时候,如果选择还是鸟瞰图,人会变成一个点,会导致信息量不足,此时应该选择前视图。

2)参考:
点云俯视图(鸟瞰图)创建参考:
https://blog.csdn.net/weixin_39999955/article/details/83819313
图片中点云:
https://github.com/charlesq34/frustum-pointnets

3)雷达点云转为图片关键点:
把激光雷达点云转换到某个相机的参考坐标系中,才能将激光点云数据转为图片显示

4)3d激光点云(kitti数据集)转换为鸟瞰图项目链接:https://github.com/charlesq34/frustum-pointnets/blob/master/kitti/kitti_util.py
在这里插入图片描述
5)源码思想解析:
激光点云数据转为彩色鸟瞰图代码大概解析,结合这个图来说,【坐标系查看上面kitti里面的坐标系定义】从激光点云坐标系变换到0号相机参考坐标系中,接着将0号相机(灰色图)自身坐标系投影到矫正坐标系(与车体一起指向正前方意思)中,接着将矫正坐标系投影到2号相机(彩色图)坐标系中。通过三次投影,才能将激光点云数据投影到彩色图上。
在这里插入图片描述
1.4 关于激光点云处理:传统VS深度学习

1)传统:
–基于点云的目标检测:分割地面->点云聚类->特征提取->分类
–地面分割依赖于人为设计的特征和规则,如设计一些阈值、表面法线等,泛化能力差【指机器学习算法对新样本的适应能力】

–多阶段的处理流程意味着可能产生复合型错误—聚类和分类并没有建立在一定的上下文基础上,目标周围的环境信息缺失
–这类方法对于单帧激光雷达扫描的计算时间和精度都是不稳定的,这和自动驾驶场景下的安全性要求(稳定、小方差)相违背

参考资料:
LIDAR-based 3D object perception
https://blog.csdn.net/AdamShan/article/details/83544089

2)深度学习(处理点云特点):End-to-End(端对端)
处理激光点云,面临的挑战:
–无结构化数据,只是一堆XYZI,没有网格这类的组织结构
–无序性:相同的点云可以由多个完全不同的矩阵表示(只是点的摆放顺序不同)
–数量变化大:图像中像素数量是常数,点云的数量可能会有很大(如:不同线的激光雷达)
–表现形式变化大:一辆车向左转,同一辆车向右转,会有不同的点云代表同一辆车
–缺少数据(采集昂贵):没有图片数据多,扫描时通常被遮挡部分数据丢失,数据稀疏

2、基于激光雷达点云的检测算法

简化版理解:将3d点云图三个平面拍个图片,放到神经网络里面,就跟正常的图片深度学习处理流程一样

2.1 Pixel-Based(基于像素)

1)基本思想:
–3d->2d,三维点云在不同角度的相机投影(映射)【不一定需要上一面说的坐标转换,只是单纯投影可以了】
–再借助2d图像处理领域成熟的深度学习框架进行分析

2)典型算法
–MVCNN MV3D AVOD
–Applo2.0 SqueezeSeg

3)MVCNN(分类):
–最早用深度学习来处理点云数据的方法
–实现CAD点云模型的分类:12个角度的图像(http://vis-www.cs.umass.edu/mvcnn/)
在这里插入图片描述
4)MV3D

–输入:BV+FV+RGB:并非简单投影(图1左侧列),而是提取高度/密度/强度/距离等特征作为像素值(图2)
–ROI:在BV训练一个3D RPN(图1中),分别向3中视图映射得到3种ROI,并融合
–缺点:该方法在检测诸如行人和骑车人等小物体方面滞后(因为他们在BEV中特征本来就少,又属于多次降采样),并且不能容易地适应具有垂直方向上的多个物体场景(只用了BV)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从上到下,依次是图1、图2、图3

5)AVOD

输入:BEV+RGB
–从[-40,40]x[0,70]x[0,2.5]范围内点云数据生成6-channel BEV map,分辨率0.1m,700x800x6【前面的80/0.1=800,前面的70/0.1=700,6表示的是6个通道的信息(指的是投影到鸟瞰图后)】
–Z轴上[0,2.5]平分5段,前五个通道时每个栅格单元的最大高度,第六个通道是每个单元中的米的信息(上面的6通道信息解析)

–点云转BEV实现代码:
–kitti lidar点云生成鸟瞰图BEV :
https://blog.csdn.net/weixin_39999955/article/details/83819313
– 点云处理:http://ronny.rest/tutorials/module/pointclouds_01
在这里插入图片描述
上面图中解析:

5-1)feature extractor(特征提取器)
–特征提取器由两部分组成:
Encoder(编码器) MXNXD->M/8XN/8XD*
Decoder(解码器)每层的操作包括通过conv-transpose操作上采样,与encoder中对应size的feature map连接,通过3X3的卷积操作融合两种feature maps,最终得到MxNxD特征图
–全分辨率feature map:对小目标友好
–借鉴论文FPN(feature pyramid networks)
在这里插入图片描述
5-2)RPN
–将feature extractor得到的feature maps通过1x1卷积操作进行降维处理减少RPN过程中的内存和计算量

–anchor6参数形式,中心点(tx,ty,tz)长宽高(dx,dy,dz),BEV上以0.5米的间距采样(tx,ty)【每0.5米生成一个anchor】,tz由传感器与地面之间的距离等因素决定。Anchors的尺寸每个类不同,从训练样本中获取70x80x0.5/0.5(num_cluster)*2(丰富的anchor对小目标友好)

–通过anchor的映射融合两种特征图:每个3d anchor投影到BEV;以及image获得两个ROI,每个roi进行crop resized to 3x3,然后进行像素级别的特征融合(特征丰富,可适应垂直方向多物体)

–在融合的特征图上训练RPN(MV3D仅在BEV上训练RPN)
–二分类:交叉熵,在BEV上通过判定anchors与ground truth的loU分辨object/background
–回归:smooth L1 loss,(▲tx, ▲ty,▲tz,▲dx,▲dy,▲dz),non-oriented?

–在BEV采用2D NMS【将不必要的框,去掉】将top k proposals送入第二阶段检测网络
在这里插入图片描述
5-3)second stage detector network:

–两个特征图的proposals crop resize融合:由于proposal远少于anchor就不再降维了,resize7x7,element-wise mean operation

–融合后的featurn通过三层全连接层得到类别(全分类)、bounding box、方向的输出,得到精准有方向有类别的3D bounding boxes

–bbox:
–采用4corner+2 height offset 编码,物体与ground plane的偏移作为gt
–回归形式是(▲x1…▲x4, ▲y1…▲y4, ▲h1, ▲h2)

–方向:
–mv3d采用估计框的长边的方向,但是很多物体不满足长边规则,例如行人
–avod种采用regressed orientation vector(逆方向矢量)以及计算(x(t),y(t))=(cos(t)),sin(t)使得t属于[-Π,Π]可以由BEV平面的惟一的单位向量表示
–每个bounding box有四个可能的朝向,选取离regressed orientation vector最近的朝向

参考:
–https://blog.csdn.net/qq_29981283/article/details/82983840
–https://blog.csdn.net/syyyao/article/details/81365400
–https://github.com/kujason/avod
在这里插入图片描述
在这里插入图片描述
2.1.1 Apollo2.0

1)Apollo2.0基于激光雷达的感知方案
–俯视图投影到地面网格(2d grid-map)每个网格计算8个统计量(图1上)
–使用UNet做障碍物分割(图3a)
–https://github.com/ApolloAuto/appollo/blob/master/docs/specs/3d_obstacle_perception.md(完整链接不存在)https://github.com/ApolloAuto/apollo(20201201这部分就有)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.1.2 SqueezeSeg

1)属于分割任务范围,然后是属于球面投影【将激光点进行球面投影】

2)关于球面投影,就看下面几个图片解析吧,因为数学公式实在不好编辑,将就看一下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3)球面投影个人理解:简单理解,就是获取上面顺数第二个图红色,青色弧线角度,因为R直接根据点云信息可以获取的,接着,空间中任何一个点的坐标都能根据两角和一边R表示出来。

4)点评:
4-1)任何的点云位置信息都可以使用球坐标系里面两角度一轴来描述
4-2)正常情况下,我们只关心两角度,因为这个轴就是雷达反射回来的长度属于已知量
4-3)一般情况下,我们只会取车前方90度范围的激光点云数据使用
4-4)上面的HWC=645125,其中5表示5个通道

2.1.3 CNN网络

–SqueezeNet,参数量极少,但是能够达到AlexNet精度,实时性好
–输入点云预处理后的数据64x512x5,输出同等尺度的label map(单相素分割)

–由于高度64小于其宽度512,网格主要对带宽进行降维(通过Max Pooling)(图2)
–conv14层的输出即对每个点的分类概率映射(分割)
–最后被输入到一个条件随机场中做进一步矫正
在这里插入图片描述
在这里插入图片描述
从上到下,图1,图2

从上面的图宽度缩小程度,可以知道,对宽度进行了降维。同时,该图的处理过程对应代码https://github.com/andylei77/SqueezeSeg_Ros/blob/master/script/squeezeseg/nets/squeezeSeg.py

2.1.4 CRF(conditional Ranoom Field 条件随机场)

1)单纯的CNN逐像素分类结果会出现边界模糊的问题(下采样丢失细节),为解决该问题,CNN输出的label map被输入到一个CRF(由RNN实现)进一步矫正CNN输出的label map

2)CRF原理:
–将像素分类问题看作为相似像素之间的概率推理问题,两个相近点具有相似的强度值极有可能属于同一个目标
–参考论文《Conditional Random Fields as Recurrent Neural Networks》如何将mean-field CRF inference 作为Recurent eural Network(RNN)的方法,在前向过程中对CNN粗糙的输出精细化,同时在训练时将误差返回给CNN

3)优点:速度快

4)缺点:
–分割的精度仍然偏低
–需要大量的训练集,而语义分割数据集标注困难
–改进版:SqueezeSegV2: Improved Model Structure and Unsupervised Domain Adaptation for Road-Object Segmentation from a LiDAR Point Cloud

5)代码:
–https://github.com/andylei77/SqueezeSeg_Ros(课程展示)
–http://wiki.ros.org/sensor_msgs

6)参考:
– https://blog.csdn.net/AdamShan/article/details/83544089
– https://github.com/AbangLZU/SqueezeSeg_Ros
–https://github.com/BichenWuUCB/SqueezeSeg
在这里插入图片描述
2.2 基于激光雷达点云的检测算法_ Voxel-Based(基于体素)

1)基本思想:
–将点云划分为均匀的空间三维体素(体素网格提供了结构,体素数量像图片一样是不变的,解决了顺序问题)

–优点:表达方式规整,可以将卷积池化等神经网络运算迁移到三维
–缺点:体素表达的数据量大(计算量很大,例如256x256x256=16777216),一般会减少分辨率(引入量化误差/局限性 例如64x64x64)

2)典型算法
–VoxNet: A 3D Convolutional Neural Network for Real-Time Object
Recognition
–Volumetric and Multi-View CNNs for Object Classification on 3D Data
–VoxelNet: Voxel-Based + Point-Based(局部+全局)
在这里插入图片描述
2.3 基于激光雷达点云的检测算法_ Tree-Based(基于树结构)

1)基本思想:
–使用tree来结构化点云,对稀疏点云进行高效地组织,再套用成熟的神经网络处理

–优点:与体素相比,是更高效的点云结构化方法(该粗就粗,该细的细)
–缺点:仍然需要额外步骤对数据进行处理(类似体素化),所以在端到端处理方面存在劣势

2)典型算法:

2-1)OctNet: Learning Deep 3D Representations at High Resolutions
–八叉树
–这一表示关注于相关稠密区域的内存分配和计算,使得3D卷积网络能够做既深又高分辨率(下图1)
–通过分析一些3d任务上的分表率,来展示octnet的作用,包括3D物体分类,方向估计和点云标注

2-2)O-CNN: Octree-based Convolutional Neural Networks for 3D Shape
Analysis
–八叉树将三维点云划分为若干节点组成的一定顺序结构

2-3)Escape from Cells: Deep Kd-Networks for the Recognition of 3D Point Cloud Models
–kd树
在这里插入图片描述
2.3 基于激光雷达点云的检测算法_Point-Based(基于点方式)

上面几种算法,都是需要对点云进行预处理的,这个基于点方式,是直接对点云进行处理的。

1)激光点云特征(处理需要解决的问题):
1-1)无序性
–点云本质上上一堆点(nx3矩阵,其中n是点数),点的顺序不影响其在空间中对整体形状的表示(相同点云可以由两个完全不同的矩阵表示)【图2右】
–希望不同的点云顺序可以得到相同的特征提取结果,可以用对称函数g(例如maxpooling或sumpooling)【图2左】

1-2)旋转/平移性
相同点云在空间中经过一定的刚性变化(旋转或平移)坐标变化
希望不论点云在怎样的坐标系下呈现网络都能正确识别出,可以通过STN(spacial transform network)解决【图1】
在这里插入图片描述
在这里插入图片描述
从上到下,依次图1,图2

2)基本思想:
–直接对点云进行处理,使用对称函数姐姐点的无序性,使用空间变换解决旋转/平移性

3)代表作品:
–PointNet PointNet++ -> Frustum-PointNet、PointRCNN
–PointCNN

参考:https://blog.csdn.net/qq_15332903/article/details/80224387

2.3.1 PointNet(cvpr2017)

1)核心点:
1-1)maxpooling作为对称函数解决无序性问题:每个点云分别提取特征之后,maxpooling可以对点的整体提取出global feature

1-2)空间变换网络解决旋转问题:三维的STN可以通过点云本身的位姿信息学习(loss调整)到一个最有利于网络进行分类或分割的变换矩阵,将点云变换到合适视角(例如 俯视图看车,正视图看人)

1-2-1)两次STN,第一次input transform可以理解为将原始点云旋转出一个更有利于分类或分割的视角,第二次feature transform是在特征层面对点云进行变换

【上述1-1)、1-2)可以结合图1加深理解】
在这里插入图片描述
Mlp指的是全连接层
下图代码来源:
https://github.com/charlesq34/pointnet/blob/master/models/pointnet_cls.py
在这里插入图片描述

def get_model(point_cloud, is_training, bn_decay=None):""" Classification PointNet, input is BxNx3, output Bx40 """#BxNx3,B表示batch_size,100张点云图;N表示每个点云图有多少个点;3表示xyz坐标batch_size = point_cloud.get_shape()[0].valuenum_point = point_cloud.get_shape()[1].valueend_points = {}with tf.variable_scope('transform_net1') as sc:transform = input_transform_net(point_cloud, is_training, bn_decay, K=3)#input_transform_net,表示变换,将BxNx3*Bx3x3->BxNx3point_cloud_transformed = tf.matmul(point_cloud, transform)input_image = tf.expand_dims(point_cloud_transformed, -1)#这里扩充了维度,BxNx3->BxNx3x1net = tf_util.conv2d(input_image, 64, [1,3],#[1,3],将BxNx3x1->BxNx1x64,通过641x3卷积核进行卷积实现全连接层,对每一个点独立抽取特征padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv1', bn_decay=bn_decay)net = tf_util.conv2d(net, 64, [1,1],#BxNx1x64->BxNx1x64,使用641x1卷积核padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv2', bn_decay=bn_decay)with tf.variable_scope('transform_net2') as sc:transform = feature_transform_net(net, is_training, bn_decay, K=64)#feature_transform_net,end_points['transform'] = transformnet_transformed = tf.matmul(tf.squeeze(net, axis=[2]), transform)#squeeze函数作用,BxNx1x64->BxNx64,去掉1;然后BxNx64*Bx64x64->BxNx64net_transformed = tf.expand_dims(net_transformed, [2])#expand_dims将维度扩充回来,BxNx64->BxNx1x64#对应流程图,mlp(64,128,1024)net = tf_util.conv2d(net_transformed, 64, [1,1],#通过卷积方式是实现全连接的,使用641x1卷积核对BxNx1x64进行卷积,得到BxNx1x64,也就是BxNx1x64->BxNx1x64padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv3', bn_decay=bn_decay)net = tf_util.conv2d(net, 128, [1,1],#基本含义同上64位置解析,BxNx1x64->BxNx1x128padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv4', bn_decay=bn_decay)net = tf_util.conv2d(net, 1024, [1,1],#基本含义同上64位置解析,BxNx1x64->BxNx1x1024padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='conv5', bn_decay=bn_decay)# Symmetric function: max poolingnet = tf_util.max_pool2d(net, [num_point,1],#max_pool2d表示池化,这句话意思是通过Nx1卷积对BxNx1x1024进行池化,得到Bx1x1x1024,也就是BxNx1x1024->Bx1x1x1024padding='VALID', scope='maxpool')net = tf.reshape(net, [batch_size, -1])#reshape,将Bx1x1x1024->Bx1024net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,#真正意义的全连接层开始,对比流程图中mlp(512,256,k),由于案例中右40个分类,所以k=40scope='fc1', bn_decay=bn_decay)net = tf_util.dropout(net, keep_prob=0.7, is_training=is_training,#keep_prob表示的是辍学率(keep_prob值是用来控制/调整训练神经网络时使用的辍学率);个人理解为废弃率scope='dp1')net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,scope='fc2', bn_decay=bn_decay)net = tf_util.dropout(net, keep_prob=0.7, is_training=is_training,scope='dp2')net = tf_util.fully_connected(net, 40, activation_fn=None, scope='fc3')#40return net, end_points

上述代码是解析上面图1的流程图,展示使用PointNet进行分类问题;其中,关键点是,利用卷积独立地对每个点进行抽特征。
下面代码,是对上面调用的转换函数进行说明的:
在这里插入图片描述

def input_transform_net(point_cloud, is_training, bn_decay=None, K=3):#输入是BxNx3点云,输出的是Bx3x3变换矩阵""" Input (XYZ) Transform Net, input is BxNx3 gray imageReturn:Transformation matrix of size 3xK """#BxNx3batch_size = point_cloud.get_shape()[0].value#表示Bnum_point = point_cloud.get_shape()[1].value#BxNx3->BxNx3x1input_image = tf.expand_dims(point_cloud, -1)net = tf_util.conv2d(input_image, 64, [1,3],#conv2d,使用卷积方法(卷积核是1x3,个数64)对每个独立点云抽特征,BxNx3x1->BxNx1x64padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='tconv1', bn_decay=bn_decay)net = tf_util.conv2d(net, 128, [1,1],#BxNx1x64->BxNx1x128padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='tconv2', bn_decay=bn_decay)net = tf_util.conv2d(net, 1024, [1,1],#BxNx1x128->BxNx1x1024padding='VALID', stride=[1,1],bn=True, is_training=is_training,scope='tconv3', bn_decay=bn_decay)net = tf_util.max_pool2d(net, [num_point,1],#max_pool2d,BxNx1x1024->Bx1x1x1024padding='VALID', scope='tmaxpool')net = tf.reshape(net, [batch_size, -1])#Bx1x1x1024->Bx1024net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,#fully_connectedscope='tfc1', bn_decay=bn_decay)#Bx1024->Bx512net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,scope='tfc2', bn_decay=bn_decay)#Bx512->Bx256with tf.variable_scope('transform_XYZ') as sc:assert(K==3)weights = tf.get_variable('weights', [256, 3*K],initializer=tf.constant_initializer(0.0),dtype=tf.float32)biases = tf.get_variable('biases', [3*K],initializer=tf.constant_initializer(0.0),dtype=tf.float32)biases += tf.constant([1,0,0,0,1,0,0,0,1], dtype=tf.float32)transform = tf.matmul(net, weights)#Bx256->Bx3Ktransform = tf.nn.bias_add(transform, biases)transform = tf.reshape(transform, [batch_size, 3, K])#Bx3K->Bx3xKreturn transform#最后返回的是Bx3x3

代码源自:https://github.com/charlesq34/pointnet/blob/master/models/transform_nets.py#L6

2.3.2 PointNet++(NIP2017)

1)PointNet:单个点云特征->全局特征【这种一步登天做法是很有问题的】,中间缺少局部信息(相当于用了很大的卷积核/pooling只做了一层卷积/pooling感受野一下就变最大)单个PointNet操作可以看作一种特殊的卷积操作(单像素抽取特征+global max pooling 或许应该放弃对单像素抽特征,没有利用领域信息,根本没有意义。除非放个像素包含了各个领域信息,例如减去中心点,直接卷积【需要卷积具有对称性:例如,卷积核内的所有权值相等?】)

2)PintNet++:单个点云特征->局部点云特征->更大局部点云特征->…->全局信息 (相当于多次卷积,感受野逐渐变大)【升级版本是解决上面一步登天问题】
在这里插入图片描述
3)ModeINet40上的准确率达到了由89.2%(PointNet)提高到90.7%(PointNet++)【下图对应的是升级版的操作流程】
在这里插入图片描述
4)核心点set abstraction(PointNet/++)
–采样:选取一些比较重要的点作为每一个局部区域的中心点
–分组:在这些中心点的周围选取k个近邻点(欧式距离给定半径内)

–PointNet:使用PointNet提取局部特征(一次PointNet相当于做一次卷积,故而称作PointNet卷积),点云子集的特征
–结果输出到下一个set abstraction重复这个过程
在这里插入图片描述
5)解决点云密度不均匀问题:激光扫描时会出现采样密度不均的问题,所以通过固定范围选取的固定个数的近邻点是不合适的,PointNet++提出了两个解决方案:

–多尺度分组【如图a,多个圈圈选取】:在每一个分组层,都通过多个尺度来确定每一个中心点的领域范围,并经过PointNet提取特征后将多个特征拼接起来,得到一个多尺度融合的新特征

–多分辨率分组【如图b,分2级到contact,一级到contact】:多尺度融合的做法,对于每一个中心点都需要多个patch的选区域提取特征,计算开销很大,多分辨率分组法是考虑多种分辨率的融合。左边特征向量【图b,contact横线的左侧点】是通过一个set abstraction

得到的(多次PointNet卷积),右边特征向量【图b,contact横线的右侧点】是直接对当前patch中所有点进行Pointnet卷积得到。并且当点云密度不均时,可以通过判断当前patch的密度对左右两个特征向量给予不同权重。例如,当patch中的密度很小,左边向量得到的

信息就没有对所有patch中心提取的特征的可行度更高,于是将右特征向量的权重提高,以此,达到减少计算量的同时解决密度问题。
在这里插入图片描述
Code:https://github.com/charlesq34/pointnet2

2.3.3 PointCNN

–PointNet:点云分别提取特征(顺序无关)->对称函数解决顺序问题(maxpooling)。”处处小心顺序问题”
–PointCNN:点云领域提取特征(顺序相关)->用X变换解决顺序问题。“前期大胆做/后期统一变”【匹对下图】
在这里插入图片描述
2.3.4 Frustum-Pointnet

–提取视锥体:RGB提取2D box(ROI) ,2D box -> 3D 视锥体(使用相机投影矩阵)
–分割视锥体内点云,分割得到物体实例,分割(3d mash 类似Mash-RCN在ROI内做二分类)
–3D box
Code: https://github.com/charlesq34/frustum-pointnets
在这里插入图片描述
2.3.5 PointRCNN

–3D RRN from raw point(使用PointNet++提取特征)
–Refining 3D proposals
–论文:https://arxiv.org/pdf/1812.04244.pdf
在这里插入图片描述
在这里插入图片描述
2.4 小结(综合上述几种算法)

解决顺序问题(结构问题)
–Pixel-Based:2D-grid【基于像素,将激光点云投影到2d网格】
–Voxel-Based:3D-grid【基于体素,将激光点云划分为3d网格】
–Tree-Based:Tree struct【基于树,利用树结构划分点云】
–Point-Based:对称函数/X变换【基于点,解决激光点云顺序问题】

3 基于激光雷达点云的检测算法_实战基于点云的目标检测

Voxel net

3.1基本介绍

1)基本思想:在3D网格单元上使用Pointnet学习的特征,而不使用手工制作的网格特征(例如h_max等)

2)整体框架:
–输入:仅使用激光雷达数据
–特征学习网络
–卷积中间层网络
–区域提取网络(RPN)

3)优缺点:
–准确度很高
–但在TitanX GPU上只有4fps的低速度

4)参考:
https://blog.csdn.net/AdamShan/article/details/84837211
https://github.com/qianguih/voxelnet
https://github.com/AbangLZU/VoxelNetRos【实战代码的原始作者版本】
在这里插入图片描述
3.2 代码原理分析

1)特征学习网络
–体素分块(Voxel Partition)输入点云(D,H,W)体素的深高宽为(vD,vH,vW),经过处理得到网格大小,voxel grid(D/(vD), H/(vH), W/(vW))
–点云分组(Grouping)将点云按照上一步分出来的体素格进行分组
–随机采样(Random Sampling)每一个体素随机采样固定数目的点T。因为 :
–a)网格单元内点云数量不均匀
–b)且64线一次扫描点云的数量巨大(10w),全部处理需要消耗很多CPU和内存
在这里插入图片描述
2)
在这里插入图片描述
3)稀疏张量表示(Sparse Tensor Representation):
–一系列的体素特征可以使用一个4维的稀疏张量来表示,C x D’ x H’ x W’
–一次lidar扫描包含接近10万格点,但是超过90%的体素格是空的,使用稀疏张量来描述非空体素格,能够减低反向传播时的内存和计算消耗

4)代码中(针对KITTI car)
–沿着lidar坐标系(z,y,x)方向分别对应取[-3,1]x[-40,40]x[0,70.4]立方体(米)作为输入点云
–体素大小
–体素网格大小
在这里插入图片描述
图中,vd,vh,vw分别对应的是 ZYX
–每个体素网格内随机采样T=35个点云
–两个VFE层VFE-1(7,32)和VFE-2(32,128)输出128维的Voxel-wise特征
–特征学习网络的输出,即为一个稀疏张量[batchsize,10,400/200,352/240,128]【10就是Z轴对应的4/0.4;400就是80/0.2;325就是70.4/0.2;里面的200,240属于对人情况的,因为分辨率(如前面的0.4,0.2)改变,得到结果不一样的;128就是维度】
代码:https://github.com/qianguih/voxelnet/blob/master/model/group_pointcloud.py

5)卷积中间层网络:
–类似PointNet中的:分层多次卷积->小邻域变大邻域
–每个卷积中间层ConvMD:3维卷积+BN层+非线性层(ReLU) 参数:3:3d c_in c_out:输入输出通道 k:卷积核(k,k,k) s:stride p:padding

–[batchsize,10,400/200,352/240,128]-> [batchsize, 400/200,352/240,128]【中间层会多卷一下】
–https://github.com/qianguih/voxelnet/blob/master/model/rpn.py

#  convolutinal middle layerstemp_conv = ConvMD(3, 128, 64, 3, (2, 1, 1),(1, 1, 1), self.input, name='conv1')temp_conv = ConvMD(3, 64, 64, 3, (1, 1, 1),(0, 1, 1), temp_conv, name='conv2')temp_conv = ConvMD(3, 64, 64, 3, (2, 1, 1),(1, 1, 1), temp_conv, name='conv3')temp_conv = tf.transpose(temp_conv, perm=[0, 2, 3, 4, 1])temp_conv = tf.reshape(temp_conv, [-1, cfg.INPUT_HEIGHT, cfg.INPUT_WIDTH, 128])

这一小节代码,就是解析卷积中间层网络的【个人还是没有理解背后的具体含义20201214】

6)区域提取网络(RPN)
–三个全卷积层块(Block),每次尺度减半
–每一个快的输出都是采样到相同尺寸进行串联得到高分辨率特征图

–输出:
–Probability Score Map(二分类 例如是否为车) [None,200/100,176/120,2]
–Regression Map(位置修正) [None,200/100,176/120,14] 【14,因为一个特征点映射回原图的话,对应两个box,每个box有7个值(3个中心点+3个宽高+旋转1个偏差)】
在这里插入图片描述
代码来自:https://github.com/qianguih/voxelnet/blob/master/model/rpn.py
代码中这些block都是上面流程图中的实现

# block1:temp_conv = ConvMD(2, 128, 128, 3, (2, 2), (1, 1),temp_conv, training=self.training, name='conv4')temp_conv = ConvMD(2, 128, 128, 3, (1, 1), (1, 1),temp_conv, training=self.training, name='conv5')temp_conv = ConvMD(2, 128, 128, 3, (1, 1), (1, 1),temp_conv, training=self.training, name='conv6')temp_conv = ConvMD(2, 128, 128, 3, (1, 1), (1, 1),temp_conv, training=self.training, name='conv7')deconv1 = Deconv2D(128, 256, 3, (1, 1), (0, 0),temp_conv, training=self.training, name='deconv1')

4.其他

答疑:
1)激光雷达扫描,只是获取两个角度和R值,而我们所看见的xyz值,是前面获取后,转换得到的

2)ROS,属于一种通信框架,目前适用于科研这类,实际使用的话,还是不能够满足车规级需要的

3)阿波罗2.0时候,采用激光雷达和高精地图作为主,这时候就主要激光点云数据处理;3.0版本时候,选择图像和毫米波雷达为主,这时候,就图像处理为主

4)这节课程中,有实战代码的,是需要重点学习的

个人小结:
这节课,介绍激光雷达点云处理算法。这些算法,基本上是深度学习方面的;也实战了一些基于激光点云处理基于神经网络算法案例。但是,很遗憾,虽然老师讲的很细,也图文并茂,但里面的代码和流程图还是很多地方不懂,主要因为相关知识太缺。
没错,菜是原罪。进步空间巨大。

各位小伙伴,链接里面的参考文献找不到的话,欢迎私聊哈。

#####################
不积硅步,无以至千里
好记性不如烂笔头
图片版权归原作者所有
感恩授课老师的付出

这篇关于self_drive car_学习笔记--第5课:动态环境感知与3D detection的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/706775

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss