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. MyBatis - MyBatis Generator 生成的example 如何使用 and or 简单混合查询

    简单介绍: Criteria,包含一个Cretiron的集合,每一个Criteria对象内包含的Cretiron之间是由AND连接的,是逻辑与的关系. oredCriteria,Example内有一个 ...

  2. 【BZOJ3036】绿豆蛙的归宿 拓补排序+概率

    [BZOJ3036]绿豆蛙的归宿 Description 随着新版百度空间的下线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿. 给出一个有向无环的连通图,起点为1终点为N,每条边都有一个长度. ...

  3. pip安装模块

    需要到pip目录下执行 pip install 模块名 pip 也需要配置环境变量,电脑是windows

  4. Json.Net的简单使用

    1.添加程序集 Newtonsoft.Json.dll 2.创建模型 public class Person {   public string Name { get; set; }   public ...

  5. 不注册Activex 直接调用它

    此处的Activex是ATL方式的. [ComVisible(false)]    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnk ...

  6. *HDU 1068 二分图

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  7. HTML基础篇之图像热区补充一下图片相对地址的定义

    HTML5课堂笔记理解2 上次说到图片相对地址的定义,举例了4中情形的下的不同目录的图片书写方法补充一个如果你要的图片目录跟上面四种都不一样话可以用以下属性值尝试 ./            当前目录 ...

  8. C fgetc

    格式:int fgetc(FILE *stream); 这个函数的返回值,是返回所读取的一个字节.如果读到文件末尾或者读取出错时返回EOF. 位于stdio.h中.从流中读取字符,即从stream所指 ...

  9. Java关键字介绍

    关键字 描述 abstract 抽象方法,抽象类的修饰符 assert 断言条件是否满足 boolean 布尔数据类型 break 跳出循环或者label代码段 byte 8-bit 有符号数据类型 ...

  10. 代码中,使用__DATE__宏,获取程序编译时间,如何保证每次编译代码(非重新生成方式),都能更新__DATE__的值?

    代码中,使用__DATE__宏,获取程序编译时间,如何保证每次编译代码(非重新生成方式),都能更新__DATE__的值? 解决:通过vs的预先生成命令中,添加批处理命令,删除对应的obj文件方式,强制 ...