0. 简介

激光雷达作为自动驾驶最常用的传感器,经常需要使用激光雷达来做建图、定位和感知等任务。而这时候使用降低点云规模的预处理方法,可以能够去除无关区域的点以及降低点云规模。并能够给后续的PCL点云分割带来有效的收益。

1. 点云预处理

1.1 指定区域获取点云

在实际使用中,我们可以看出,虽然点云的分布范围较广,但大部分的点都集中的中间区域,距离越远点云越稀疏,相对的信息量也越小。此外还能明显看到一些离群点,因此我们可以筛选掉一些较远的点,只保留我们感兴趣范围内的点。以下为保留 x 在 30m,y 在 15m,z 在 2m 范围内的点的效果:

template <class PointType>
void removePointsOutsideRegion(boost::shared_ptr<pcl::PointCloud<PointType>>& src_cloud_ptr,boost::shared_ptr<pcl::PointCloud<PointType>>& dst_cloud_ptr,const std::pair<double, double>& x_range,const std::pair<double, double>& y_range,const std::pair<double, double>& z_range) {int num_points = src_cloud_ptr->points.size();boost::shared_ptr<pcl::PointCloud<PointType>> cloud_ptr(new pcl::PointCloud<PointType>());cloud_ptr->points.reserve(num_points);for (const auto& pt : src_cloud_ptr->points) {bool inside = (pt.x >= x_range.first && pt.x <= x_range.second && pt.y >= y_range.first &&pt.y <= y_range.second && pt.z >= z_range.first && pt.z <= z_range.second);if (inside) {cloud_ptr->points.push_back(pt);}}dst_cloud_ptr = cloud_ptr;
}// 或者使用CropBox来实现去除给定区域外的点pcl::CropBox<pcl::PointXYZ> box_filter;box_filter.setInputCloud(cloud_ptr);box_filter.setMin(Eigen::Vector4f(keep_x_range.first, keep_y_range.first, keep_z_range.first, 1.0));box_filter.setMax(Eigen::Vector4f(keep_x_range.second, keep_y_range.second, keep_z_range.second, 1.0));box_filter.filter(*temp_cloud_ptr);

1.2 去除给定区域的点

在某些情况下,我们也会需要去除给定区域内部的点,比如在自动驾驶中激光扫描的区域有一部分来自搭载激光雷达的车子本身

template <class PointType>
void filterPointsWithinRegion(boost::shared_ptr<pcl::PointCloud<PointType>>& src_cloud_ptr,boost::shared_ptr<pcl::PointCloud<PointType>>& dst_cloud_ptr,const std::pair<double, double>& x_range,const std::pair<double, double>& y_range,const std::pair<double, double>& z_range,bool remove) {int num_points = src_cloud_ptr->points.size();boost::shared_ptr<pcl::PointCloud<PointType>> cloud_ptr(new pcl::PointCloud<PointType>());cloud_ptr->points.reserve(num_points);for (const auto& pt : src_cloud_ptr->points) {bool inside = (pt.x >= x_range.first && pt.x <= x_range.second && pt.y >= y_range.first &&pt.y <= y_range.second && pt.z >= z_range.first && pt.z <= z_range.second);if (inside ^ remove) {cloud_ptr->points.push_back(pt);}}dst_cloud_ptr = cloud_ptr;
}// PassThrough: 可以指定点云中的点的某个字段进行范围限制,将其设为 true 时可以进行给定只保留给定范围内的点的功能pcl::PassThrough<pcl::PointXYZ> pass_filter;bool reverse_limits = true;pass_filter.setInputCloud(filtered_cloud_ptr);pass_filter.setFilterFieldName("x");pass_filter.setFilterLimits(-5, 5);pass_filter.getFilterLimitsNegative(reverse_limits);  // reverse the limitspass_filter.filter(*filtered_cloud_ptr);pass_filter.setFilterFieldName("y");pass_filter.setFilterLimits(-2, 2);pass_filter.getFilterLimitsNegative(reverse_limits);  // reverse the limitspass_filter.filter(*filtered_cloud_ptr);pass_filter.setFilterFieldName("z");pass_filter.setFilterLimits(-2, 2);pass_filter.getFilterLimitsNegative(reverse_limits);  // reverse the limitspass_filter.filter(*filtered_cloud_ptr);

1.3 点云下采样

1.3.1 栅格化采样

这里第一点介绍栅格化的下采样,在 PCL 中对应的函数为体素滤波。栅格化下采样大致的思路是计算整体点云的中心,通过计算每个点到中心的距离结合要求的分辨率计算栅格对应的坐标,并入其中,最后遍历每个包含点的栅格计算其中点的几何中心或者取该栅格中心加入目标点云即可。

    pcl::VoxelGrid<pcl::PointXYZ> voxel_filter;voxel_filter.setLeafSize(0.1, 0.1, 0.1);voxel_filter.setInputCloud(cloud_ptr);voxel_filter.filter(*filtered_cloud_ptr);

1.3.2 点云所在区域密度规律滤波

该方法直接基于点云分布密度进行去噪,直观的感受是可以根据点云中每个点所在区域判断其是否是噪声,一般来说噪声点所在区域都比较稀疏。

    pcl::RadiusOutlierRemoval<pcl::PointXYZ>::Ptr radius_outlier_removal(new pcl::RadiusOutlierRemoval<pcl::PointXYZ>(true));radius_outlier_removal->setInputCloud(cloud_ptr);radius_outlier_removal->setRadiusSearch(1.0);radius_outlier_removal->setMinNeighborsInRadius(10);radius_outlier_removal->filter(*filtered_cloud_ptr);

1.3.3 点云所在区域分布规律滤波

除了根据稠密意以外还可以根据距离来筛选滤波,每个点计算其到周围若干点的平均距离,如果这个平均距离相对于整体点云中所有点的平均距离较近,则认为其不是噪点

    // PCL built-in radius removalpcl::StatisticalOutlierRemoval<pcl::PointXYZ>::Ptr statistical_outlier_removal(new pcl::StatisticalOutlierRemoval<pcl::PointXYZ>(true)); // set to true if we want to extract removed indicesstatistical_outlier_removal->setInputCloud(cloud_ptr);statistical_outlier_removal->setMeanK(20);statistical_outlier_removal->setStddevMulThresh(2.0);statistical_outlier_removal->filter(*filtered_cloud_ptr);
1.3.4 根据点云是否可以被稳定观察到筛选

LOAM 中对点云中的点是否能形成可靠特征的一个判断标准是它能否被稳定观察到。LOAM 中着重提了这两种情况的点是不稳定的:

  • 特征成平面和扫描线近乎平行
  • 特征扫描到的其中一端被另一个平面挡住,这部分的点也不稳定
template <typename PointType>
void filter_occuluded_points(boost::shared_ptr<pcl::PointCloud<PointType>>& src_cloud_ptr,boost::shared_ptr<pcl::PointCloud<PointType>>& dst_cloud_ptr,int neighbor_count,float distance_threshold,float horizontal_angle_diff_threshold,boost::shared_ptr<std::vector<int>> removed_indices = nullptr) {int cloud_size     = src_cloud_ptr->points.size();distance_threshold = std::fabs(distance_threshold);boost::shared_ptr<pcl::PointCloud<PointType>> cloud_ptr(new pcl::PointCloud<PointType>());cloud_ptr->points.reserve(cloud_size);std::vector<int> status(cloud_size, 0);for (int i = neighbor_count; i < cloud_size - neighbor_count; ++i) {const PointType& pt1 = src_cloud_ptr->points[i];const PointType& pt2 = src_cloud_ptr->points[i + 1];double horizontal_angle_1 = std::atan2(pt1.y, pt1.x) / M_PI * 180.0;double horizontal_angle_2 = std::atan2(pt2.y, pt2.x) / M_PI * 180.0;if (std::fabs(horizontal_angle_1 - horizontal_angle_2) > horizontal_angle_diff_threshold) continue;float range1 = std::sqrt(pt1.x * pt1.x + pt1.y * pt1.y + pt1.z * pt1.z);float range2 = std::sqrt(pt2.x * pt2.x + pt2.y * pt2.y + pt2.z * pt2.z);if (range1 - range2 > distance_threshold)  // pt1 is occluded{for (int j = i; j >= i - neighbor_count; j--) {status[j] = 1;}} else if (range2 - range1 > distance_threshold) {  // pt2 is occludedfor (int j = i + 1; j <= i + neighbor_count; j++) {status[j] = 1;}}}for (int i = 0; i < cloud_size; ++i) {if (status[i] == 0) {cloud_ptr->points.push_back(src_cloud_ptr->points[i]);} else if (removed_indices != nullptr) {removed_indices->push_back(i);}}dst_cloud_ptr = cloud_ptr;
}

2. 特征提取

2.1 激光雷达时间序列

这一帧数据中点的排列顺序为从最高的线束到最低的线束进行排列,每条线束之间点按逆时针的顺序排列。目前大部分主流激光雷达应该都可以直接在点云中提供每个点对应的扫描线已经时间戳,所以其实可以不用这种粗略的方法来进行计算。

template <typename PointType>
void sortPointCloudByScanLine(boost::shared_ptr<pcl::PointCloud<PointType>>& src_cloud_ptr,std::vector<boost::shared_ptr<pcl::PointCloud<PointType>>>& dst_cloud_ptr_vec) {const int N_SCAN = 64;dst_cloud_ptr_vec.resize(N_SCAN);dst_cloud_ptr_vec.clear();PointType pt;int line_id;for (int i = 0; i < src_cloud_ptr->points.size(); ++i) {pt      = src_cloud_ptr->points[i];line_id = 0;double elevation_angle = std::atan2(pt.z, std::sqrt(pt.x * pt.x + pt.y * pt.y)) / M_PI * 180.0;// adapt from a-loamif (elevation_angle >= -8.83)line_id = int((2 - elevation_angle) * 3.0 + 0.5);elseline_id = 64 / 2 + int((-8.83 - elevation_angle) * 2.0 + 0.5);if (elevation_angle > 2 || elevation_angle < -24.33 || line_id > 63 || line_id < 0) {continue;}if (dst_cloud_ptr_vec[line_id] == nullptr)dst_cloud_ptr_vec[line_id] = boost::make_shared<pcl::PointCloud<PointType>>();dst_cloud_ptr_vec[line_id]->points.push_back(pt);}
}

2.2 三维激光雷达压缩成二维

…详情请参照古月居

自动驾驶-激光雷达预处理/特征提取相关推荐

  1. 华为首超苹果,iPhone 风光已不再?百度资讯搜索来源调整;自动驾驶激光雷达厂商Velodyne筹备上市;...

    关注并标星星CSDN云计算 极客头条:速递.最新.绝对有料.这里有企业新动.这里有业界要闻,打起十二分精神,紧跟fashion你可以的! 每周三次,打卡即read 更快.更全了解泛云圈精彩news g ...

  2. 百度apollo 汽车环境感知 自动驾驶 激光雷达slamtec a1m8-r5 三角测距 双目相机

    datasheet,通讯,开发文档 win10需要驱动CP210 下载githubv1.11的演示程序,设定好com口和 115200 就可以采集数据了 在线文档slamtec 实践:目测图中一圈是2 ...

  3. 前沿 | 一文详解自动驾驶激光雷达和摄像头的数据融合方法

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:计算机视觉联盟 自动驾驶感知模块中传感器融合已经成为了标 ...

  4. 自动驾驶激光雷达物体检测技术

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者:william 链接:https://zhuanlan.zhihu.com/p/12851117 ...

  5. 带你浅浅了解自动驾驶激光雷达

    "激光雷达市场竞争异常激烈,国内两大巨头厂商禾赛科技.速腾聚创一较高下,国外FMCW方案厂商Aeva一骑绝尘.本文将介绍TOF和FMCW的激光雷达以及行业现状,带大家浅浅了解激光雷达小知识. ...

  6. 自动驾驶激光雷达、摄像头、毫米波雷达融合算法

    无人驾驶汽车多传感器冗余下的数据融合算法研究 [论文]详见知网链接.ELSEVIER链接.IEEE链接,[开源项目]详见github链接 [编译运行]详见DWD_sensor_fusion编译运行 目 ...

  7. 读自动驾驶激光雷达物体检测技术(Lidar Obstacle Detection)(3):Segmentation

    Segmentation的任务是将属于道路的点和属于场景的点分开,在该分割部分作者工使用了两种方法: 第一种: 下图中的12分别是第一种程序保存的点云结果. 下面是保存的点云的可视化结果: obstC ...

  8. 读自动驾驶激光雷达物体检测技术(Lidar Obstacle Detection)(4):Clustering(欧式聚类)

    在第(3)实现了地面点与障碍物的分离,此部分要实现的是聚类,聚类是指把不同物体的点云分别组合聚集起来, 从而能让你跟踪汽车, 行人等多个目标. 其中一种对点云数据进行分组和聚类的方法称为欧氏聚类. 欧 ...

  9. 读自动驾驶激光雷达物体检测技术(Lidar Obstacle Detection)(1):Stream PCD流式载入激光点云数据

    首先贴一下大佬的github链接:https://github.com/williamhyin/SFND_Lidar_Obstacle_Detection 知乎专栏:https://www.zhihu ...

  10. 读自动驾驶激光雷达物体检测技术(Lidar Obstacle Detection)(2):点云滤波FilterCloud()函数

    FilterCloud()所包括的功能: 1.首先使用体素滤波(相当于做稀释减少点的数量)(体素网格过滤将创建一个立方体网格, 过滤点云的方法是每个体素立方体内只留下一个点, 因此立方体每一边的长度越 ...

最新文章

  1. python使用joblib模块保存和加载机器学模型
  2. html文字随机变色效果,html肿么让字体得到随机颜色
  3. android频繁点击ui崩溃,android easeui 集成 启动崩溃
  4. 牛根生--蒙牛创业故事
  5. 【HTML+CSS网页设计与布局 从入门到精通】第7章-class、ID选择器,CSS格式
  6. Effective C# Item30:尽可能实现CLS兼容的程序集
  7. 【感悟】人生本如梦,学会看淡一切。
  8. ARP伪造使用抓包工具进行ARP欺骗arp伪造攻击
  9. Linux编译安装Apache
  10. iOS关于data.bin的文件的解析、存储、读取
  11. 怎么重置计算机网络设置密码,路由器密码怎么重置 路由器密码重置方法【详解】...
  12. 【微信小程序系列:三】前端实现微信支付与代扣签约
  13. LeetCode 1041. 困于环中的机器人(C++)
  14. 服务器U盘安装安装centos
  15. layui前端项目打包方法_layui封装模块基础教程
  16. JavaFx之横向布局左右两侧对齐(十九)
  17. unshift() 与shift() 方法
  18. 选购地磁传感器应避免哪些坑
  19. Pycharm新手使用教程(详解)
  20. 老夫带你深度剖析Redisson实现分布式锁的原理

热门文章

  1. python飞机大战源码素材包_Python飞机大战实战项目案例
  2. cpda项目数据分析师与cda数据分析师的区别?不建议考CPDA
  3. 阵列信号处理及matlab实现,《阵列信号处理的理论和应用》(pdf+程序)
  4. 最近在学习Floquet理论,主要是想用于稳定性分析
  5. endnotex8与9的区别_下载安装EndnoteX8或EndnoteX9,建立数据库并以自己的名字命名。...
  6. 全国省市区数据SQL - 2017年数据(三级联动)
  7. 爬去当当热销图书信息
  8. 华为手机fastboot解锁
  9. 截图上传录屏gif上传工具推荐
  10. 《人工智能-一种现代的方法》阅读笔记