PCL专栏目录及须知-优快云博客
1. 原理
双边滤波通过计算点云点周围的高斯权重,按照卷积核中元素强度值与中心点强度的近似情况来设置权重,强度值越相近,则该点权重越大。简单来说,就是取点云点附近的邻近点,然后通过其距离差异和强度差异,计算一个新的强度值出来,然后再赋值到该点上,以此实现强度的平滑。
(1)计算空间领域,得到的空间领域内的所有点。
(2)在该领域范围内,计算操作点和空间邻域内所有点的强度差异是否在高斯权重的范围内,如果不在高斯权重的范围内,那么使用高斯权重平滑强度。
(3)得到最终结果。
具体理解如下图,中心点为某次待计算双边滤波的点云点,其他点为邻近点。双边滤波计算时,通过该点与其他点的强度差异和距离远近,重新计算一个通过权重平均后的强度值。
2.应用场景
用于强度的降噪平滑。
双边滤波可以较好保留点云的边缘信息,避免降噪平滑之后,边缘点也被处理变得不清晰。
3.注意事项
双边滤波是对强度做平滑,不是对位置做平滑。
4.关键函数
(1)设置高斯搜索窗口的大小(也就是每一次高斯步长中,邻域范围的大小)
setHalfSize();
(2)高斯分布的标准差参数(即西格玛的值)
setStdDev()
5.代码
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/search/kdtree.h>
#include <pcl/filters/bilateral.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>
// 用于生成随机数
#include <random>
using namespace std;
int main()
{
/****************双边滤波********************/
// 原始点云(双边滤波的点云必须有强度值)
pcl::PointCloud<pcl::PointXYZI>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZI>());
pcl::io::loadPCDFile("D:/code/csdn/data/kmeansTest.pcd", *cloud); // 加载原始点云数据
// 写入由随机数生成的强度信息(用于示例代码,如果实际使用时,点云文件已有强度信息,不需要写入)
for (size_t i = 0; i < cloud->points.size(); i++)
{
random_device seed;
ranlux48 engine(seed());
uniform_int_distribution<> distrib(1, 254);
int random = distrib(engine);
cloud->points.at(i).intensity = random;
}
// 结果点云
pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZI>);
// kd树
pcl::search::KdTree<pcl::PointXYZI>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZI>); // 建树,用于邻近搜索(PCL双边滤波的原理为:对该点与其附近点的强度值计算高斯权重,然后再按照权重进行平滑,所以需要建树以搜索邻近点)
// 双边滤波
pcl::BilateralFilter<pcl::PointXYZI> filters; // 创建滤波器
filters.setInputCloud(cloud); // 输入原始点云
filters.setSearchMethod(tree); // 设置搜索树
filters.setHalfSize(0.1); // 设置高斯搜索的窗口大小(即每次以某点为基准进行邻近搜索,以计算高斯权重的范围大小)
filters.setStdDev(0.03); // 设置标准差(算权重需要,不知道看下百度百科)
filters.filter(*cloud_filtered); // 结果存入新点云对象中
/****************展示********************/
boost::shared_ptr<pcl::visualization::PCLVisualizer> view_raw(new pcl::visualization::PCLVisualizer("raw"));
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI>rawColor(cloud, "intensity");
view_raw->addPointCloud<pcl::PointXYZI>(cloud, rawColor, "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"));
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI>filteredColor(cloud, "intensity");
view_filtered->addPointCloud<pcl::PointXYZI>(cloud, filteredColor, "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;
}