如何在 RANSAC 平面估算器中包含自定义约束/排名?

How to include custom constraints/rankings on a RANSAC plane estimator?

本文关键字:自定义 包含 约束 排名 RANSAC 平面      更新时间:2023-10-16

我正在尝试使用点云库从点云中分割平面,并且我有一些关于平面模型的先验信息(即,法线应该类似于z轴,高度(d)应该在0左右)。

有没有办法强制 RANSAC 算法首选与我之前的模型相似的系数?我认为这可以通过包含对模型的约束或修改所选平面的排名来实现。

我尝试使用直通过滤器过滤数据,该过滤器仅保留前一个平面周围的点。然后,我使用 SACSegmentation 对象在过滤后的数据上查找具有法线平面模型和法线角公差的平面。

我也尝试使用平行平面模型。


pcl::PointIndices::Ptr indices_for_segmentation(new pcl::PointIndices);
pcl::PassThrough<pcl::PointXYZL> pass_through;
pass_through.setInputCloud(cloud_);
pass_through.setIndices(clean_indices);
pass_through.setFilterFieldName("z");
pass_through.setFilterLimits(z_min_lim, z_max_lim);
pass_through.filter(indices_for_segmentation->indices);

pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
pcl::SACSegmentation<pcl::PointXYZL> ransac;
ransac.setOptimizeCoefficients(true);
ransac.setIndices(indices_for_segmentation);
ransac.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE);
ransac.setMethodType(pcl::SAC_RANSAC);
ransac.setDistanceThreshold(plane_thresh);
ransac.setInputCloud(cloud_);
ransac.setAxis(Eigen::Vector3f(0, 0, 1));  // search around the z axis
ransac.setEpsAngle(pcl::deg2rad(5));
ransac.segment(*inliers, *coefficients_);

当前解决方案的问题在于

  • 在这两种情况下(平行平面和法平面),该算法似乎都没有严格使用 epsAngle 约束(它似乎被用作某种推荐)
  • 这并不能满足对飞机高度的要求。
  • 直通滤波器有时只留下几个点,这使得平面估计不稳定(每一帧估计不同的平面)

在我看来,您对如何使用PCL有一些误解。

您正在使用pcl::SACSegmentation<pcl::PointXYZL>声明 RANSAC 估算器。

如果您只提供XYZ数据,您认为 RANSAC 将如何计算点法线和表面法线之间的角度差?正确,它不能

因此,首先,您必须计算输入云的法线。有关详细信息,请参阅本教程。

获得法线后,您只需对现有代码进行微小的更改即可。

pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
pcl::SACSegmentationFromNormals<pcl::PointXYZL, pcl::Normal> ransac; // ** change to SACSegmentationFromNormals
ransac.setOptimizeCoefficients(true);
ransac.setIndices(indices_for_segmentation);
ransac.setModelType(pcl::SACMODEL_NORMAL_PLANE);
ransac.setMethodType(pcl::SAC_RANSAC);
ransac.setDistanceThreshold(plane_thresh);
ransac.setInputCloud(cloud_);
ransac.setInputNormals(normals_); // ** set input normals
ransac.setAxis(Eigen::Vector3f(0, 0, 1));  // search around the z axis
ransac.setEpsAngle(pcl::deg2rad(5));
ransac.segment(*inliers, *coefficients_);

希望这有帮助,祝你好运!