pcl::BoundaryEstimation用于散乱点云的边界提取,但应该只适用于简单的点云,过于复杂的话效果应该不太好。同时,需要pcl::NormalEstimation先计算法线,算起来也挺慢的。
https://download.csdn.net/download/qq_32867925/10184934 这个资源里有一个文献可以参考理解
获取采样点的近邻点作为局部型面参考数据,以最小二乘法拟合该数据的微切平面,并将其向微切平面投影,根据采样点与其k近邻所对应投影点连线的最大夹角识别散乱点云边界特征。
文献中算法效果,可以看出有些许的改进。
资源代码结果:
pcl源代码:
#include <iostream>
#include <pcl/console/parse.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/features/boundary.h>
#include <math.h>
#include <boost/make_shared.hpp>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/range_image_visualizer.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/covariance_sampling.h>
#include <pcl/filters/normal_space.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/boundary.h>
#include <pcl/io/ply_io.h>
int estimateBorders(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud,float re,float reforn)
{
pcl::PointCloud<pcl::Boundary> boundaries;
//使用角度标准确定一组点是否位于边界上。该代码利用输入数据集中每个点估计的表面法线
pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundEst;
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normEst;
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary (new pcl::PointCloud<pcl::PointXYZ>);
normEst.setInputCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr(cloud));
normEst.setRadiusSearch(reforn);
normEst.compute(*normals);
boundEst.setInputCloud(cloud);
boundEst.setInputNormals(normals);
boundEst.setRadiusSearch(re);
boundEst.setAngleThreshold(M_PI/4);
boundEst.setSearchMethod(pcl::search::KdTree<pcl::PointXYZ>::Ptr (new pcl::search::KdTree<pcl::PointXYZ>));
boundEst.compute(boundaries);
for(int i = 0; i < cloud->points.size(); i++)
{
if(boundaries[i].boundary_point > 0)
{
cloud_boundary->push_back(cloud->points[i]);
}
}
boost::shared_ptr<pcl::visualization::PCLVisualizer> MView (new pcl::visualization::PCLVisualizer ("点云库PCL从入门到精通案例"));
int v1(0);
MView->createViewPort (0.0, 0.0, 0.5, 1.0, v1);
MView->setBackgroundColor (0.3, 0.3, 0.3, v1);
MView->addText ("Raw point clouds", 10, 10, "v1_text", v1);
int v2(0);
MView->createViewPort (0.5, 0.0, 1, 1.0, v2);
MView->setBackgroundColor (0.5, 0.5, 0.5, v2);
MView->addText ("Boudary point clouds", 10, 10, "v2_text", v2);
MView->addPointCloud<pcl::PointXYZ> (cloud, "sample cloud",v1);
MView->addPointCloud<pcl::PointXYZ> (cloud_boundary, "cloud_boundary",v2);
MView->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_COLOR, 1,0,0, "sample cloud",v1);
MView->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_COLOR, 0,1,0, "cloud_boundary",v2);
MView->addCoordinateSystem (1.0);
MView->initCameraParameters ();
MView->spin();
return 0;
}
int
main(int argc, char** argv)
{
//是以当前时间为种子,产生随意数。
//其中,time(NULL)用来获取当前时间,本质上得到的是一个大整数,然后用这个数来随机数。
//https://www.cnblogs.com/hangaozu/p/8280397.html 介绍这个函数
srand(time(NULL));
float re,reforn;
re=std::atof(argv[2]);//把字符串转换成浮点数
reforn=std::atof(argv[3]);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_src (new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile (argv[1], *cloud_src);
estimateBorders(cloud_src,re,reforn);
return 0;
}
结果: