PCL支持点云的形态学滤波,四种操作:侵蚀、膨胀、开(先侵蚀后膨胀)、闭(先膨胀后侵蚀)

关于渐进的策略,在初始cell_size_ 的基础上逐渐变大。满足如下公式:

$$window\_size =cell\_size *(2*base^{k}+1)$$

$$window\_size =cell\_size *(2*base*(k+1)+1)$$

 // Compute the series of window sizes and height thresholds
std::vector<float> height_thresholds;
std::vector<float> window_sizes;
int iteration = ;
float window_size = 0.0f;
float height_threshold = 0.0f; while (window_size < max_window_size_)
{
// Determine the initial window size.
if (exponential_)
window_size = cell_size_ * (2.0f * std::pow (base_, iteration) + 1.0f);
else
window_size = cell_size_ * (2.0f * (iteration+) * base_ + 1.0f); // Calculate the height threshold to be used in the next iteration.
if (iteration == )
height_threshold = initial_distance_;
else
height_threshold = slope_ * (window_size - window_sizes[iteration-]) * cell_size_ + initial_distance_; // Enforce max distance on height threshold
if (height_threshold > max_distance_)
height_threshold = max_distance_; window_sizes.push_back (window_size);
height_thresholds.push_back (height_threshold); iteration++;
}

在#include <pcl/filters/morphological_filter.h>中定义了枚举类型

  enum MorphologicalOperators
{
MORPH_OPEN,
MORPH_CLOSE,
MORPH_DILATE,
MORPH_ERODE
};

具体实现:

 template <typename PointT> void
pcl::applyMorphologicalOperator (const typename pcl::PointCloud<PointT>::ConstPtr &cloud_in,
float resolution, const int morphological_operator,
pcl::PointCloud<PointT> &cloud_out)
{
if (cloud_in->empty ())
return; pcl::copyPointCloud<PointT, PointT> (*cloud_in, cloud_out); pcl::octree::OctreePointCloudSearch<PointT> tree (resolution);

tree.setInputCloud (cloud_in);
tree.addPointsFromInputCloud (); float half_res = resolution / 2.0f; switch (morphological_operator)
{
case MORPH_DILATE:
case MORPH_ERODE:
{
for (size_t p_idx = ; p_idx < cloud_in->points.size (); ++p_idx)
{
Eigen::Vector3f bbox_min, bbox_max;
std::vector<int> pt_indices;
float minx = cloud_in->points[p_idx].x - half_res;
float miny = cloud_in->points[p_idx].y - half_res;
float minz = -std::numeric_limits<float>::max ();
float maxx = cloud_in->points[p_idx].x + half_res;
float maxy = cloud_in->points[p_idx].y + half_res;
float maxz = std::numeric_limits<float>::max ();
bbox_min = Eigen::Vector3f (minx, miny, minz);
bbox_max = Eigen::Vector3f (maxx, maxy, maxz);
tree.boxSearch (bbox_min, bbox_max, pt_indices); if (pt_indices.size () > )
{
Eigen::Vector4f min_pt, max_pt;
pcl::getMinMax3D<PointT> (*cloud_in, pt_indices, min_pt, max_pt); switch (morphological_operator)
{
case MORPH_DILATE:
{
cloud_out.points[p_idx].z = max_pt.z ();
break;
}
case MORPH_ERODE:
{
cloud_out.points[p_idx].z = min_pt.z ();
break;
}
}
}
}
break;
}
case MORPH_OPEN:
case MORPH_CLOSE:
{
pcl::PointCloud<PointT> cloud_temp; pcl::copyPointCloud<PointT, PointT> (*cloud_in, cloud_temp); for (size_t p_idx = ; p_idx < cloud_temp.points.size (); ++p_idx)
{
Eigen::Vector3f bbox_min, bbox_max;
std::vector<int> pt_indices;
float minx = cloud_temp.points[p_idx].x - half_res;
float miny = cloud_temp.points[p_idx].y - half_res;
float minz = -std::numeric_limits<float>::max ();
float maxx = cloud_temp.points[p_idx].x + half_res;
float maxy = cloud_temp.points[p_idx].y + half_res;
float maxz = std::numeric_limits<float>::max ();
bbox_min = Eigen::Vector3f (minx, miny, minz);
bbox_max = Eigen::Vector3f (maxx, maxy, maxz);
tree.boxSearch (bbox_min, bbox_max, pt_indices);

if (pt_indices.size () > )
{
Eigen::Vector4f min_pt, max_pt;
pcl::getMinMax3D<PointT> (cloud_temp, pt_indices, min_pt, max_pt); switch (morphological_operator)
{
case MORPH_OPEN:
{
cloud_out.points[p_idx].z = min_pt.z ();
break;
}
case MORPH_CLOSE:
{
cloud_out.points[p_idx].z = max_pt.z ();
break;
}
}
}
} cloud_temp.swap (cloud_out); for (size_t p_idx = ; p_idx < cloud_temp.points.size (); ++p_idx)
{
Eigen::Vector3f bbox_min, bbox_max;
std::vector<int> pt_indices;
float minx = cloud_temp.points[p_idx].x - half_res;
float miny = cloud_temp.points[p_idx].y - half_res;
float minz = -std::numeric_limits<float>::max ();
float maxx = cloud_temp.points[p_idx].x + half_res;
float maxy = cloud_temp.points[p_idx].y + half_res;
float maxz = std::numeric_limits<float>::max ();
bbox_min = Eigen::Vector3f (minx, miny, minz);
bbox_max = Eigen::Vector3f (maxx, maxy, maxz);
tree.boxSearch (bbox_min, bbox_max, pt_indices); if (pt_indices.size () > )
{
Eigen::Vector4f min_pt, max_pt;
pcl::getMinMax3D<PointT> (cloud_temp, pt_indices, min_pt, max_pt); switch (morphological_operator)
{
case MORPH_OPEN:
default:
{
cloud_out.points[p_idx].z = max_pt.z ();
break;
}
case MORPH_CLOSE:
{
cloud_out.points[p_idx].z = min_pt.z ();
break;
}
}
}
}
break;
}
default:
{
PCL_ERROR ("Morphological operator is not supported!\n");
break;
}
} return;
}

而渐进形态学滤波则是逐渐增大窗口,循环进行开操作

template <typename PointT> void
pcl::ProgressiveMorphologicalFilter<PointT>::extract (std::vector<int>& ground)
{
bool segmentation_is_possible = initCompute ();
if (!segmentation_is_possible)
{
deinitCompute ();
return;
} // Compute the series of window sizes and height thresholds
std::vector<float> height_thresholds;
std::vector<float> window_sizes;
int iteration = ;
float window_size = 0.0f;
float height_threshold = 0.0f; while (window_size < max_window_size_)
{
// Determine the initial window size.
if (exponential_)
window_size = cell_size_ * (2.0f * std::pow (base_, iteration) + 1.0f);
else
window_size = cell_size_ * (2.0f * (iteration+) * base_ + 1.0f); // Calculate the height threshold to be used in the next iteration.
if (iteration == )
height_threshold = initial_distance_;
else
height_threshold = slope_ * (window_size - window_sizes[iteration-]) * cell_size_ + initial_distance_; // Enforce max distance on height threshold
if (height_threshold > max_distance_)
height_threshold = max_distance_; window_sizes.push_back (window_size);
height_thresholds.push_back (height_threshold); iteration++;
} // Ground indices are initially limited to those points in the input cloud we
// wish to process
ground = *indices_; // Progressively filter ground returns using morphological open
for (size_t i = ; i < window_sizes.size (); ++i)
{
PCL_DEBUG (" Iteration %d (height threshold = %f, window size = %f)...",
i, height_thresholds[i], window_sizes[i]); // Limit filtering to those points currently considered ground returns
typename pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
pcl::copyPointCloud<PointT> (*input_, ground, *cloud); // Create new cloud to hold the filtered results. Apply the morphological
// opening operation at the current window size.
typename pcl::PointCloud<PointT>::Ptr cloud_f (new pcl::PointCloud<PointT>);
pcl::applyMorphologicalOperator<PointT> (cloud, window_sizes[i], MORPH_OPEN, *cloud_f); // Find indices of the points whose difference between the source and
// filtered point clouds is less than the current height threshold.
std::vector<int> pt_indices;
for (size_t p_idx = ; p_idx < ground.size (); ++p_idx)
{
float diff = cloud->points[p_idx].z - cloud_f->points[p_idx].z;
if (diff < height_thresholds[i])
pt_indices.push_back (ground[p_idx]);
} // Ground is now limited to pt_indices
ground.swap (pt_indices); PCL_DEBUG ("ground now has %d points\n", ground.size ());
} deinitCompute ();
}

[PCL]点云渐进形态学滤波的更多相关文章

  1. PCL—点云分割(基于形态学) 低层次点云处理

    博客转载自:http://www.cnblogs.com/ironstark/p/5017428.html 1.航空测量与点云的形态学 航空测量是对地形地貌进行测量的一种高效手段.生成地形三维形貌一直 ...

  2. PCL—点云滤波(初步处理)

    博客转载自:http://www.cnblogs.com/ironstark/p/4991232.html 点云滤波的概念 点云滤波是点云处理的基本步骤,也是进行 high level 三维图像处理之 ...

  3. PCL—点云滤波(基于点云频率) 低层次点云处理

    博客转载自:http://www.cnblogs.com/ironstark/p/5010771.html 1.点云的频率 今天在阅读分割有关的文献时,惊喜的发现,点云和图像一样,有可能也存在频率的概 ...

  4. PCL中点云数据格式之间的转化

    (1) 关于pcl::PCLPointCloud2::Ptr和pcl::PointCloud<pcl::PointXYZ>两中数据结构的区别 pcl::PointXYZ::PointXYZ ...

  5. PCL点云分割(1)

    点云分割是根据空间,几何和纹理等特征对点云进行划分,使得同一划分内的点云拥有相似的特征,点云的有效分割往往是许多应用的前提,例如逆向工作,CAD领域对零件的不同扫描表面进行分割,然后才能更好的进行空洞 ...

  6. PCL点云配准(2)

    (1)正态分布变换进行配准(normal Distributions Transform) 介绍关于如何使用正态分布算法来确定两个大型点云之间的刚体变换,正态分布变换算法是一个配准算法,它应用于三维点 ...

  7. PCL—点云分割(邻近信息) 低层次点云处理

    博客转载自:http://www.cnblogs.com/ironstark/p/5000147.html 分割给人最直观的影响大概就是邻居和我不一样.比如某条界线这边是中华文明,界线那边是西方文,最 ...

  8. PCL点云库(Point Cloud Library)简介

    博客转载自:http://www.pclcn.org/study/shownews.php?lang=cn&id=29 什么是PCL PCL(Point Cloud Library)是在吸收了 ...

  9. PCL点云库:ICP算法

    ICP(Iterative Closest Point迭代最近点)算法是一种点集对点集配准方法.在VTK.PCL.MRPT.MeshLab等C++库或软件中都有实现,可以参见维基百科中的ICP Alg ...

随机推荐

  1. C++ 数字转换为string类型

    经常需要循环读入多组序号的图像,需要将int转换为string,简单的函数代码如下: #include <sstream>#include <string> string In ...

  2. Wpf/Wp/Silverlight-Chart图表控件:柱状图、饼状图等使用汇总

    链接:http://www.cnblogs.com/jimson/archive/2010/06/21/Wpfchat.html http://www.cnblogs.com/mgen/p/32361 ...

  3. pointers on c (day 1,chapter3)

    第3章 数据 c中,仅有4中基本数据类型——整型.浮点型.指针和聚合类型(如数组和结构等). 整型:字符.短整型和长整型,它们都分为有符号(signed)和无符号(unsigned). short i ...

  4. strncpy,strcpy

    strncpy不会为des自动添加“\0” strcpy遇空结束,自动添加结束符 结论: 1.使用strcpy时一定不能用于无结束符的字符串,因为strcpy依赖\0判断源字符串的结束 2.使用str ...

  5. compass Sprites 雪碧图 小图片合成[Sass和compass学习笔记]

    demo 源码 地址 https://github.com/qqqzhch/webfans 什么是雪碧图? CSS雪碧 即CSS Sprites,也有人叫它CSS精灵,是一种CSS图像合并技术,该方法 ...

  6. linux设备驱动

    http://blog.csdn.net/bob_fly1984/article/details/8820670 struct ov5640_data {    struct ov5640_platf ...

  7. ejabberd 在eclipse(erlide)中的配置、调试、运行

    最近在折腾ejabberd,将ejabberd项目配置到eclipse中进行编译.调试等,现在将过程记下来,希望能帮助到需要的人. 准备 本次环境是在linux中进行,博主的linux是fedora2 ...

  8. winform 进程,线程

    进程:一个程序就是一个进程,但是也有一个程序需要多个进程来支持的情况 进程要使用的类是:Process它在命名空间:System.Diagnostics; 静态方法Start(); 点击按钮打开一个程 ...

  9. c++利用循环数组建立FIFO模板队列

    可直接编译运行,其中status()方法效果如图: #include <iostream> using std::cout; template<typename T> clas ...

  10. C语言中定义全局变量

    (1)在C语言的头文件中定义变量出现的问题 最好不要傻嘻嘻的在头文件里定义什么东西.比如全局变量: /*xx头文件*/ #ifndef  _XX_头文件.H #define  _XX_头文件.H in ...