本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。
由于网上对点云高斯滤波的描述较少,博客和知网上的大量论文直接用统计滤波的算法原理用来描述高斯滤波,使计算原理与PCL中点云高斯滤波代码的计算过程差别较大。因此,写下该文章进行科普。
1、原理概述
高斯滤波利用了高斯函数经傅里叶变换后仍具有高斯函数的特性。令指定区域的权重为高斯分布,从而将高频的噪声点滤除。具体是将某一数据点与其前后各 n n n个数据点加权平均,那些远大于操作距离的点被处理成固定的端点,这有助于识别间隙和端点。由于高斯滤波平均效果较小,在滤波的同时,能较好地保持数据原貌,因而常被使用。
2、实现流程
点云高斯滤波是一种在三维点云数据上应用高斯滤波器的技术。在点云高斯滤波中,每个点的邻域被加权平均,以产生平滑的点云,权重由一个高斯分布函数计算。在三维空间中函数形式为
G = e − d 2 2 σ 2 (1) G=e^{-\frac{d^2}{2\sigma^2}}\tag{1} G=e−2σ2d2(1)
式中, d d d为点云中每个点到邻域点的距离; σ σ σ为高斯函数的标准差。
对于每个点,高斯滤波器将其邻域内的所有点乘以一个对应的高斯权重,然后将其加权平均。过程公式为:
F ( x , y , z ) = ∑ i = 1 N p i G ( ∣ ∣ p i − p o ∣ ∣ ) ∑ i = 1 N G ( ∣ ∣ p i − p o ∣ ∣ ) (2) F(x,y,z)=\frac{\sum_{i=1}^Np_iG(||p_i-p_{o}||)}{\sum_{i=1}^NG(||p_i-p_{o}||)}\tag{2} F(x,y,z)=∑i=1NG(∣∣pi−po∣∣)∑i=1NpiG(∣∣pi−po∣∣)(2)
式中, p o p_o po为当前点的坐标值; p i p_i pi为邻域内第 i i i个点的坐标值; N N N为邻域内的点数; G ( p i − p o ) G(p_i-p_{o}) G(pi−po)为第 i i i个点的高斯权重,它与第 i i i个点与当前点的距离 p i − p o p_i-p_{o} pi−po有关; F ( x , y , z ) F(x,y,z) F(x,y,z)为滤波后点的坐标值。
3、算法源码
///
template<typename PointInT, typename PointOutT> bool
pcl::filters::GaussianKernel<PointInT, PointOutT>::initCompute ()
{
if (sigma_ == 0)
{
PCL_ERROR ("Sigma is not set or equal to 0!\n", sigma_);
return (false);
}
sigma_sqr_ = sigma_ * sigma_;
if (sigma_coefficient_)
{
if ((*sigma_coefficient_) > 6 || (*sigma_coefficient_) < 3)
{
PCL_ERROR ("Sigma coefficient (%f) out of [3..6]!\n", (*sigma_coefficient_));
return (false);
}
else
threshold_ = (*sigma_coefficient_) * (*sigma_coefficient_) * sigma_sqr_;
}
return (true);
}
///
template<typename PointInT, typename PointOutT> PointOutT
pcl::filters::GaussianKernel<PointInT, PointOutT>::operator() (const Indices& indices,
const std::vector<float>& distances)
{
using namespace pcl::common;
PointOutT result;
float total_weight = 0;
std::vector<float>::const_iterator dist_it = distances.begin ();
for (Indices::const_iterator idx_it = indices.begin ();
idx_it != indices.end ();
++idx_it, ++dist_it)
{
if (*dist_it <= threshold_ && isFinite ((*input_) [*idx_it]))
{
float weight = std::exp (-0.5f * (*dist_it) / sigma_sqr_);
result += weight * (*input_) [*idx_it];
total_weight += weight;
}
}
if (total_weight != 0)
result /= total_weight;
else
makeInfinite (result);
return (result);
}
4、参考文献
[1] 王东妍,于才,沈鹍,等. 点云数据在道岔关键节点几何检测应用 [J]. 测绘通报, 2024, (03): 107-112. DOI:10.13474/j.cnki.11-2246.2024.0318.
这篇文章是目前论文中唯一篇描述比较正确的,但是高斯核函数与PCL中的不同。