PCL extracts point cloud boundary contour-AC method, plane contour

1. Overview

PCL point cloud boundary feature detection (with complete code C++)_pcl calculates point cloud feature values_McQueen_LT’s blog-CSDN blog

In terms of point cloud boundary feature detection (grid model boundary feature detection is already a deterministic problem, see grid model boundary detection), there is a method in PCL for point cloud boundaries that can be called s t a t e ? of ? t h e ? a r t state-of-the-artstate?of?the?art method, this method comes from D e t e c t i n g H o l e s i n P o i n t S e t S u r f a c e s Detecting\space Holes\space in\space Point\space Set\space SurfacesDetecting Holes in Point The paper Set Surfaces is called A n g l e C r i t e r i o n Angle\ CriterionAngle Criterion, or A C ACAC for short. Another method of detecting boundaries also proposed in this paper is H a l f d i s c C r i t e r i o n Halfdisc\ CriterionHalfdisc Criterion, H d C HdCHdC. At present, PCL should only integrate A C ACAC, because this method is indeed better than H d C HdCHdC and is enough. The ideas of these two methods are very simple, but they are very effective, and the classic methods that are often handed down are this simple and effective method.

2. AC method steps explained

3. AC method code

Original point cloud:

Calculation steps

1. Calculate the normal vector of the point cloud

2. Calculate the boundary of the point cloud

3. Display

Code

int PointCloudBoundary2(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{

// 1 Calculate normal vector
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
normalEstimation.setInputCloud(cloud);
normalEstimation.setSearchMethod(tree);
normalEstimation.setRadiusSearch(0.02); // Radius of normal vector
normalEstimation.compute(*normals);

/*pcl calculation boundary*/
pcl::PointCloud<pcl::Boundary>::Ptr boundaries(new pcl::PointCloud<pcl::Boundary>); //Declare a boundary class pointer as the return value
boundaries->resize(cloud->size()); //Initialize size
pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundary_estimation; //Declare a BoundaryEstimation class
boundary_estimation.setInputCloud(cloud); //Set input point cloud
boundary_estimation.setInputNormals(normals); //Set input normals
pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree_ptr(new pcl::search::KdTree<pcl::PointXYZ>);
boundary_estimation.setSearchMethod(kdtree_ptr); //Set the method of searching k nearest neighbors
boundary_estimation.setKSearch(30); //Set the number of k nearest neighbors
boundary_estimation.setAngleThreshold(M_PI * 0.6); //Set the angle threshold, which is greater than the threshold as the boundary
boundary_estimation.compute(*boundaries); //Calculate point cloud boundaries and save the results in boundaries
\t
cout << "The number of points in the boundary point cloud: "<< boundaries->size()<< endl;


/*Visualization*/
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_visual(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_boundary(new pcl::PointCloud<pcl::PointXYZRGB>);
cloud_visual->resize(cloud->size());
for (size_t i = 0; i < cloud->size(); i + + )
{
cloud_visual->points[i].x = cloud->points[i].x;
cloud_visual->points[i].y = cloud->points[i].y;
cloud_visual->points[i].z = cloud->points[i].z;
if (boundaries->points[i].boundary_point != 0)
{
cloud_visual->points[i].r = 255;
cloud_visual->points[i].g = 0;
cloud_visual->points[i].b = 0;
cloud_boundary->push_back(cloud_visual->points[i]);
}
else
{
cloud_visual->points[i].r = 255;
cloud_visual->points[i].g = 255;
cloud_visual->points[i].b = 255;
}
}
pcl::io::savePCDFileBinaryCompressed("D:\work\Pointclouds\clouds\all.pcd", *cloud_visual);
pcl::io::savePCDFileBinaryCompressed("D:\work\Pointclouds\clouds\boundaries.pcd", *cloud_boundary);
return 0;
}

Display

 boundary_estimation.setKSearch(30); //Set the number of k nearest neighbors
boundary_estimation.setAngleThreshold(M_PI * 0.6); //Set the angle threshold, which is greater than the threshold as the boundary
boundary_estimation.compute(*boundaries); //Calculate point cloud boundaries and save the results in boundaries

M_PI*0.6

M_PI*0.8

4. Plane profile

Original point cloud:

Steps:

1. Use RANSAC to extract planes

2. Extract plane

Code:

int PointCloudBoundary2(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{

// 1 Calculate normal vector
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
normalEstimation.setInputCloud(cloud);
normalEstimation.setSearchMethod(tree);
normalEstimation.setRadiusSearch(0.02); // Radius of normal vector
normalEstimation.compute(*normals);

/*pcl calculation boundary*/
pcl::PointCloud<pcl::Boundary>::Ptr boundaries(new pcl::PointCloud<pcl::Boundary>); //Declare a boundary class pointer as the return value
boundaries->resize(cloud->size()); //Initialize size
pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundary_estimation; //Declare a BoundaryEstimation class
boundary_estimation.setInputCloud(cloud); //Set input point cloud
boundary_estimation.setInputNormals(normals); //Set input normals
pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree_ptr(new pcl::search::KdTree<pcl::PointXYZ>);
boundary_estimation.setSearchMethod(kdtree_ptr); //Set the method of searching k nearest neighbors
boundary_estimation.setKSearch(30); //Set the number of k nearest neighbors
boundary_estimation.setAngleThreshold(M_PI * 0.8); //Set the angle threshold, greater than the threshold is the boundary
boundary_estimation.compute(*boundaries); //Calculate point cloud boundaries and save the results in boundaries
\t
cout << "The number of points in the boundary point cloud: "<< boundaries->size()<< endl;


/*Visualization*/
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_visual(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_boundary(new pcl::PointCloud<pcl::PointXYZRGB>);
cloud_visual->resize(cloud->size());
for (size_t i = 0; i < cloud->size(); i + + )
{
cloud_visual->points[i].x = cloud->points[i].x;
cloud_visual->points[i].y = cloud->points[i].y;
cloud_visual->points[i].z = cloud->points[i].z;
if (boundaries->points[i].boundary_point != 0)
{
cloud_visual->points[i].r = 255;
cloud_visual->points[i].g = 0;
cloud_visual->points[i].b = 0;
cloud_boundary->push_back(cloud_visual->points[i]);
}
else
{
cloud_visual->points[i].r = 255;
cloud_visual->points[i].g = 255;
cloud_visual->points[i].b = 255;
}
}
pcl::io::savePCDFileBinaryCompressed("D:\work\Pointclouds\clouds\all22.pcd", *cloud_visual);
pcl::io::savePCDFileBinaryCompressed("D:\work\Pointclouds\clouds\boundaries222.pcd", *cloud_boundary);
return 0;
}
/// <summary>
/// First extract the plane of the point cloud and then perform the boundary forest outline
/// </summary>
/// <param name="cloud"></param>
/// <returns></returns>
int PlaneCloudContour(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{

// 0 Calculate normal vector
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
normalEstimation.setInputCloud(cloud);
normalEstimation.setSearchMethod(tree);
normalEstimation.setRadiusSearch(0.02); // Radius of normal vector
normalEstimation.compute(*normals);


// 1 Propose the plane
//Extract the index of the plane point cloud
pcl::PointIndices::Ptr index_plane(new pcl::PointIndices);
pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> sacSegmentationFromNormals;
pcl::ModelCoefficients::Ptr mdelCoefficients_plane(new pcl::ModelCoefficients);
sacSegmentationFromNormals.setInputCloud(cloud);
sacSegmentationFromNormals.setOptimizeCoefficients(true);//Set the estimated model coefficients that need to be optimized
sacSegmentationFromNormals.setModelType(pcl::SACMODEL_NORMAL_PLANE); //Set the segmentation model
sacSegmentationFromNormals.setNormalDistanceWeight(0.1);//Set the surface normal weight coefficient
sacSegmentationFromNormals.setMethodType(pcl::SAC_RANSAC);//Set the parameter estimation method using RANSAC as the algorithm
sacSegmentationFromNormals.setMaxIterations(500); //Set the maximum number of iterations
sacSegmentationFromNormals.setDistanceThreshold(0.05); //Set the maximum allowed distance from the interior point to the model
sacSegmentationFromNormals.setInputCloud(cloud);
  sacSegmentationFromNormals.setInputNormals(normals);
sacSegmentationFromNormals.segment(*index_plane, *mdelCoefficients_plane);
std::cerr << "Plane coefficients: " << *mdelCoefficients_plane << std::endl;

//Point cloud extraction
pcl::ExtractIndices<pcl::PointXYZ> extractIndices;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_p(new pcl::PointCloud<pcl::PointXYZ>);
extractIndices.setInputCloud(cloud);
extractIndices.setIndices(index_plane);
extractIndices.setNegative(false);
extractIndices.filter(*cloud_p);
pcl::io::savePCDFileBinaryCompressed("D:\work\Pointclouds\clouds\planeCloud.pcd",*cloud_p);
\t // 2  
PointCloudBoundary2(cloud_p);
return 0;
}

Result:

Contour line calculation of plane point cloud-alpha shapes algorithm principle and implementation_α-shape algorithm-CSDN blog

Research on extracting point cloud building outlines using dual-threshold Alpha Shapes algorithm – Docin.com

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Algorithm skill tree Home page Overview 57624 people are learning the system