点云是一种描述周围环境离散式的三维表达,无论是采用视觉三维重建,还是采用激光扫描获取的三维空间点云,往往会获取到环境周边的杂乱无章的点云,我们可以通过场景构建避免大部分,但是多多少少都会有一些杂点。
离群点滤波是一种常见的去除噪点的方法。它通过计算一个点的邻域内的点和该点的距离,来判断该点是否为噪点。如果该点距离邻域内的点的平均距离超过一定的阈值,则认为该点为噪点。
StatisticalOutlierRemoval 是一种基于统计学的离群点滤波方法。它通过计算每个点与其邻域内点的距离的标准差和平均值,来判断该点是否为噪点。如果该点与邻域内点的距离超过一定倍数的标准差,则认为该点为噪点。
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor(true);//
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filter(new pcl::PointCloud<pcl::PointXYZ>);
// 设置输入数据
sor.setInputCloud(m_PointOrigin);
//bool gt=sor.extract_removed_indices_
// 设置在过滤过程中保留的离群点的最大数量(设置为0表示忽略这个参数)
sor.setNegative(false);
// 设置统计方法使用的邻居数目
sor.setMeanK(50);
// 设置标准差乘数阈值,点到k近邻平均距离超过多少个标准差的点会被视为离群点
sor.setStddevMulThresh(10);
//提取过滤值
// sor.FilterIndices(true);
// 执行过滤
sor.filter(*cloud_filter);
pcl::IndicesConstPtr inpt= sor.getRemovedIndices();
const int* idx_ptr = &(*inpt)[0];
for (int i = 0; i < inpt->size(); ++i)
{
m_PointOrigin->points.erase(m_PointOrigin->points.begin() + idx_ptr[i] - i);
}
std::vector<std::string> vecLable;
for (int i = 0; i < cloud_filter->points.size(); ++i)
{
vecLable.push_back("K" + std::to_string(i));
}
其中需要注意的是
1. pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor(true);默认是不输出保留和移除的点云Index的,如果需要获取移除的Index和保留的点,构造时要给一个默认参数,这样就会输出相应的Index。
2. 获取移除的Index如下面的代码块所示
pcl::IndicesConstPtr inpt= sor.getRemovedIndices();
const int* idx_ptr = &(*inpt)[0];
通过int nSize=inpt->size();
idx_ptr[i]来便利获取每个移除的Index