[PCL]点云渐进形态学滤波

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

在#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
 13   tree.setInputCloud (cloud_in);
 14   tree.addPointsFromInputCloud ();
 15
 16   float half_res = resolution / 2.0f;
 17
 18   switch (morphological_operator)
 19   {
 20     case MORPH_DILATE:
 21     case MORPH_ERODE:
 22     {
 23       for (size_t p_idx = 0; p_idx < cloud_in->points.size (); ++p_idx)
 24       {
 25         Eigen::Vector3f bbox_min, bbox_max;
 26         std::vector<int> pt_indices;
 27         float minx = cloud_in->points[p_idx].x - half_res;
 28         float miny = cloud_in->points[p_idx].y - half_res;
 29         float minz = -std::numeric_limits<float>::max ();
 30         float maxx = cloud_in->points[p_idx].x + half_res;
 31         float maxy = cloud_in->points[p_idx].y + half_res;
 32         float maxz = std::numeric_limits<float>::max ();
 33         bbox_min = Eigen::Vector3f (minx, miny, minz);
 34         bbox_max = Eigen::Vector3f (maxx, maxy, maxz);
 35         tree.boxSearch (bbox_min, bbox_max, pt_indices);
 36
 37         if (pt_indices.size () > 0)
 38         {
 39           Eigen::Vector4f min_pt, max_pt;
 40           pcl::getMinMax3D<PointT> (*cloud_in, pt_indices, min_pt, max_pt);
 41
 42           switch (morphological_operator)
 43           {
 44             case MORPH_DILATE:
 45             {
 46               cloud_out.points[p_idx].z = max_pt.z ();
 47               break;
 48             }
 49             case MORPH_ERODE:
 50             {
 51               cloud_out.points[p_idx].z = min_pt.z ();
 52               break;
 53             }
 54           }
 55         }
 56       }
 57       break;
 58     }
 59     case MORPH_OPEN:
 60     case MORPH_CLOSE:
 61     {
 62       pcl::PointCloud<PointT> cloud_temp;
 63
 64       pcl::copyPointCloud<PointT, PointT> (*cloud_in, cloud_temp);
 65
 66       for (size_t p_idx = 0; p_idx < cloud_temp.points.size (); ++p_idx)
 67       {
 68         Eigen::Vector3f bbox_min, bbox_max;
 69         std::vector<int> pt_indices;
 70         float minx = cloud_temp.points[p_idx].x - half_res;
 71         float miny = cloud_temp.points[p_idx].y - half_res;
 72         float minz = -std::numeric_limits<float>::max ();
 73         float maxx = cloud_temp.points[p_idx].x + half_res;
 74         float maxy = cloud_temp.points[p_idx].y + half_res;
 75         float maxz = std::numeric_limits<float>::max ();
 76         bbox_min = Eigen::Vector3f (minx, miny, minz);
 77         bbox_max = Eigen::Vector3f (maxx, maxy, maxz);
 78         tree.boxSearch (bbox_min, bbox_max, pt_indices);
 79
 80         if (pt_indices.size () > 0)
 81         {
 82           Eigen::Vector4f min_pt, max_pt;
 83           pcl::getMinMax3D<PointT> (cloud_temp, pt_indices, min_pt, max_pt);
 84
 85           switch (morphological_operator)
 86           {
 87             case MORPH_OPEN:
 88             {
 89               cloud_out.points[p_idx].z = min_pt.z ();
 90               break;
 91             }
 92             case MORPH_CLOSE:
 93             {
 94               cloud_out.points[p_idx].z = max_pt.z ();
 95               break;
 96             }
 97           }
 98         }
 99       }
100
101       cloud_temp.swap (cloud_out);
102
103       for (size_t p_idx = 0; p_idx < cloud_temp.points.size (); ++p_idx)
104       {
105         Eigen::Vector3f bbox_min, bbox_max;
106         std::vector<int> pt_indices;
107         float minx = cloud_temp.points[p_idx].x - half_res;
108         float miny = cloud_temp.points[p_idx].y - half_res;
109         float minz = -std::numeric_limits<float>::max ();
110         float maxx = cloud_temp.points[p_idx].x + half_res;
111         float maxy = cloud_temp.points[p_idx].y + half_res;
112         float maxz = std::numeric_limits<float>::max ();
113         bbox_min = Eigen::Vector3f (minx, miny, minz);
114         bbox_max = Eigen::Vector3f (maxx, maxy, maxz);
115         tree.boxSearch (bbox_min, bbox_max, pt_indices);
116
117         if (pt_indices.size () > 0)
118         {
119           Eigen::Vector4f min_pt, max_pt;
120           pcl::getMinMax3D<PointT> (cloud_temp, pt_indices, min_pt, max_pt);
121
122           switch (morphological_operator)
123           {
124             case MORPH_OPEN:
125             default:
126             {
127               cloud_out.points[p_idx].z = max_pt.z ();
128               break;
129             }
130             case MORPH_CLOSE:
131             {
132               cloud_out.points[p_idx].z = min_pt.z ();
133               break;
134             }
135           }
136         }
137       }
138       break;
139     }
140     default:
141     {
142       PCL_ERROR ("Morphological operator is not supported!\n");
143       break;
144     }
145   }
146
147   return;
148 }

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

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 = 0;
  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+1) * base_ + 1.0f);

    // Calculate the height threshold to be used in the next iteration.
    if (iteration == 0)
      height_threshold = initial_distance_;
    else
      height_threshold = slope_ * (window_size - window_sizes[iteration-1]) * 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 = 0; 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 = 0; 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 ();
}
时间: 2024-10-13 01:46:27

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

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

(1) 关于pcl::PCLPointCloud2::Ptr和pcl::PointCloud<pcl::PointXYZ>两中数据结构的区别 pcl::PointXYZ::PointXYZ ( float_x, float_y, float_z ) 区别: struct PCLPointCloud2 { PCLPointCloud2 () : header (), height (0), width (0), fields (), is_bigendian (false), point_ste

【计算机视觉】形态学滤波

[计算机视觉]形态学滤波 标签(空格分隔): [图像处理] [信号处理] 版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/lg1259156776/. 说明:本文主要想弄清楚形态学滤波在图象处理和信号处理中的应用,图像处理中非常直观的通过腐蚀膨胀获得开闭运算的效果,而在数据实时滤波中,形态学滤波也是可以使用的. 形态学滤波基本知识 原理:在特殊领域运算形式--结构元素(Sturcture Element),在每个像素位置上与二值图像对应的区域进行特定的逻辑运

形态学滤波:(1)腐蚀与膨胀 (2)开运算,闭运算,形态学梯度,顶帽,黑帽

一.形态学概述 图像处理中的形态学一般指的是数学形态学. 数学形态学是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论.其基本运算包括:二值腐蚀和膨胀,二值开闭运算,骨架抽取,极限腐蚀,击中击不中变换,形态学梯度,top-hat变换,颗粒分析,流域变换,灰值腐蚀和膨胀,灰值开闭运算,灰值形态学梯度等. 简单来讲,形态学操作就是基于形状的一系列图像处理操作. 二.形态学滤波 (1)腐蚀与膨胀 膨胀和腐蚀能实现多种多样的功能,主要如下: 消除噪声: 分割(isolate)

《VS2010(X64)&amp;PCL点云库学习》Part 2 A simple test of PCL in MFC

<VS2010(X64)&PCL点云库学习>Part 2 A simple test of PCL in MFC                                                                             本文主要介绍如何将PCL的控制台程序移植到MFC中,基本内容还是按照上一篇PCL配置博文来继续讲解的. 1.新建MFC程序 2.应用程序类型对话框中,勾选基于对话框,一直下一步,或者直接点击完成. 3.配置环境:主要包括添加

Windows下安装PCL点云库

原文链接:http://blog.csdn.net/u012337034/article/details/38270109 简介: 在Windows下安装PCL点云库的方法大概有两种:其一,all-in-one-installer,这个只有两个版本1.5.1和1.6.0,而且顾名思义,安装方法极其简单,这里就不多做介绍了:其二,build PCL out of source,这里我们可以使用PCL的各种版本,而且随着PCL的更新,我们也可以不断的update.接下来我将会详细介绍如何独立安装PC

PCL—点云分割(最小割算法)

1.点云分割的精度 在之前的两个章节里介绍了基于采样一致的点云分割和基于临近搜索的点云分割算法.基于采样一致的点云分割算法显然是意识流的,它只能割出大概的点云(可能是杯子的一部分,但杯把儿肯定没分割出来).基于欧式算法的点云分割面对有牵连的点云就无力了(比如风筝和人,在不用三维形态学去掉中间的线之前,是无法分割风筝和人的).基于法线等信息的区域生长算法则对平面更有效,没法靠它来分割桌上的碗和杯子.也就是说,上述算法更关注能不能分割,除此之外,我们还需要一个方法来解决分割的"好不好"这个

[PCL](1)PCL点云库安装

1.安装文件下载:官网,我还是比较喜欢别人编译好的安装包啊,哈哈. http://www.pointclouds.org/downloads/windows.html 2.傻瓜式安装(下面的依赖项都集成进来了) 写入环境变量,这个很不错,可选. 中间安装了Boost.VTK.Kinect驱动什么的.反正是一路下一步,当然我的机器是Win7系统,之前没有安装过PCL,比较纯净. 之后又单独安装了QT4.8.2的sdk. 3.测试 在安装目录下有share/doc/pcl-1.6/tutorials

python数字图像处理(13):基本形态学滤波

对图像进行形态学变换.变换对象一般为灰度图或二值图,功能函数放在morphology子模块内. 1.膨胀(dilation) 原理:一般对二值图像进行操作.找到像素值为1的点,将它的邻近像素点都设置成这个值.1值表示白,0值表示黑,因此膨胀操作可以扩大白色值范围,压缩黑色值范围.一般用来扩充边缘或填充小的孔洞. 功能函数:skimage.morphology.dilation(image, selem=None) selem表示结构元素,用于设定局部区域的形状和大小. from skimage

PCL点云库中怎样读取指定的PCD文件,又一次命名,处理后保存到指定目录

我一直想把处理后的pcd文件重命名,然后放到指定的目录,尝试了好久最终做到了: 比方我想读取  "table_scene_lms400.pcd" 把它进行滤波处理,重命名为 "table_scene_lms400_filter.pcd" ,然后保存到  "C:\PCD_FILTER\"文件夹下. 基本的语句例如以下: <span style="font-family:Microsoft YaHei;font-size:14px;&