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