PCL 高斯滤波(永久免费版)
目录
- 一、概述
- 1.1 原理
- 1.2 实现步骤
- 1.3应用场景
- 二、关键函数
- 2.1 头文件
- 2.2 卷积核
- 2.3 高斯滤波
- 2.4 可视化
- 三、完整代码
- 四、结果展示
即日起,付费专栏所有内容将以永久免费形式陆续进行发表!!!抄袭狗加油抄
一、概述
1.1 原理
通过高斯分布函数计算各点的高斯权重,然后按照每个点领域点的与其的距离和权重进行高斯处理,以平滑点云。
(1)生成一个卷积核,并设置相应参数。
(2)按照步长获取每个点云点的领域点,作为高斯滤波的窗口。
(3)对每一个点云点,获取其窗口中的所有领域点,按照高斯权重进行高斯处理。
(4)按照卷积核所设置的参数修改窗口中每个点云点xyz分量。
(5)使得最终的结果点云中,每个点云窗口中的所有点云点都符合高斯分布规律。
(6)将处理后的点云组合成结果点云。
1.2 实现步骤
点云高斯滤波是一种常用的点云噪声平滑处理技术,其基本思想是通过对每个点附近的一组邻居点赋予权重,然后应用高斯函数对其进行加权平均,以降低随机噪声的影响。以下是点云高斯滤波的基本实现步骤:
- 设定滤波窗口:首先确定滤波半径,即感兴趣的邻居范围。这个半径决定了过滤的尺度,大的半径会提供更多的邻接点用于平滑。
- 建立邻接矩阵:遍历点云,对于每个点,找出其在指定半径内的所有邻居,并将它们的位置存储在一个邻接矩阵中。
- 计算权重:给每个邻接点分配一个高斯权重。高斯函数通常形式为 exp(-d^2 / (2 * sigma^2)),其中d是当前点到邻居点的距离,sigma是高斯函数的标准差,控制着滤波的精细程度。
- 求和平均:对每个待处理点,将它的坐标加上其邻接矩阵中所有邻居点坐标乘以其对应的高斯权重后的总和,然后除以权重之和,得到平滑后的点的坐标。
- 重复迭代:如果需要更平滑的效果,可以多次重复上述过程,每次使用前一次滤波的结果作为新的输入。
- 处理边界:由于高斯滤波可能会超出原始点云边界,所以需要采取特殊处理策略,例如扩展点云、采用边界条件(如镜像、零填充等)。
1.3应用场景
点云高斯滤波是一种处理三维几何数据(如激光雷达扫描生成的点云)的重要技术,主要用于以下几个应用场景:
噪声去除:点云中通常包含传感器采集时产生的随机噪声,高斯滤波可以平滑这些噪声点,提高数据质量。
表面细节增强:通过低通滤波,保留了较大的空间结构信息,而高频噪声被减弱,有助于突出点云表面的细节特征。
预处理:在后续的分析、分割或建模阶段,高斯滤波作为预处理步骤,能为后续算法提供更干净的数据输入。
SLAM(同时定位与地图构建):在机器人导航和自主系统中,对传感器数据进行高斯滤波有助于改善定位和环境理解的准确性。
3D重建:在计算机视觉领域,点云高斯滤波对于从点云生成连续的3D模型也有重要作用。
二、关键函数
2.1 头文件
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/search/kdtree.h>
#include <boost/thread/thread.hpp>
#include <pcl/filters/convolution_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
2.2 卷积核
// 卷积核pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ> kernel;// 卷积核(用于高斯滤波)kernel.setSigma(4); // 标准差kernel.setThresholdRelativeToSigma(4); // 关联作用域{可类比领域半径,通过公式计算}(用其自己的计算公式,公式为:||pi - q|| > sigma_coefficient^2 * sigma^2)kernel.setThreshold(0.05); // 卷积半径pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);// 进行领域搜索的kd树tree->setInputCloud(cloud);
2.3 高斯滤波
该函数使用 pcl::filters::Convolution3D
类来进行高斯滤波。
// -------------------------------高斯滤波---------------------------------pcl::filters::Convolution3D<pcl::PointXYZ, pcl::PointXYZ, pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ>> gk;gk.setKernel(kernel); // 设置卷积核gk.setInputCloud(cloud); // 输入点云gk.setNumberOfThreads(4); // 同时计算的线程数gk.setSearchMethod(tree); // 领域搜索的kd树gk.setRadiusSearch(0.02); // 搜索半径pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);gk.convolve(*cloud_filtered); // 计算
2.4 可视化
该函数用两个大窗口可视化滤波前和滤波后的点云数据。
// ------------------------------结果展示---------------------------------boost::shared_ptr<pcl::visualization::PCLVisualizer> view_raw(new pcl::visualization::PCLVisualizer("raw"));view_raw->addPointCloud<pcl::PointXYZ>(cloud, "raw cloud");view_raw->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "raw cloud");boost::shared_ptr<pcl::visualization::PCLVisualizer> view_filtered(new pcl::visualization::PCLVisualizer("filter"));view_filtered->addPointCloud<pcl::PointXYZ>(cloud_filtered, "filtered cloud");view_filtered->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "filtered cloud");while (!view_raw->wasStopped()){view_raw->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}while (!view_filtered->wasStopped()){view_filtered->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}
三、完整代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/search/kdtree.h>
#include <boost/thread/thread.hpp>
#include <pcl/filters/convolution_3d.h>
#include <pcl/visualization/pcl_visualizer.h>int main()
{// -----------------------------加载源点云数据-----------------------------pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPCDFile<pcl::PointXYZ>("bunny.pcd", *cloud) < 0){PCL_ERROR("Couldn't read file \n");return -1;}// 卷积核pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ> kernel;// 卷积核(用于高斯滤波)kernel.setSigma(4); // 标准差kernel.setThresholdRelativeToSigma(4); // 关联作用域{可类比领域半径,通过公式计算}(用其自己的计算公式,公式为:||pi - q|| > sigma_coefficient^2 * sigma^2)kernel.setThreshold(0.05); // 卷积半径pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);// 进行领域搜索的kd树tree->setInputCloud(cloud);// -------------------------------高斯滤波---------------------------------pcl::filters::Convolution3D<pcl::PointXYZ, pcl::PointXYZ, pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ>> gk;gk.setKernel(kernel); // 设置卷积核gk.setInputCloud(cloud); // 输入点云gk.setNumberOfThreads(4); // 同时计算的线程数gk.setSearchMethod(tree); // 领域搜索的kd树gk.setRadiusSearch(0.02); // 搜索半径pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);gk.convolve(*cloud_filtered); // 计算// ------------------------------结果展示---------------------------------boost::shared_ptr<pcl::visualization::PCLVisualizer> view_raw(new pcl::visualization::PCLVisualizer("raw"));view_raw->addPointCloud<pcl::PointXYZ>(cloud, "raw cloud");view_raw->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "raw cloud");boost::shared_ptr<pcl::visualization::PCLVisualizer> view_filtered(new pcl::visualization::PCLVisualizer("filter"));view_filtered->addPointCloud<pcl::PointXYZ>(cloud_filtered, "filtered cloud");view_filtered->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "filtered cloud");while (!view_raw->wasStopped()){view_raw->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}while (!view_filtered->wasStopped()){view_filtered->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}return 0;
}