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. CombineStream 与 Multipart Form

    最近开始研究http 特别是multipart 表单,想弄明白他是怎么work 的.在nodejs 里,可以使用form-data 来组合一个multipart 表单,然后使用http.request ...

  2. 主动模式FTP与被动模式FTP该如何选择

    主动模式FTP与被动模式FTP该如何选择  无论是主动模式还是被动模式,其要进行文件传输都必须依次建立两个连接,分别为命令连接与数据连结.而主动模式与被动模式的差异主要体现在数据连结通道上.为了说明两 ...

  3. 13.linux中断处理程序

    linux中断处理程序 一.中断处理流程 在linux内核代码中进入entry-armv.S目录: linux统一的入口:__irq svc. 进入了统一的入口之后,程序跳到irq_handler标号 ...

  4. 在Jenkins中获取GitHub对应Repository的Resource Code

    1):Install Jenkins 请看如下链接: https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins 2):Install ...

  5. list点击项高亮其他默认

    // 点击项颜色高亮,其他默认 if (position != lastPosition && onClickItemView != null) { TabMenu lastTabMe ...

  6. 浏览器-05 HTML和CSS解析1

    一个浏览器内核几个主要部分,HTML/CSS解析器,网络处理,JavaScript引擎,2D/3D图形引擎,多媒体支持等; HTML 解析和 DOM 网页基本结构 一个网页(Page),每个Page都 ...

  7. RUDP之一 —— UDP VS TCP

    原文链接 原文:http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/ 介绍 大家好,我是Glenn Fiedler, ...

  8. BZOJ4643 : 卡常大水题

    将边按权值$A$从小到大排序,从小到大枚举$\max(A)$,然后双指针从大到小枚举$\max(B)$. 按权值$B$用大根堆维护所有已经加入的边,每次$\max(B)$减少时,不断取出权值$B$最大 ...

  9. Spring+SpringMvc+Mybatis整合注意事项

    1.web.xml代码如下 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi ...

  10. innerHTML 与 innerText 的区别

    innerHTML指的是从对象的起始位置到终止位置的全部内容,包括Html标签.innerText 指的是从起始位置到终止位置的内容,但它去除Html标签.同时,innerHTML 是所有浏览器都支持 ...