当前位置: 首页 > article >正文

3D-Lidar点云数据处理

3D-Lidar点云数据处理

  • 3D-Lidar点云数据处理
    • 原始激光点云数据滤波
    • 点云分割(地面与非地面)
    • 目标聚类
      • 欧式聚类
      • Add Bounding Boxes
    • 目标跟踪
        • 基础卡尔曼滤波
        • 3D-IoU ( Interserction over Union)
        • 匈牙利算法(Hungarian)
        • 3D-MOT

3D-Lidar点云数据处理

本篇博客,记录自己学习处理3D-Lidar点云数据目前遇到的算法及本工程使用的算法,作为记录有不足的地方,烦请大家批评指正、指导。

原始激光点云数据滤波

参考Being_young大佬文章:https://blog.csdn.net/u013019296/article/details/70052319

对于原始点的滤波,觉得目前PCL库已经做了很好的处理,PCL库中给出几种需要进行点云滤波处理情况:

  1. 点云数据密度不规则需要平滑;
  2. 扫描时,由于障碍物可能会存在遮挡,离群点需要去除;
  3. 数据太大需要下采样(现在已经遇到这个数据量太大的问题了,16线的Lidar一次采样存在 ( 32 + 16 * 2 ) * 360 / 0.18 = 128000 个点云数据);
  4. 去除噪声

对应解决方案:

  1. 给定的规则限制过滤去除点
  2. 通过常用滤波算法修改点的部分属性,统计滤波
  3. 下采样(测试选在0.1,过滤可达到50%以上)

PCL库直通滤波例子

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
/**
* 1、创建直通滤波器的对象,设立参数,滤波字段名被设置为Z轴方向
* 2、通过函数setFilterLimitsNegative,过滤所有点的Z轴坐标不在该范围内的点过滤掉(false)或保留(true) 
*/
// 设置滤波器对象
pcl::PassThrough<pcl::PointXYZ> pass;	// 声明滤波器对象
pass.setInputCloud (cloud);				// 设置输入点云(ptr指针)
pass.setFilterFieldName ("z");			// 设置过滤x,y,z哪个方向
pass.setFilterLimits (-1.8, 0.5);		// 设置在过滤方向的范围
pass.setFilterLimitsNegative (false);   // 设置保留范围内还是过滤掉范围内
pass.filter (*cloud_filtered);			// 执行滤波,保存过滤结果到cloud_filtered(ptr指针)

PCL库体素下采样例子

本工程使用的滤波器

/**
* 创建pcl::VoxelGrid滤波器对象,并设置叶素大小为1cm
*/
pcl::VoxelGrid<pcl::PCLPointCloud2> vg;	// 创建滤波对象
vg.setInputCloud (cloud);				// 输入点云(ptr指针)
vg.setLeafSize (0.01f, 0.01f, 0.01f);	// 设置体素体积为1cm的立方体
vg.filter (*cloud_filtered);			// 执行滤波处理,存储输出

PCL库统计滤波器例子

/**
* 1、创建统计滤波器statisticalOutlierRemoval对象
* 2、设置在进行统计时考虑查询点临近点数
*/
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;	// 创建滤波器对象  
sor.setInputCloud(cloud);							// 输入点云(ptr指针)
sor.setMeanK(50);									// 设置在进行统计时考虑查询点临近点数  
sor.setStddevMulThresh(1.0);						// 设置判断是否为离群点的阀值  
sor.filter(*cloud_filtered);						// 执行滤波处理,存储输出  

原始点云数据
After-filter

点云分割(地面与非地面)

  1. Fast Segmentation of 3D Ponit Clouds for Ground Vehicles 论文实现 文章解读 IEEE 文章下载
  2. PCL库,随机采样一致性实现

本工程采用快速分割
1、根据Lidar旋转角度和角分辨率分割扇形区域,sector_num = 360° / 0.18°;0.18是水平角分辨率;
2、根据object的x,y值计算 θ \theta θ角,通过向下取整的方式把点运数据投影到不同扇形区域内,然后每个扇形区域内的点根据半径距离也向下取整并从小到大排列;
3、设置点与点之间最大坡度 point2point_max_slope = 5° 和地面坡度 ground_max_slope = 8°,根据实际情况标定;
4、计算点与点之间的高度阈值 point_height_threshold 和 ground_height_threshold 以及 point_distance;

计算开始之前,需要将原有点云数据转类型,新类型除包含原有数据内容,还添加了投影在xy平面的半径,X轴方向上的夹角 θ \theta θ,扇形分割的序列索引,所在扇形根据半径从小到大重排列的序列索引,以及原始点云序列索引

struct PointXYZRTCO
{pcl::PointXYZ point; 	// 保存原始点云数据 float radius;		 	// cylindric coords on XY Planefloat theta;		 	// angle deg on XY planesize_t radial_div;   	// index = 保存点云数据属于哪个扇形size_t concentric_div;  // index = 保存该扇形点云的重排列序列size_t original_index;  // index = 保存原始点云序列
};

对LIDAR的扫描区域进行扇形分割,每个扇形区域的点云将组成一条射线

XY平面扇形分割

对扇形区域内的点云,进行重排列:
1、根据 floor( θ \theta θ / 0.18°),对点云的射线所以归属进行取值;
2、然后,根据每个点云数据的x,y坐标值计算每个点云所在圆弧的半径r,根据半径r,将原有射线上的点云进行从小到大的顺序排列;

单个扇形点云转换为单个射线

根据每条射线的点云分布,对其进行地面分割:
1、首先,对点与点之间坡度以及地面总体坡度进行估计,该估计值属于经验值,对于不同雷达,在分割数据时,需要进行标定调参;
2、从射线的最小端开始,计算点与点之间之间的距离,和高度差的阈值;

当前点高度属于前一个点高度 ± 点与点高度阈值情况,即
current_point.z ∈ (pre_point.z - height_threshold , pre_point.z + height_threshold)
1、情况一,前个点属于非地面的情况:

  • 如果,当前点的高度也属于负的Lidar高度 ± 地面高度通用阈值,即current_point.z ∈ (- sensor_height - general_height_threshold , - sensor_height + general_height_threshold) :得到当前点为地面点;
  • 否则,也属于非地面点。

前一个点不属于地面

当前点高度属于前一个点高度 ± 高度阈值情况,即
current_point.z ∈ (pre_point.z - height_threshold , pre_point.z + height_threshold)
2、情况二,前个点属于地面的情况:

  • 此时,当前点也为地面点。

前一个点属于地面

当前点高度不属于前一个点高度 ± 高度阈值情况,即
current_point.z ∉ (pre_point.z - height_threshold , pre_point.z + height_threshold)
1、情况一,当前点的高度属于负的Lidar高度 ± 地面高度通用阈值,即current_point.z ∈ (- sensor_height - general_height_threshold , - sensor_height + general_height_threshold) && 点与点之间的距离很大p2p_distance > reclass_distance_threshold:得到当前点为地面点;
2、其他情况,当前点都为非地面点。

前一个点不论在不在地面

分割后,地面点云:

ground

分割后,非地面点云:

unground

目标聚类

本工程基于非地面分割点云数据进行欧式聚类

  1. PCL库 欧式聚类
  2. 深度学习 Point++ / PointNet++ / PointRCNN
  3. Fast and Furious: Real Time End-to-End 3D Detection, Tracking and Motion Forecasting with a Single Convolutional Net (1) (2) (3) (4)

对于2/3的方式,下一步可以尝试优化3D检测跟踪

欧式聚类

PCL库使用kd-tree加快欧式聚类算法进度

Kd-tree详解:(1)
欧式聚类算法流程详解: (1) (2)
由于点云数据在距离增加的时候,离散度在不断增加,所以考虑这种情况,在下面传参的时候根据距离判断传入不同的容忍度:

std::vector<pcl::PointIndices> local_indices;
pcl::EuclideanClusterExtraction<PointT> euclid;
euclid.setInputCloud(in_ground_cloud_2d);
euclid.setClusterTolerance(in_max_cluster_distance[i]);
euclid.setMinClusterSize(50);
euclid.setMaxClusterSize(10000);
euclid.setSearchMethod(tree);
euclid.extract(local_indices);

KD-Tree 搜索过程关键点:
k = 3情况下,x,y,z三个方向的超平面选择方法,根据三个方向上数值方差最大值判断超平面选择顺序,根据均值选择二分点;
方差越大,数据分布越离散,选择最大的可以很好的将数据分割开来。

KD搜索流程,二分速度就是快:
图中对于给定的查询数据点m,须从KD-Tree的根结点开始进行比较,其中m(k)为当前结点划分维度k上数据点m对应的值,d为当前结点划分的阈值。若 m(k)小于d,则访问左子树;否则访问右子树,直至到达叶子结点Q。此时Q就是当m前最近邻点,而m与Q之间的距离就是当前最小距离Dmin 。随后沿着原搜索路径回退至根结点,若此过程中发现和m之间距离小于 Dmin的点,则须将未曾访问过的子节点均纳入搜索范畴,并及时更新最近邻点,直至所有的搜索路径都为空,整个基于KD-Tree结构的最近邻点查询过程便告完成。

KD-tree

欧式聚类流程:
对于欧式聚类来说,距离判断准则为欧氏距离 E u = s q r t ( ( x k − x i ) 2 + ( y k − y i ) 2 + ( z k − z i ) 2 + . . . ) Eu = sqrt((xk-xi)^2 + (yk-yi)^2 + (zk-zi)^2 + ...) Eu=sqrt((xkxi)2+(ykyi)2+(zkzi)2+...)。对于空间某点P,通过KD-Tree近邻搜索算法找到k个离p点最近的点,这些点中距离小于设定阈值的便聚类到集合Q中。如果Q中元素的数目不在增加(或者小于最小搜索数目,或者大于最大搜索数目),整个聚类过程便结束;否则须在集合Q中选取p点以外的点,重复上述过程,直到Q中元素的数目不在增加为止。

欧式聚类

Add Bounding Boxes

对于Bounding Boxes的生成可以使用PCA主成分分析法生成更小的方框, 实现更高的预测结果精准性. 具体PCL实现可以查看这个链接:PCL-PCA.

BBox

目标跟踪

Doing

在使用深度学习目标检测算法(PointRCNN)后,该3D多目标追踪系统不需要使用GPU且取得了最快处理速度(214.7FPS)。
本工程尝试使用欧式聚类的方式获取bbox,然后根据该目标检测结果进行多目标跟踪。

  1. 基础卡尔曼滤波 -> 根据需求可以优化为EKF(扩展卡尔曼滤波)和UKF(无损卡尔曼滤波)
  2. 3D-MOT
  3. A Baseline for 3D Multi-Object Tracking 原文 (译文)
基础卡尔曼滤波

用最简单的过程模型来描述目标运动——恒定速度模型

  1. 同论文一样,对于检测目标object中 [ x \ x  x, y \ y  y, z \ z  z]T 信息转化为 [ x \ x  x, y \ y  y, z \ z  z, θ \theta θ, l \ l  l, w \ w  w, h \ h  h, v x \ v_{x}  vx, v y \ v_{y}  vy, v z \ v_{z}  vz]T
  2. 然后根据卡尔曼滤波算法,预测更新
    X k \ X_{k}  Xk = F \ F  F · X k − 1 \ X_{k-1}  Xk1 + B \ B  B · u k \ u_{k}  uk
    P k \ P_{k}  Pk = F \ F  F · P k − 1 \ P_{k-1}  Pk1 · F T \ F^T  FT + Q \ Q  Q
    G k \ G_{k}  Gk = P k \ P_{k}  Pk · C T \ C^T  CT / ( F \ F  F · P k \ P_{k}  Pk · F T \ F^T  FT + R \ R  R)
    X k \ X_{k}  Xk = X k \ X_{k}  Xk + G k \ G_{k}  Gk · ( Z \ Z  Z - C \ C  C · X k \ X_{k}  Xk)
    P k \ P_{k}  Pk = ( I \ I  I G k \ G_{k}  Gk · C \ C  C) · P k \ P_{k}  Pk
  3. 其中, X k \ X_{k}  Xk 为状态向量, F \ F  F 为状态转移矩阵, B \ B  B为控制矩阵, P k \ P_{k}  Pk为估计状态概率分布的协方差矩阵, Q \ Q  Q是我们的过程噪声的协方差矩阵,由于过程噪声是随机带入的,所以 u k \ u_{k}  uk 本质是一个高斯分布: u k \ u_{k}  uk ~ N \ N  N( 0 \ 0  0, Q \ Q  Q), Q \ Q  Q是过程噪声的协方差, C \ C  C为测量矩阵, Z \ Z  Z为实际测量值矩阵,同样对于恒速运动模型,我们可以将 B \ B  B · u k \ u_{k}  uk忽略。
  4. 特别注意,过程噪声协方差矩阵获取方式参考(1),论文中用的过程噪声协方差矩阵,值为0.01的7*7方阵,并且没有考虑到采样时间问题,直接考虑时间为等值分布。
3D-IoU ( Interserction over Union)

从1D-IoU到2D-IoU推导

匈牙利算法(Hungarian)

匹配前后帧的对象,中心思想为二分图查找 实现最大匹配数

3D-MOT

中心思想就是使用每次检测结果的去估计

http://www.lryc.cn/news/2415793.html

相关文章:

  • 最新仿映客直播APP开发实战项目IOS开发实战8天
  • 新学期flag-适合每个人的专业课
  • 2021年美容师(中级)考试题库及美容师(中级)考试总结
  • 云IDE使用入门教程——初步认识云IDE
  • 5本免费的Java电子书
  • 中文乱码解决大全
  • STL---Vector常用接口介绍及模拟实现
  • 华为C++笔试题
  • 【AI视野·今日CV 计算机视觉论文速览 第304期】Thu, 7 Mar 2024
  • 苹果商店开发者能不能不找到评论人_顶风作案!“涉黄” App 一夜登顶榜首,苹果清词、清榜不够狠?...
  • 子域名收集 -- Esd
  • 流星蝴蝶剑修改大全
  • 先验概率、最大似然估计、贝叶斯估计、最大后验概率
  • promise对象与ajax的爱情故事,还有JSON
  • shell中declare命令
  • ps4三国战纪服务器维护,PS4三国战纪游戏心得 最快升级方法
  • SDK(Software Development Kit)
  • 3.Magento的布局(Layout),块(Block)和模板(Template)
  • 直播商城系统源码直播带货app源码短视频直播平台
  • perl的chomp重要性
  • microsoft html 帮助,Microsoft HTML Help Workshop(CHM文件生成)
  • 123123123
  • scrapy爬取京东的数据
  • java基础之:集合
  • MySQL查看数据库状态命令详解
  • 情侣网站开源源码-带后台
  • httpclient发送Get请求和Post请求
  • OpenLayers源码解析2 View.js
  • sql的IndexOf和LastIndexOf
  • Android Studio gradle build error: PKIX path building failed解决方法