为什么pcl::PointNormal RANSAC圆柱模型在估计模型系数时声明不包含法线?

问题描述 投票:0回答:1

我一直在尝试使用 pcl 工具将圆柱体模型拟合到生成的点云。我一直在修改文档here中提供的示例代码。

根据我的理解,

pcl::SampleConsensusModelCylinder
需要法线数据,因此我在代码中添加了一个新的检查来检查
-cf
参数。然后,代码计算称为
pcl::Normals
cloud_normals
类型点云中每个点的法线,然后将其与原始
pcl::PointXYZ
类型点云
cloud
连接起来。我将其保存到一个名为
pcl::PointNormal
的新
cloud_normalpoints
型点云中,并尝试使用 RANdom SAmple Consensus (RANSAC) 来拟合
pcl::SampleConsensusModelCylinder

我已包含以下代码:

  else if (pcl::console::find_argument (argc, argv, "-cf") >= 0 )
  {
    //TODO: find fastest way to fit cylinder model to point cloud
    // the cloud_normals point cloud will be used to store the point cloud or normals
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
    cloud_normals->width    = 500;
    cloud_normals->height   = 1;
    // is_dense is True if no points have NaN or Inf in any of their floating points field
    cloud_normals->is_dense = false;
    cloud_normals->points.resize (cloud_normals->width * cloud_normals->height);


    // the NormalEstimation object ne is created and will estimate the normals and curvature at each point
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    // the search:KdTree object pointer points to a search method for finding points in 3D space (3D point clouds)
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
    // use the filtered cloud as an input to the normal estimator
    ne.setInputCloud (cloud);
    // set number of k-nearest neighbours to use for feature estimation to 50
    ne.setKSearch (50);
    // compute normals and save these to the clouds_normals point cloud
    ne.compute (*cloud_normals);

    pcl::PointCloud<pcl::PointNormal>::Ptr cloud_normalpoints (new pcl::PointCloud<pcl::PointNormal>);
    cloud_normalpoints->width    = 500;
    cloud_normalpoints->height   = 1;
    // is_dense is True if no points have NaN or Inf in any of their floating points field
    cloud_normalpoints->is_dense = false;
    cloud_normalpoints->points.resize (cloud_normalpoints->width * cloud_normalpoints->height);

    pcl::concatenateFields(*cloud,*cloud_normals,*cloud_normalpoints);

    //TODO: Solve normals not given error
    pcl::SampleConsensusModelCylinder<pcl::PointNormal, pcl::Normal>::Ptr
      model_c (new pcl::SampleConsensusModelCylinder<pcl::PointNormal, pcl::Normal> (cloud_normalpoints));
    // Declares ransac as a ransac implementation searching for a cylinder (according to model_c -> in cloud)
    pcl::RandomSampleConsensus<pcl::PointNormal> ransac (model_c);
    // Set distance threshold of .01 -> believe this is for inliers
    ransac.setDistanceThreshold (.01);
    // Compute model coefficients and find inliers
    ransac.computeModel();
    
    // Return indices of best set of inliers so far for this model
    ransac.getInliers(inliers);
  }

我还添加了一些更多的代码来生成包含圆柱体的原始点云,但这有效,所以我不会在这里详细介绍。

当我运行代码时,它会进入计算模型阶段,然后抛出以下错误:

[pcl::SampleConsensusModelCylinder::computeModelCoefficients] No input dataset containing normals was given!

有谁知道这是为什么吗?

cloud_normalpoints
云包含为每个点找到的正常数据。我应该以不同的方式设置 RANSAC 估算器吗?我应该使用不同的点类型吗?我对 pcl 比较陌生,因此我们将不胜感激!

c++ geometry point-cloud-library point-clouds ransac
1个回答
0
投票

您必须调用 setInputNormals

 的函数 
model_c
,并在其中传递 
cloud_normals
。 您在
SampleConsensusModelCylinder
的构造函数中传递的云仅设置 XYZ 信息,但不用于法线。

本教程也可能对您感兴趣:https://pcl.readthedocs.io/projects/tutorials/en/latest/cyclone_segmentation.html

© www.soinside.com 2019 - 2024. All rights reserved.