zoukankan      html  css  js  c++  java
  • 29 基于PCL的点云平面分割拟合算法技术路线(针对有噪声的点云数据)

    0 引言

    最近项目中用到了基于PCL开发的基于平面的点云和CAD模型的配准算法,点云平面提取采用的算法如下。

    1 基于PCL的点云平面分割拟合算法

     2 参数及其意义介绍

    (1)点云下采样

      1. 参数:leafsize

      2. 意义:Voxel Grid的leafsize参数,物理意义是下采样网格的大小,直接影响处理后点云密集程度,并对后期各种算法的处理速度产生直接影响。

      3. 值越大,点云密度越低,处理速度越快;值越小,点云密度越高,处理速度越慢。通常保持这个值,使得其他的与点数有关的参数可以比较稳定而不作大的改动。

      4. 对应的代码:

    PointCloudPtr cloud(new pointCloud);
    ParameterReader pd(ParameterFilePath);
    double leafsize = stod(pd.getData("leafsize"));
    pcl::VoxelGrid<PointT> sor;
    sor.setInputCloud(CRTP::cloud_org);
    sor.setLeafSize(leafsize, leafsize, leafsize);
    sor.filter(*cloud);

    (2)点云法线估计

      1. 参数:Ksearch

      2. 意义:估计法线时邻域内点的个数

      3. 值越小,对点云的轮廓描述越精细;值越大,对点云的轮廓描述越粗糙。

      4. 对应的代码:

    ParameterReader pd(ParameterFilePath);
    pcl::NormalEstimation<PointT, pcl::Normal> ne;
    pcl::PointCloud<pcl::Normal>::Ptr mynormals(new pcl::PointCloud<pcl::Normal>);
    pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>);
    tree->setInputCloud(cloud_filter);
    ne.setInputCloud(cloud_filter);
    ne.setSearchMethod(tree);
    ne.setKSearch(stoi(pd.getData("Ksearch")));
    ne.compute(*mynormals);

     (3)RegionGrowing生长聚类算法对可能是平面的点云进行分割

     算法步骤:  

      1. 算法首先计算所有点的曲率值,并将曲率最小的点作为种子(seeds),开始进行生长 

      2. 以法线夹角阈值(Angle threshold)作为判断标准,对邻域内的点进行遍历判断 ,符合条件则加入当前点集,不符合则reject,并加入reject点集

      3. 以曲率阈值(Curvature threshold)作为判断标准,将邻域内符合条件的点加入到种子队列中 

      4. 移除当前种子 

      5. 如果当前种子队列空了,表明当前子区域分割停止,遍历其他种子区域,直到停止整个点云均被遍历完为止生长

     参数分析: 

      1. 参数:MinClusterSize(最小聚类点云数目),MaxClusterSize(最大聚类点云数据)

      NumberOfNeighbours(寻找种子seed点最近的点判断是否为同类),SmoothnessThreshold(聚类的法线夹角阈值)

           CurvatureThreshold(聚类的曲率阈值,可以直观地将圆柱面等区别开)

      2. 对应的代码

    ParameterReader pd(ParameterFilePath);
    pcl::RegionGrowing<PointT, pcl::Normal> reg;
    pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>);
    reg.setMinClusterSize(stoi(pd.getData("MinClusterSize")));
    reg.setMaxClusterSize(stoi(pd.getData("MaxClusterSize")));
    reg.setSearchMethod(tree);
    reg.setNumberOfNeighbours(stoi(pd.getData("NumberOfNeighbours")));
    reg.setInputCloud(CloudFilter);
    reg.setInputNormals(Normals);
    reg.setSmoothnessThreshold(stod(pd.getData("SmoothnessThreshold")) / 180.0 * M_PI); 
    reg.setCurvatureThreshold(stod(pd.getData("CurvatureThreshold")));
    std::vector <pcl::PointIndices> clusters;
    reg.extract(clusters);
    /* wk 添加: 可视化调试 */
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_segmented(new pcl::PointCloud<pcl::PointXYZRGB>());
    cloud_segmented = reg.getColoredCloud();
    pcl::visualization::CloudViewer viewer("Cluster viewer");
    viewer.showCloud(cloud_segmented);
    while (!viewer.wasStopped())
    {
    }
    /* wk 添加: 可视化调试 */
    

    (4)SACSegmentation 利用RANSAC算法对平面点云进行分割并拟合

      1. 参数:MaxIterations(最大迭代次数),threshold(距离阈值,判断点是否为当前拟合平面的内点,理论上该值越大平面越粗糙)

      2. 代码

    /*RanSAC拟合平面,并将平面内点分割出来*/
    
    pcl::SACSegmentation<PointT> seg;
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
    seg.setOptimizeCoefficients(true);
    seg.setModelType(pcl::SACMODEL_PLANE);
    seg.setMethodType(pcl::SAC_RANSAC);
    seg.setMaxIterations(stoi(pd.getData("Maxci")));
    seg.setDistanceThreshold(stod(pd.getData("threshold")));
    seg.setInputCloud(cloud);
    seg.segment(*inliers, *coefficients);
    
    // 分割内点,另存
    pcl::ExtractIndices<PointT> extract;
    PointCloudPtr cloud_plane(new pointCloud);
    extract.setInputCloud(cloud);
    extract.setIndices(inliers);
    extract.setNegative(false);
    extract.filter(*cloud_plane);

      3 部分效果图展示

    (1)原图

    (2)RegionGrowing分割效果图

     4 算法的局限性

      区域生长算法分割平面步骤及问题分析:针对分辨率低、扫描质量比较差的点云,如图所示,算法无法将破碎、扭曲的大块区域识别为平面区域,只能将这部分点判断为非平面点集舍弃掉。

            

      区域生长算法通常在分割细节处比较平滑的平面点云时,具有相当的优势。但是在处理“波纹”状点云时,就没什么优势了。而实际扫描点云的细节部位很多时候是如上图所示的,为了将曲率较小的曲面区别开,而调低平滑及曲率阈值时,这类从大视角上看明显是平面的点云会被rejected,从而导致分割失效。如下图所示,RegionGrowing更适合处理接近理想点云的这类点云,而不适合处理波动起伏状的、扫描精度较差的点云。

             

  • 相关阅读:
    Java web项目部署之SecureCRT+SecureFX的简单使用
    Ubuntu Linux系统用命令安装MySQL数据库
    Linux中操作tomcat的一些命令
    学习Java第二天
    学Java第一天
    在Windows10下在WSL中使用visual studio code
    Makefile中的变量赋值
    我见过的最好的关于typedef函数指针声明的解说
    C语言中打印格式
    Vim常用小操作【持续更新】
  • 原文地址:https://www.cnblogs.com/ghjnwk/p/10178975.html
Copyright © 2011-2022 走看看