激光雷达点云预处理介绍

描述

激光雷达作为自动驾驶最常用的传感器,经常需要使用激光雷达来做建图、定位和感知等任务。

而这时候使用降低点云规模的预处理方法,可以能够去除无关区域的点以及降低点云规模。并能够给后续的PCL点云分割带来有效的收益。

点云预处理

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 limits pass_filter.filter(*filtered_cloud_ptr); pass_filter.setFilterFieldName("y"); pass_filter.setFilterLimits(-2, 2); pass_filter.getFilterLimitsNegative(reverse_limits);  // reverse the limits pass_filter.filter(*filtered_cloud_ptr); pass_filter.setFilterFieldName("z"); pass_filter.setFilterLimits(-2, 2); pass_filter.getFilterLimitsNegative(reverse_limits);  // reverse the limits pass_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 removal    pcl::StatisticalOutlierRemoval&lt;pcl::PointXYZ&gt;::Ptr statistical_outlier_removal(        new pcl::StatisticalOutlierRemoval&lt;pcl::PointXYZ&gt;(true)); // set to true if we want to extract removed indices    statistical_outlier_removal-&gt;setInputCloud(cloud_ptr);    statistical_outlier_removal-&gt;setMeanK(20);    statistical_outlier_removal-&gt;setStddevMulThresh(2.0);    statistical_outlier_removal-&gt;filter(*filtered_cloud_ptr);

1.3.4 根据点云是否可以被稳定观察到筛选

LOAM 中对点云中的点是否能形成可靠特征的一个判断标准是它能否被稳定观察到。

LOAM 中着重提了这两种情况的点是不稳定的:

  • 特征成平面和扫描线近乎平行
  • 特征扫描到的其中一端被另一个平面挡住,这部分的点也不稳定
template < typename PointType >void filter_occuluded_points(boost::s
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分