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

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

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

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

  1. // Compute the series of window sizes and height thresholds
  2. std::vector<float> height_thresholds;
  3. std::vector<float> window_sizes;
  4. int iteration = ;
  5. float window_size = 0.0f;
  6. float height_threshold = 0.0f;
  7.  
  8. while (window_size < max_window_size_)
  9. {
  10. // Determine the initial window size.
  11. if (exponential_)
  12. window_size = cell_size_ * (2.0f * std::pow (base_, iteration) + 1.0f);
  13. else
  14. window_size = cell_size_ * (2.0f * (iteration+) * base_ + 1.0f);
  15.  
  16. // Calculate the height threshold to be used in the next iteration.
  17. if (iteration == )
  18. height_threshold = initial_distance_;
  19. else
  20. height_threshold = slope_ * (window_size - window_sizes[iteration-]) * cell_size_ + initial_distance_;
  21.  
  22. // Enforce max distance on height threshold
  23. if (height_threshold > max_distance_)
  24. height_threshold = max_distance_;
  25.  
  26. window_sizes.push_back (window_size);
  27. height_thresholds.push_back (height_threshold);
  28.  
  29. iteration++;
  30. }

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

  1. enum MorphologicalOperators
  2. {
  3. MORPH_OPEN,
  4. MORPH_CLOSE,
  5. MORPH_DILATE,
  6. MORPH_ERODE
  7. };

具体实现:

  1. template <typename PointT> void
  2. pcl::applyMorphologicalOperator (const typename pcl::PointCloud<PointT>::ConstPtr &cloud_in,
  3. float resolution, const int morphological_operator,
  4. pcl::PointCloud<PointT> &cloud_out)
  5. {
  6. if (cloud_in->empty ())
  7. return;
  8.  
  9. pcl::copyPointCloud<PointT, PointT> (*cloud_in, cloud_out);
  10.  
  11. pcl::octree::OctreePointCloudSearch<PointT> tree (resolution);

  12. tree.setInputCloud (cloud_in);
  13. tree.addPointsFromInputCloud ();
  14.  
  15. float half_res = resolution / 2.0f;
  16.  
  17. switch (morphological_operator)
  18. {
  19. case MORPH_DILATE:
  20. case MORPH_ERODE:
  21. {
  22. for (size_t p_idx = ; p_idx < cloud_in->points.size (); ++p_idx)
  23. {
  24. Eigen::Vector3f bbox_min, bbox_max;
  25. std::vector<int> pt_indices;
  26. float minx = cloud_in->points[p_idx].x - half_res;
  27. float miny = cloud_in->points[p_idx].y - half_res;
  28. float minz = -std::numeric_limits<float>::max ();
  29. float maxx = cloud_in->points[p_idx].x + half_res;
  30. float maxy = cloud_in->points[p_idx].y + half_res;
  31. float maxz = std::numeric_limits<float>::max ();
  32. bbox_min = Eigen::Vector3f (minx, miny, minz);
  33. bbox_max = Eigen::Vector3f (maxx, maxy, maxz);
  34. tree.boxSearch (bbox_min, bbox_max, pt_indices);
  35.  
  36. if (pt_indices.size () > )
  37. {
  38. Eigen::Vector4f min_pt, max_pt;
  39. pcl::getMinMax3D<PointT> (*cloud_in, pt_indices, min_pt, max_pt);
  40.  
  41. switch (morphological_operator)
  42. {
  43. case MORPH_DILATE:
  44. {
  45. cloud_out.points[p_idx].z = max_pt.z ();
  46. break;
  47. }
  48. case MORPH_ERODE:
  49. {
  50. cloud_out.points[p_idx].z = min_pt.z ();
  51. break;
  52. }
  53. }
  54. }
  55. }
  56. break;
  57. }
  58. case MORPH_OPEN:
  59. case MORPH_CLOSE:
  60. {
  61. pcl::PointCloud<PointT> cloud_temp;
  62.  
  63. pcl::copyPointCloud<PointT, PointT> (*cloud_in, cloud_temp);
  64.  
  65. for (size_t p_idx = ; p_idx < cloud_temp.points.size (); ++p_idx)
  66. {
  67. Eigen::Vector3f bbox_min, bbox_max;
  68. std::vector<int> pt_indices;
  69. float minx = cloud_temp.points[p_idx].x - half_res;
  70. float miny = cloud_temp.points[p_idx].y - half_res;
  71. float minz = -std::numeric_limits<float>::max ();
  72. float maxx = cloud_temp.points[p_idx].x + half_res;
  73. float maxy = cloud_temp.points[p_idx].y + half_res;
  74. float maxz = std::numeric_limits<float>::max ();
  75. bbox_min = Eigen::Vector3f (minx, miny, minz);
  76. bbox_max = Eigen::Vector3f (maxx, maxy, maxz);
  77. tree.boxSearch (bbox_min, bbox_max, pt_indices);

  78. if (pt_indices.size () > )
  79. {
  80. Eigen::Vector4f min_pt, max_pt;
  81. pcl::getMinMax3D<PointT> (cloud_temp, pt_indices, min_pt, max_pt);
  82.  
  83. switch (morphological_operator)
  84. {
  85. case MORPH_OPEN:
  86. {
  87. cloud_out.points[p_idx].z = min_pt.z ();
  88. break;
  89. }
  90. case MORPH_CLOSE:
  91. {
  92. cloud_out.points[p_idx].z = max_pt.z ();
  93. break;
  94. }
  95. }
  96. }
  97. }
  98.  
  99. cloud_temp.swap (cloud_out);
  100.  
  101. for (size_t p_idx = ; p_idx < cloud_temp.points.size (); ++p_idx)
  102. {
  103. Eigen::Vector3f bbox_min, bbox_max;
  104. std::vector<int> pt_indices;
  105. float minx = cloud_temp.points[p_idx].x - half_res;
  106. float miny = cloud_temp.points[p_idx].y - half_res;
  107. float minz = -std::numeric_limits<float>::max ();
  108. float maxx = cloud_temp.points[p_idx].x + half_res;
  109. float maxy = cloud_temp.points[p_idx].y + half_res;
  110. float maxz = std::numeric_limits<float>::max ();
  111. bbox_min = Eigen::Vector3f (minx, miny, minz);
  112. bbox_max = Eigen::Vector3f (maxx, maxy, maxz);
  113. tree.boxSearch (bbox_min, bbox_max, pt_indices);
  114.  
  115. if (pt_indices.size () > )
  116. {
  117. Eigen::Vector4f min_pt, max_pt;
  118. pcl::getMinMax3D<PointT> (cloud_temp, pt_indices, min_pt, max_pt);
  119.  
  120. switch (morphological_operator)
  121. {
  122. case MORPH_OPEN:
  123. default:
  124. {
  125. cloud_out.points[p_idx].z = max_pt.z ();
  126. break;
  127. }
  128. case MORPH_CLOSE:
  129. {
  130. cloud_out.points[p_idx].z = min_pt.z ();
  131. break;
  132. }
  133. }
  134. }
  135. }
  136. break;
  137. }
  138. default:
  139. {
  140. PCL_ERROR ("Morphological operator is not supported!\n");
  141. break;
  142. }
  143. }
  144.  
  145. return;
  146. }

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

  1. template <typename PointT> void
  2. pcl::ProgressiveMorphologicalFilter<PointT>::extract (std::vector<int>& ground)
  3. {
  4. bool segmentation_is_possible = initCompute ();
  5. if (!segmentation_is_possible)
  6. {
  7. deinitCompute ();
  8. return;
  9. }
  10.  
  11. // Compute the series of window sizes and height thresholds
  12. std::vector<float> height_thresholds;
  13. std::vector<float> window_sizes;
  14. int iteration = ;
  15. float window_size = 0.0f;
  16. float height_threshold = 0.0f;
  17.  
  18. while (window_size < max_window_size_)
  19. {
  20. // Determine the initial window size.
  21. if (exponential_)
  22. window_size = cell_size_ * (2.0f * std::pow (base_, iteration) + 1.0f);
  23. else
  24. window_size = cell_size_ * (2.0f * (iteration+) * base_ + 1.0f);
  25.  
  26. // Calculate the height threshold to be used in the next iteration.
  27. if (iteration == )
  28. height_threshold = initial_distance_;
  29. else
  30. height_threshold = slope_ * (window_size - window_sizes[iteration-]) * cell_size_ + initial_distance_;
  31.  
  32. // Enforce max distance on height threshold
  33. if (height_threshold > max_distance_)
  34. height_threshold = max_distance_;
  35.  
  36. window_sizes.push_back (window_size);
  37. height_thresholds.push_back (height_threshold);
  38.  
  39. iteration++;
  40. }
  41.  
  42. // Ground indices are initially limited to those points in the input cloud we
  43. // wish to process
  44. ground = *indices_;
  45.  
  46. // Progressively filter ground returns using morphological open
  47. for (size_t i = ; i < window_sizes.size (); ++i)
  48. {
  49. PCL_DEBUG (" Iteration %d (height threshold = %f, window size = %f)...",
  50. i, height_thresholds[i], window_sizes[i]);
  51.  
  52. // Limit filtering to those points currently considered ground returns
  53. typename pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
  54. pcl::copyPointCloud<PointT> (*input_, ground, *cloud);
  55.  
  56. // Create new cloud to hold the filtered results. Apply the morphological
  57. // opening operation at the current window size.
  58. typename pcl::PointCloud<PointT>::Ptr cloud_f (new pcl::PointCloud<PointT>);
  59. pcl::applyMorphologicalOperator<PointT> (cloud, window_sizes[i], MORPH_OPEN, *cloud_f);
  60. // Find indices of the points whose difference between the source and
  61. // filtered point clouds is less than the current height threshold.
  62. std::vector<int> pt_indices;
  63. for (size_t p_idx = ; p_idx < ground.size (); ++p_idx)
  64. {
  65. float diff = cloud->points[p_idx].z - cloud_f->points[p_idx].z;
  66. if (diff < height_thresholds[i])
  67. pt_indices.push_back (ground[p_idx]);
  68. }
  69.  
  70. // Ground is now limited to pt_indices
  71. ground.swap (pt_indices);
  72.  
  73. PCL_DEBUG ("ground now has %d points\n", ground.size ());
  74. }
  75.  
  76. deinitCompute ();
  77. }

[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. android中四大组件之间相互通信

    好久没有写有关android有关的博客了,今天主要来谈一谈android中四大组件.首先,接触android的人,都应该知道android中有四大组件,activity,service,broadca ...

  2. getFields()和getDeclaredFields()的区别

    getFields()获得某个类的所有的公共(public)的字段,包括父类. getDeclaredFields()获得某个类的所有申明的字段,即包括public.private和proteced, ...

  3. hierarchyid

    hierarchyid: http://www.cnblogs.com/shanyou/archive/2011/07/01/2095968.html RABBITMQ: http://www.rab ...

  4. 激活Windows 8.1 RTM原来如此简单

    日前,Windows 8.1 RTM各种版本已经在坊间泄露开来,许多迫不及待的用户也开始跃跃欲试,但可能有人会疑惑,Windows 8.1RTM该如何激活?其实,它远比你想象的要简单. 实际上,Win ...

  5. jquery:closest和parents的主要区别

    closest和parents的主要区别是:1,前者从当前元素开始匹配寻找,后者从父元素开始匹配寻找:2,前者逐级向上查找,直到发现匹配的元素后就停止了,后者一直向上查找直到根元素,然后把这些元素放进 ...

  6. PHP操作字符串 截取指定长度字符 移除字符串两侧 左侧 右侧指定字符 或空白字符 替换字符

    trim() trim() 函数移除字符串两侧的空白字符或其他预定义字符. <?php $str = "Hello World!"; echo $str . "&l ...

  7. redis、memcached、mongoDB 对比与安装

    一.redis.memcached.mongoDB 对比 Memcached 和 Redis都是内存型数据库,数据保存在内存中,通过tcp直接存取,速度快,并发高.Mongodb是文档型的非关系型数据 ...

  8. [LintCode] Majority Number 求众数

    Given an array of integers, the majority number is the number that occurs more than half of the size ...

  9. ZK textbox Constraint验证

    test.zul: <?page title="" contentType="text/html;charset=UTF-8"?> <zk x ...

  10. jquer 基础篇 dom操作

    DOM操作: 1.新增元素:创建元素:$("HTML")返回的创建成功的新元素新增子元素:元素.append(obj) 在匹配元素的里面新增一个子元素 追加方式 新元素作为最后一个 ...