c++ 使用RANSAC和pcl::SACSegmentation从点云中仅分割水平面(0*x+0*y+1*z+D=0)

5ktev3wc  于 2023-04-01  发布在  其他
关注(0)|答案(2)|浏览(339)

我想使用PCL库从点云提取水平面。有一个已知的程序使用RANSAC提取平面,该程序将找到最大的平面,但是我想将搜索限制为仅水平面(Ax+By+C*z+D=0,其中A、B=0且C=1)。下面的代码试图通过沿着z轴添加Axis向量来实现(0,0,1)和EpsAngle容差。
然而,它似乎并不像我期望的那样工作,看起来使用setAxis()设置Axis vector根本不会影响内层平面,我继续从相邻的墙壁而不是地板(水平)平面或沿着指定轴定向的平面获取侧平面。
点云是这样的,有4面墙(因此4个平面)和一个地板,也应该与第五个平面的结果。

pcl::PointCloud<pcl::PointXYZ>::Ptr pointcloudIn(new pcl::PointCloud<pcl::PointXYZ>());
// Segment the ground
pcl::ModelCoefficients::Ptr         plane (new pcl::ModelCoefficients);
pcl::PointIndices::Ptr              inliers (new pcl::PointIndices);
plane->values.resize(4);            // Make room for a plane equation (ax+by+cz+d=0)

pcl::SACSegmentation<pcl::PointXYZ>  seg;   // Create the segmentation object
seg.setAxis(Eigen::Vector3f(0., 0., 1.));   // Set the axis along which we need to search for a model perpendicular to
seg.setEpsAngle((10.*M_PI)/180.);           // Set maximum allowed difference between the model normal and the given axis in radians
seg.setOptimizeCoefficients(true);          // Coefficient refinement is required
seg.setMethodType(pcl::SAC_RANSAC);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setDistanceThreshold(0.05f);
seg.setInputCloud(pointcloudIn);
seg.segment(*inliers, *plane);

// Extract inliers
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud(pointcloudIn);
extract.setIndices(inliers);
extract.setNegative(false);             // Extract the inliers
extract.filter(*pointcloudPlane);       // pointcloudPlane contains the plane
dtcbnfnu

dtcbnfnu1#

使用SACMODEL_PARALLEL_PLANE代替SACMODEL_PLANEsetAxis。使用Z-轴作为轴,因此setAxis(Eigen::Vector3f::UnitZ())
您还应该考虑使用setEpsAngle(),不要将自己限制在完美的平面上。

fafcakar

fafcakar2#

我设法使用SACMODEL_PARALLEL_PLANE和setAxis(1,0,0)检测到一个水平表面。这很奇怪,但它可以工作(我希望提供0,0,1)。
可能是pcl中的一个bug(我用的是1.13)。

相关问题