PCL chapter10 BoundarEstimation边界提取(基于法线估计)

1、概述

这种边界检测的方式和上一次的不同:本次是基于点云的,有点云估计出法线,再由法线和点云数据估计出边界;上次https://blog.csdn.net/suyunzzz/article/details/99175706的边界估计是基于深度图像的。

注意:此API中有多个参数需要用户根据自己的数据进行调整,其中影响主要是估计法线的半径设置normEST.setRadiusSearch(reforn)。设置为分辨率的10倍时,效果较好,主要是对于法线估计。邻域半径选择太小了,噪声较大,估计的法线就容易出错,而搜索邻域半径设置的太大估计速度就比较慢。boundEst.setRadiusSearch(re),也设置10倍,太小则内部的很多点就都当成边界点了。最后一个参数是边界判断时的角度阈值,默认值为PI/2,此处设置为PI/4,用户也可以根据需要进行更改。

2、边界估计代码

//相关头文件
#include 
#include 
#include 

int estimateBorders(pcl::PointCloud::Ptr &cloud,float re,float reforn) 
{ 

	pcl::PointCloud boundaries; //保存边界估计结果
	pcl::BoundaryEstimation boundEst; //定义一个进行边界特征估计的对象
	pcl::NormalEstimation normEst; //定义一个法线估计的对象
	pcl::PointCloud::Ptr normals(new pcl::PointCloud); //保存法线估计的结果
	pcl::PointCloud::Ptr cloud_boundary (new pcl::PointCloud); 
	normEst.setInputCloud(pcl::PointCloud::Ptr(cloud)); 
	normEst.setRadiusSearch(reforn); //设置法线估计的半径
	normEst.compute(*normals); //将法线估计结果保存至normals
	//输出法线的个数
	std:cout<<"reforn: "<size() << std::endl;

	boundEst.setInputCloud(cloud); //设置输入的点云
	boundEst.setInputNormals(normals); //设置边界估计的法线,因为边界估计依赖于法线
	boundEst.setRadiusSearch(re); //设置边界估计所需要的半径
	boundEst.setAngleThreshold(M_PI/4); //边界估计时的角度阈值
	boundEst.setSearchMethod(pcl::search::KdTree::Ptr (new pcl::search::KdTree)); //设置搜索方式KdTree
	boundEst.compute(boundaries); //将边界估计结果保存在boundaries

	//输出边界点的个数
	std::cerr << "boundaries: " <points.size(); i++) 
	{ 
		
		if(boundaries[i].boundary_point > 0) 
		{ 
			cloud_boundary->push_back(cloud->points[i]); 
		} 
	} 

 3、全部代码

#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 

#include 
#include 


#include 
#include 


#include 
#include 
#include 

#include 

#include 

int estimateBorders(pcl::PointCloud::Ptr &cloud,float re,float reforn) 
{ 

	pcl::PointCloud boundaries; //保存边界估计结果
	pcl::BoundaryEstimation boundEst; //定义一个进行边界特征估计的对象
	pcl::NormalEstimation normEst; //定义一个法线估计的对象
	pcl::PointCloud::Ptr normals(new pcl::PointCloud); //保存法线估计的结果
	pcl::PointCloud::Ptr cloud_boundary (new pcl::PointCloud); 
	normEst.setInputCloud(pcl::PointCloud::Ptr(cloud)); 
	normEst.setRadiusSearch(reforn); //设置法线估计的半径
	normEst.compute(*normals); //将法线估计结果保存至normals
	//输出法线的个数
	std:cout<<"reforn: "<size() << std::endl;

	boundEst.setInputCloud(cloud); //设置输入的点云
	boundEst.setInputNormals(normals); //设置边界估计的法线,因为边界估计依赖于法线
	boundEst.setRadiusSearch(re); //设置边界估计所需要的半径
	boundEst.setAngleThreshold(M_PI/4); //边界估计时的角度阈值
	boundEst.setSearchMethod(pcl::search::KdTree::Ptr (new pcl::search::KdTree)); //设置搜索方式KdTree
	boundEst.compute(boundaries); //将边界估计结果保存在boundaries

	//输出边界点的个数
	std::cerr << "boundaries: " <points.size(); i++) 
	{ 
		
		if(boundaries[i].boundary_point > 0) 
		{ 
			cloud_boundary->push_back(cloud->points[i]); 
		} 
	} 

	//可视化
	boost::shared_ptr 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 (cloud, "sample cloud",v1);
	MView->addPointCloud (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)
{
	//srand(time(NULL));

	float re,reforn;
	re=std::atof(argv[2]);
	reforn=std::atof(argv[3]);
	pcl::PointCloud::Ptr cloud_src (new pcl::PointCloud); 



	//Laden der PCD-Files 
	pcl::io::loadPCDFile (argv[1], *cloud_src);


    // 创建滤波器对象
    pcl::PointCloud::Ptr cloud_filtered(new pcl::PointCloud);
    pcl::StatisticalOutlierRemoval sor;
    sor.setInputCloud (cloud_src);
    sor.setMeanK (100);//寻找每个点的50个最近邻点
    sor.setStddevMulThresh (1.0);//一个点的最近邻距离超过全局平均距离的一个标准差以上,就会舍弃
    sor.filter (*cloud_filtered);
    std::cout<<"cloud_src: "<points.size()<points.size()<

4、可视化

统计滤波去噪之前的边界估计 

PCL chapter10 BoundarEstimation边界提取(基于法线估计)_第1张图片

统计滤波去噪之后的边界估计

PCL chapter10 BoundarEstimation边界提取(基于法线估计)_第2张图片

 

 

你可能感兴趣的:(PointCloud)