赞
踩
PCL点云边界特征检测 (附完整代码 C++)_pcl计算点云特征值_McQueen_LT的博客-CSDN博客
在点云的边界特征检测(网格模型的边界特征检测已经是一个确定性问题了,见 网格模型边界检测)方面,PCL中有一个针对点云边界的可以称作为是s t a t e − o f − t h e − a r t state-of-the-artstate−of−the−art的方法,这个方法出自 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 Set Surfaces这篇论文,叫做 A n g l e C r i t e r i o n Angle\ CriterionAngle Criterion,简称 A C ACAC。这篇论文中还提出了另一种检测边界的方法是H a l f d i s c C r i t e r i o n Halfdisc\ CriterionHalfdisc Criterion,H d C HdCHdC。目前PCL中应该只集成了A C ACAC,因为这个方法确实比H d C HdCHdC好,已经够用了。这两种方法的思路都非常简单,但是却非常有效,而往往流传下来的经典方法都是这种简单有效的方法。
1、计算点云的法向量
2、计算点云的边界
3、显示
-
- int PointCloudBoundary2(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
- {
-
- // 1 计算法向量
- 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); // 法向量的半径
- normalEstimation.compute(*normals);
-
- /*pcl计算边界*/
- pcl::PointCloud<pcl::Boundary>::Ptr boundaries(new pcl::PointCloud<pcl::Boundary>); //声明一个boundary类指针,作为返回值
- boundaries->resize(cloud->size()); //初始化大小
- pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundary_estimation; //声明一个BoundaryEstimation类
- boundary_estimation.setInputCloud(cloud); //设置输入点云
- boundary_estimation.setInputNormals(normals); //设置输入法线
- pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree_ptr(new pcl::search::KdTree<pcl::PointXYZ>);
- boundary_estimation.setSearchMethod(kdtree_ptr); //设置搜寻k近邻的方式
- boundary_estimation.setKSearch(30); //设置k近邻数量
- boundary_estimation.setAngleThreshold(M_PI * 0.6); //设置角度阈值,大于阈值为边界
- boundary_estimation.compute(*boundaries); //计算点云边界,结果保存在boundaries中
-
- cout << "边界点云的点数 : "<< boundaries->size()<< endl;
-
-
- /*可视化*/
- 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;
- }
- boundary_estimation.setKSearch(30); //设置k近邻数量
- boundary_estimation.setAngleThreshold(M_PI * 0.6); //设置角度阈值,大于阈值为边界
- boundary_estimation.compute(*boundaries); //计算点云边界,结果保存在boundaries中
M_PI*0.8
原始点云:
1、采用RANSAC提取平面
2、提取平面
-
- int PointCloudBoundary2(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
- {
-
- // 1 计算法向量
- 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); // 法向量的半径
- normalEstimation.compute(*normals);
-
- /*pcl计算边界*/
- pcl::PointCloud<pcl::Boundary>::Ptr boundaries(new pcl::PointCloud<pcl::Boundary>); //声明一个boundary类指针,作为返回值
- boundaries->resize(cloud->size()); //初始化大小
- pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundary_estimation; //声明一个BoundaryEstimation类
- boundary_estimation.setInputCloud(cloud); //设置输入点云
- boundary_estimation.setInputNormals(normals); //设置输入法线
- pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree_ptr(new pcl::search::KdTree<pcl::PointXYZ>);
- boundary_estimation.setSearchMethod(kdtree_ptr); //设置搜寻k近邻的方式
- boundary_estimation.setKSearch(30); //设置k近邻数量
- boundary_estimation.setAngleThreshold(M_PI * 0.8); //设置角度阈值,大于阈值为边界
- boundary_estimation.compute(*boundaries); //计算点云边界,结果保存在boundaries中
-
- cout << "边界点云的点数 : "<< boundaries->size()<< endl;
-
-
- /*可视化*/
- 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>
- /// 先提取点云的平面然后在进行边界林廓
- /// </summary>
- /// <param name="cloud"></param>
- /// <returns></returns>
- int PlaneCloudContour(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
- {
-
- // 0 计算法向量
- 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); // 法向量的半径
- normalEstimation.compute(*normals);
-
-
- // 1 提出出平面
- // 提取平面点云的索引
- 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);//设置对估计的模型系数需要进行优化
- sacSegmentationFromNormals.setModelType(pcl::SACMODEL_NORMAL_PLANE); //设置分割模型
- sacSegmentationFromNormals.setNormalDistanceWeight(0.1);//设置表面法线权重系数
- sacSegmentationFromNormals.setMethodType(pcl::SAC_RANSAC);//设置采用RANSAC作为算法的参数估计方法
- sacSegmentationFromNormals.setMaxIterations(500); //设置迭代的最大次数
- sacSegmentationFromNormals.setDistanceThreshold(0.05); //设置内点到模型的距离允许最大值
- sacSegmentationFromNormals.setInputCloud(cloud);
- sacSegmentationFromNormals.setInputNormals(normals);
- sacSegmentationFromNormals.segment(*index_plane, *mdelCoefficients_plane);
- std::cerr << "Plane coefficients: " << *mdelCoefficients_plane << std::endl;
-
- // 点云提取
- 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);
- // 2
- PointCloudBoundary2(cloud_p);
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。