我一直在尝试使用pcl工具将圆柱体模型拟合到生成的点云上,我一直在修改here文档中提供的示例代码。
据我所知,pcl::SampleConsensusModelCylinder
需要法线数据,所以我在代码中添加了一个新的检查,用于检查-cf
参数。然后,代码计算pcl::Normals
类型点云中每个点的法线(称为cloud_normals
),并将其与原始pcl::PointXYZ
类型点云连接。我将其保存到称为cloud_normalpoints
的新的pcl::PointNormal
类型的点云,并且利用该点云,我尝试使用随机采样一致性(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比较陌生,所以任何帮助都将不胜感激!
1条答案
按热度按时间rryofs0p1#
你必须调用
model_c
的函数setInputNormals
,在这里你传递了cloud_normals
,你在SampleConsensusModelCylinder
的构造函数中传递的云只设置XYZ信息,而不用于法线。本教程也可能对您感兴趣:https://pcl.readthedocs.io/projects/tutorials/en/latest/cylinder_segmentation.html