• 点云的滤波


    激光扫描通常会产生密度不均匀的点云数据集。另外,测量中的误差会产生稀疏的离群点,使效果更糟。估计局部点云特征(例如采样点处法向量或曲率变化率)的运算很复杂,这会导致错误的数值,反过来有可能导致点云的配准等后期处理失败。

    以下方法可以解决其中部分问题:对每个点的邻域进行一个统计分析,并修剪掉那些不符合一定标准的点。我们的稀疏离群点移除方法基于在输入数据中对点到临*点的距离分布的计算。对每个点,我们计算它到它的所有临*点的*均距离。假设得到的结果是一个高斯分布,其形状由均值和标准差决定,*均距离在标准范围(由全局距离*均值和方差定义)之外的点,可被定义为离群点并可从数据集中去除掉。

    使用StatisticalOutlierRemoval滤波器移除离群点

    统计滤波器StatisticalOutlierRemoval用于去除明显离群点(离群点往往由测量噪声引入)。其特征是在空间中分布稀疏,可以理解为:每个点都表达一定信息量,某个区域点越密集则可能信息量越大。噪声信息属于无用信息,信息量较小。所以离群点表达的信息可以忽略不计。考虑到离群点的特征,则可以定义某处点云小于某个密度,既点云无效。计算每个点到其最*的k个点*均距离。则点云中所有点的距离应构成高斯分布。给定均值与方差,可剔除离群点。

    图1展示了稀疏离群点分析和移除的效果:左图为原始数据集,右图为处理结果。该图展示了处理前和处理后,一个点邻域范围内的k*邻邻域*均距离。

    图1 稀疏离群点分析和移除的效果对比图

    代码

    首先,在PCL(Point Cloud Learning)中国协助发行的书[1]提供光盘的第8章例3文件夹中,打开名为statistical_removal.cpp的代码文件,

    同文件夹下可以找到相关的测试点云文件table_scene_lms400.pcd

    下面来解析上面打开源代码的关键语句。下列代码将从磁盘中读取点云数据。

    pcl::PCDReaderreader;//定义读取对象
    reader.read<pcl::PointXYZ>("table_scene_lms400.pcd",*cloud);//读取点云文件

    然后,创建了一个pcl::StatisticalOutlierRemoval滤波器,将对每个点分析的临*点个数设为50,并将标准差倍数设为1,这意味着如果一个点的距离超出*均距离一个标准差以上,则该点被标记为离群点,并将被移除。计算后的输出结果储存在cloud_filtered中。

    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;// 创建滤波器对象
    sor.setInputCloud(cloud);                        //设置呆滤波的点云
    sor.setMeanK(50);                                //设置在进行统计时考虑查询点邻*点数
    sor.setStddevMulThresh(1.0);                    //设置判断是否为离群点的阈值
    sor.filter(*cloud_filtered);                    //执行滤波处理保存内点到cloud_filtered

    剩下的数据(内部点)将被存入磁盘,以供其他使用,例如可视化等。

    pcl::PCDWriterwriter;
    writer.write<pcl::PointXYZ>("table_scene_lms400_inliers.pcd",*cloud_filtered,false);

    然后,使用同样的参数再次调用该滤波器,但是利用函数setNegative设置使输出取外点,以获取离群点数据(也就是原本滤除掉的点)。

    sor.setNegative(true);
    sor.filter(*cloud_filtered);

    并将数据写回到磁盘

    writer.write<pcl::PointXYZ>("table_scene_lms400_outliers.pcd",*cloud_filtered,false);
    #include <iostream>
    #include <pcl/io/pcd_io.h>
    #include <pcl/point_types.h>
    #include <pcl/filters/statistical_outlier_removal.h>
    
    int
    main (int argc, char** argv)
    {
      pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
      pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
      // 填入点云数据
      pcl::PCDReader reader;
      // 把路径改为自己存放文件的路径
      reader.read<pcl::PointXYZ> ("table_scene_lms400.pcd", *cloud);
      std::cerr << "Cloud before filtering: " << std::endl;
      std::cerr << *cloud << std::endl;
      // 创建滤波器对象
      pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
      sor.setInputCloud (cloud);
      sor.setMeanK (50);
      sor.setStddevMulThresh (1.0);
      sor.filter (*cloud_filtered);
      std::cerr << "Cloud after filtering: " << std::endl;
      std::cerr << *cloud_filtered << std::endl;
      pcl::PCDWriter writer;
      writer.write<pcl::PointXYZ> ("table_scene_lms400_inliers.pcd", *cloud_filtered, false);
      sor.setNegative (true);
      sor.filter (*cloud_filtered);
      writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.pcd", *cloud_filtered, false);
      return (0);
    }
    

      可以直接在VS中执行控制台会输出点云滤波的信息,并得到两个pcb分别存储内点和外点:

    table_scene_lms400_inliers.pcd
    table_scene_lms400_outliers.pcd
    原点云可视化结果:

    滤波处理后:    

     

     参考:http://www.pclcn.org/study/shownews.php?lang=cn&id=68  

               http://blog.sina.com.cn/s/blog_a2b9923f0102wrwy.html

  • 相关阅读:
    谈谈对《镇魔曲》经济的一些看法
    谈谈对《神武2》经济的一些看法
    关于数值策划在使用Excel表时的一点想法
    游戏系统数值建模过程设计
    制作Excel工作薄目录
    制作当前表所在文件夹中所有文件的动态链接
    Excel各种tips汇总
    关于randbetween连乘的问题
    VBA实现两种方法生成任意概率分布的随机数
    Excel数值、文本相互转换
  • 原文地址:https://www.cnblogs.com/zhaobinyouth/p/6146331.html
Copyright © 2020-2023  润新知