最近投稿点云数据处理的文章,经常被审稿人Diss不加点云去噪的相关介绍。点云去噪本身就是一个非常独立且复杂的研究领域,要想增加这部分内容的介绍,还是要下一点功夫的。这里,就跟大家分享一个基于PCL库的比较成熟的点云去噪方法实现,即高斯滤波。
高斯滤波(标准差去噪)
去噪结果:
点云数据去噪前(左),去噪后,sigma = 6(右)。
Mesh数据去噪前(左),去噪后(右)。
适用于呈正态分布的数据。考虑到离群点的特征,则可以定义某处点云小于某个密度,既点云无效。计算每个点到其最近的k个点平均距离。则点云中所有点的距离应构成高斯分布。给定均值与方差,可剔除3∑之外的点。
高斯函数的具体介绍转自:https://blog.csdn.net/jorg_zhao/article/details/52687448
这里有几个对高斯核函数进行参数设置的方法,单独列出来以方便学习:
setSigma()
设置高斯函数的方差。随着sigma的增大,整个高斯函数的尖峰逐渐减小,整体也变的更加平缓,则对图像的平滑效果越来越明显。
扫描二维码关注公众号,回复:
13228997 查看本文章
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;
}