如何在RANSAC平面估算器上包含自定义约束/等级?

时间:2019-07-16 13:59:54

标签: c++ point-cloud-library robotics ransac

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

有没有一种方法可以迫使RANSAC算法更喜欢与先前模型相似的系数?我认为,可以通过在模型中加入约束或修改所选飞机的排名来实现。

我尝试使用PassThrough过滤器过滤数据,该过滤器仅保留围绕先前平面的点。然后,我使用一个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约束(似乎有些推荐)
  • 这并不能满足飞机高度的要求。
  • 通过滤波器有时仅留下几个点,这使得平面估计不稳定(每帧估计一个不同的平面)

1 个答案:

答案 0 :(得分:0)

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

您要使用pcl::SACSegmentation<pcl::PointXYZL>声明RANSAC估计量。

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

因此,首先,您必须计算输入云的法线。有关更多信息,请参见此tutorial

一旦有了法线,您只需要对现有代码进行少量更改即可。

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_);

希望这会有所帮助,祝您好运!