基于PCL库函数的点云高斯滤波去噪方法

最近投稿点云数据处理的文章,经常被审稿人Diss不加点云去噪的相关介绍。点云去噪本身就是一个非常独立且复杂的研究领域,要想增加这部分内容的介绍,还是要下一点功夫的。这里,就跟大家分享一个基于PCL库的比较成熟的点云去噪方法实现,即高斯滤波。

高斯滤波(标准差去噪)

去噪结果:

点云数据去噪前(左),去噪后,sigma = 6(右)。

Mesh数据去噪前(左),去噪后(右)。

适用于呈正态分布的数据。考虑到离群点的特征,则可以定义某处点云小于某个密度,既点云无效。计算每个点到其最近的k个点平均距离。则点云中所有点的距离应构成高斯分布。给定均值与方差,可剔除3∑之外的点。

高斯函数的具体介绍转自:https://blog.csdn.net/jorg_zhao/article/details/52687448

这里有几个对高斯核函数进行参数设置的方法,单独列出来以方便学习:

setSigma()

设置高斯函数的方差。随着sigma的增大,整个高斯函数的尖峰逐渐减小,整体也变的更加平缓,则对图像的平滑效果越来越明显。

setThreshold()

设置高斯函数的作用域半径threshold,超过则不计入计算。

 setThresholdRelativeToSigma()

依据核函数方差获得关联作用域,sigma_coefficient^2 * sigma^2 = threshold。

实例代码如下:

//radius代表点云扫面的半径,这里需要用户计算获得

#include <iostream> 
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h> 
#include <pcl/point_cloud.h>
#include <boost/random.hpp>
#include <pcl/console/time.h>
#include <pcl/filters/convolution_3d.h>
#include <pcl/kdtree/kdtree_flann.h>
using namespace std;

vector<vector<double>> DenoisingPD_GaussianKernel(vector<vector<double>> pointCloudOriginal,double radius) {

    cout << "Gaussian denoising start:" << endl;
	pcl::PointCloud<pcl::PointXYZ>::Ptr inputcloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr outputcloud(new pcl::PointCloud<pcl::PointXYZ>);

	//Read point cloud in the input file
	for (int i = 0; i < pointCloudOriginal.size(); i++)
	{
		pcl::PointXYZ cloud_i;
		cloud_i.x = pointCloudOriginal[i][0];
		cloud_i.y = pointCloudOriginal[i][1];
		cloud_i.z = pointCloudOriginal[i][2];
		inputcloud->push_back(cloud_i);
	}

	//Set up the Gaussian Kernel
	pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ>::Ptr kernel(new pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ>);
	(*kernel).setSigma(4);
	(*kernel).setThresholdRelativeToSigma(4);
	std::cout << "Kernel made" << std::endl;

	//Set up the KDTree
	pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>);
	(*kdtree).setInputCloud(inputcloud);
	std::cout << "KdTree made" << std::endl;


	//Set up the Convolution Filter
	pcl::filters::Convolution3D <pcl::PointXYZ, pcl::PointXYZ, pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ> > convolution;
	convolution.setKernel(*kernel);
	convolution.setInputCloud(inputcloud);
	convolution.setSearchMethod(kdtree);
	convolution.setRadiusSearch(radius);
    convolution.setNumberOfThreads(10);//important! Set Thread number for openMP
	std::cout << "Convolution Start" << std::endl;
	convolution.convolve(*outputcloud);
	std::cout << "Convoluted" << std::endl;

    vector<vector<double>> pCDenosing(pointCloudOriginal.size());

	for (int i = 0; i < outputcloud->size(); i++) {
		vector<double> pi(3);
		pi[0] = outputcloud->at(i).x;
		pi[1] = outputcloud->at(i).y;
		pi[2] = outputcloud->at(i).z;
		pCDenosing[i] = pi;
	}
	cout << "Gaussian denoising finished!" << endl;
}

猜你喜欢

转载自blog.csdn.net/aliexken/article/details/107932964
今日推荐