(2)关于上一篇博文中提到的欧几里德分割法称之为标准的距离分离,当然接下来介绍其他的与之相关的延伸出来的聚类的方法,我称之为条件欧几里德聚类法,(是我的个人理解),这个条件的设置是可以由我们自定义的,因为除了距离检查,聚类的点还需要满足一个特殊的自定义的要求,就是以第一个点为标准作为种子点,候选其周边的点作为它的对比或者比较的对象,如果满足条件就加入到聚类的对象中,至于到底怎么翻译我也蒙了,只能这样理解了

主要的缺点:该算法没有初始化种子系统,没有过度分割或者分割不足的控制,还有就是从主循环运算中调用条件函数时,效率比较低,

看一下代码吧,至于到底怎么理解各个有个人的理解吧

#include <pcl/io/pcd_io.h>
#include <pcl/segmentation/conditional_euclidean_clustering.h> #include <iostream> //如果此函数返回true,则将添加候选点到种子点的簇类中。
bool
customCondition(const pcl::PointXYZ& seedPoint, const pcl::PointXYZ& candidatePoint, float squaredDistance)
{
// 在这里你可以添加你自定义的条件
if (candidatePoint.y < seedPoint.y)
return false; return true;
} int
main(int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[], *cloud) != )
{
return -;
} // 申明一个条件聚类的对象
pcl::ConditionalEuclideanClustering<pcl::PointXYZ> clustering;
clustering.setClusterTolerance(0.02);
clustering.setMinClusterSize();
clustering.setMaxClusterSize();
clustering.setInputCloud(cloud);
// 设置要检查每对点的函数。
clustering.setConditionFunction(&customCondition);
std::vector<pcl::PointIndices> clusters;
clustering.segment(clusters); // 对于每一个聚类结果
int currentClusterNum = ;
for (std::vector<pcl::PointIndices>::const_iterator i = clusters.begin(); i != clusters.end(); ++i)
{
// ...add all its points to a new cloud...
pcl::PointCloud<pcl::PointXYZ>::Ptr cluster(new pcl::PointCloud<pcl::PointXYZ>);
for (std::vector<int>::const_iterator point = i->indices.begin(); point != i->indices.end(); point++)
cluster->points.push_back(cloud->points[*point]);
cluster->width = cluster->points.size();
cluster->height = ;
cluster->is_dense = true; // ...and save it to disk.
if (cluster->points.size() <= )
break;
std::cout << "Cluster " << currentClusterNum << " has " << cluster->points.size() << " points." << std::endl;
std::string fileName = "cluster" + boost::to_string(currentClusterNum) + ".pcd";
pcl::io::savePCDFileASCII(fileName, *cluster); currentClusterNum++;
}
}

上面执行的条件是检查候选点的Y坐标是否小于种子的Y坐标,没有什么实际意义。所以我就再查看结果了。

那么同时我暂时也用不到,如果有想法的时候再回来研究吧

(2)最小分割算法

该算法是将一幅点云图像分割为两部分:前景点云(目标物体)和背景物体(剩余部分)

关于该算法的论文的地址:http://gfx.cs.princeton.edu/pubs/Golovinskiy_2009_MBS/paper_small.pdf

The Min-Cut (minimum cut) algorithm最小割算法是图论中的一个概念,其作用是以某种方式,将两个点分开,当然这两个点中间可能是通过无数的点再相连的。如图

如果要分开最左边的点和最右边的点,红绿两种割法都是可行的,但是红线跨过了三条线,绿线只跨过了两条。单从跨线数量上来论可以得出绿线这种切割方法更优 的结论。但假设线上有不同的权值,那么最优切割则和权值有关了。当你给出了点之间的 “图” ,以及连线的权值时,最小割算法就能按照要求把图分开。

所以那么怎么来理解点云的图呢?

显而易见,切割有两个非常重要的因素,第一个是获得点与点之间的拓扑关系,这种拓扑关系就是生成一张 “图”。第二个是给图中的连线赋予合适的权值。只要这两个要素合适,最小割算法就会正确的分割出想要的结果。点云是分开的点。只要把点云中所有的点连起来就可以了。连接算法如下:

  1. 找到每个点临近的n个点
  2. 将这n个点和父点连接
  3. 找到距离最小的两个块(A块中某点与B块中某点距离最小),并连接
  4. 重复3,直至只剩一个块

经过上面的步骤现在已经有了点云的“图”,只要给图附上合适的权值,就满足了最小分割的前提条件。物体分割比如图像分割给人一个直观印象就是属于该物体的点,应该相互之间不会太远。也就是说,可以用点与点之间的欧式距离来构造权值。所有线的权值可映射为线长的函数。

我们知道这种分割是需要指定对象的,也就是我们指定聚类的中心点(center)以及聚类的半径(radius),当然我们指定了中心点和聚类的半径,那么就要被保护起来,保护的方法就是增加它的权值

接下来我们就来看看代码

#include <pcl/io/pcd_io.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d.h>
#include <pcl/segmentation/region_growing.h>
#include <pcl/segmentation/min_cut_segmentation.h>
#include <iostream>
#include <pcl/segmentation/region_growing_rgb.h> int
main(int argc, char** argv)
{
//申明点云的类型
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 法线
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[], *cloud) != )
{
return -;
}
// 申明一个Min-cut的聚类对象
pcl::MinCutSegmentation<pcl::PointXYZ> clustering;
clustering.setInputCloud(cloud); //设置输入
//创建一个点云,列出所知道的所有属于对象的点
// (前景点)在这里设置聚类对象的中心点(想想是不是可以可以使用鼠标直接选择聚类中心点的方法呢?)
pcl::PointCloud<pcl::PointXYZ>::Ptr foregroundPoints(new pcl::PointCloud<pcl::PointXYZ>());
pcl::PointXYZ point;
point.x = 100.0;
point.y = 100.0;
point.z = 100.0;
foregroundPoints->points.push_back(point);
clustering.setForegroundPoints(foregroundPoints); //设置聚类对象的前景点 //设置sigma,它影响计算平滑度的成本。它的设置取决于点云之间的间隔(分辨率)
clustering.setSigma(0.02);
// 设置聚类对象的半径.
clustering.setRadius(0.01); //设置需要搜索的临近点的个数,增加这个也就是要增加边界处图的个数
clustering.setNumberOfNeighbours(); //设置前景点的权重(也就是排除在聚类对象中的点,它是点云之间线的权重,)
clustering.setSourceWeight(0.6); std::vector <pcl::PointIndices> clusters;
clustering.extract(clusters); std::cout << "Maximum flow is " << clustering.getMaxFlow() << "." << std::endl; int currentClusterNum = ;
for (std::vector<pcl::PointIndices>::const_iterator i = clusters.begin(); i != clusters.end(); ++i)
{
//设置聚类后点云的属性
pcl::PointCloud<pcl::PointXYZ>::Ptr cluster(new pcl::PointCloud<pcl::PointXYZ>);
for (std::vector<int>::const_iterator point = i->indices.begin(); point != i->indices.end(); point++)
cluster->points.push_back(cloud->points[*point]);
cluster->width = cluster->points.size();
cluster->height = ;
cluster->is_dense = true; //保存聚类的结果
if (cluster->points.size() <= )
break;
std::cout << "Cluster " << currentClusterNum << " has " << cluster->points.size() << " points." << std::endl;
std::string fileName = "cluster" + boost::to_string(currentClusterNum) + ".pcd";
pcl::io::savePCDFileASCII(fileName, *cluster); currentClusterNum++;
}
}

看一下实际运行的最小分割法的结果

原始的点云

最小分割法的结果

对于实际应用中我们应该设置正确的参数这是最为关键的!

PCL中分割方法的介绍(2)的更多相关文章

  1. PCL中分割方法的介绍(3)

    (3)上两篇介绍了关于欧几里德分割,条件分割,最小分割法等等还有之前就有用RANSAC法的分割方法,这一篇是关于区域生成的分割法, 区 域生长的基本 思想是: 将具有相似性的像素集合起来构成区域.首先 ...

  2. 使用Memcache在PHP中调试方法的介绍及应用

    使用Memcache在PHP中调试方法的介绍及应用 如果我们在网络开发中,特别是大访问量的web项目开发中,为了提高响应速度,减少数据查询运算,那么我们都会选用memcahce.首先我们必须要安装,接 ...

  3. PCL中分割_欧式分割(1)

    基于欧式距离的分割和基于区域生长的分割本质上都是用区分邻里关系远近来完成的.由于点云数据提供了更高维度的数据,故有很多信息可以提取获得.欧几里得算法使用邻居之间距离作为判定标准,而区域生长算法则利用了 ...

  4. 基于传统方法点云分割以及PCL中分割模块

      之前在微信公众号中更新了以下几个章节 1,如何学习PCL以及一些基础的知识 2,PCL中IO口以及common模块的介绍 3,PCL中常用的两种数据结构KDtree以及Octree树的介绍    ...

  5. js中propertyIsEnumerable()方法使用介绍

    javascript的propertyIsEnumerable()方法使用介绍 概述 propertyIsEnumerable()用来检测属性是否属于某个对象的,如果检测到了,返回true,否则fal ...

  6. Swift - AppDelegate.swift类中默认方法的介绍

    项目创建后,AppDelegate类中默认带有如下几个方法,具体功能如下: 1,应用程序第一次运行时执行 这个方法只有在App第一次运行的时候被执行过一次,每次App从后台激活时都不会再执行该方法. ...

  7. Thread中join()方法进行介绍

    http://www.cnblogs.com/skywang12345/p/3479275.html https://blog.csdn.net/dabing69221/article/details ...

  8. Swift编程语言中的方法引用

    由于Apple官方的<The Swift Programming Guide>对Swift编程语言中的方法引用介绍得不多,所以这里将更深入.详细地介绍Swift中的方法引用. Swift与 ...

  9. String类中intern方法的原理分析

    一,前言 ​ 昨天简单整理了JVM内存分配和String类常用方法,遇到了String中的intern()方法.本来想一并总结起来,但是intern方法还涉及到JDK版本的问题,内容也相对较多,所以今 ...

随机推荐

  1. jQuery学习笔记(Ajax)

    jQuery对Ajax操作进行了封装,在jQuery中$.ajax方法属于最底层的方法,第2层是$.load().$.get().$.post()方法,第3层是$.getScript()和$.getJ ...

  2. Atitit 如何设置与安放知识的trap陷阱  知识聚合 rss url聚合工具 以及与trap的对比

    Atitit 如何设置与安放知识的trap陷阱  知识聚合 rss url聚合工具 以及与trap的对比 1.1. 安放地点 垂直知识网站csdn cnblogs等特定频道栏目,大牛博客 1 1.2. ...

  3. IOS 学习 Key-value coding

    1 前言 本节我们主要介绍键值编码,以及如何使一个类符合KVC编码. 2 详述 键-值编码是一个对于间接访问一个对象属性和关系使用字符标识的机制.它支持或者关系几个特别的Cocoa编程机制和技术,在C ...

  4. Xilinx FPGA用户约束文件(转自xilinx ISE 开发指南

    FPGA设计中的约束文件有3类:用户设计文件(.UCF文件).网表约束文件(.NCF文件)以及物理约束文件(.PCF文件),可以完成时序约束.管 脚约束以及区域约束.3类约束文件的关系为:用户在设计输 ...

  5. 【Unity】4.7 摄像机

    分类:Unity.C#.VS2015 创建日期:2016-04-11 一.简介 摄像机(Camera)是为玩家捕捉并展示世界的一种设备.场景中至少需要有一台摄像机,也可以在一个场景中使用多台摄像机.这 ...

  6. html5中audio的详细使用

    html5的audio功能上已经非常强大,回放,跳转,缓冲等以前只能用flash才能实现的功能,html5的audio都能轻松搞定 最近的一个项目使用到了这个功能,把我使用的情况写下来,供大家参考, ...

  7. Apache Flink Training and sample code

    http://training.data-artisans.com/ https://github.com/dataArtisans/blog-post-code-samples https://gi ...

  8. bulk insert 在mssql中使用

    从远程数据文件中批量导入 若要使用 BULK INSERT 从其他计算机中大容量导入数据,必须在两台计算机之间共享数据文件. 指定共享数据文件时,请使用它的通用命名约定 (UNC) 名称,其一般形式为 ...

  9. iOS应用管理(字典转模型)

    1. 新建appViewModel 1.1声明需要的属性 //NSString一般用copy来修饰 @property(nonatomic,copy)NSString *name; @property ...

  10. Centos crontab定时任务

    CRONTAB是一个用于设置周期性被执行的任务的工具,有了它,我们就可以从定时工作中解放出来. 一 : 检查CRONTAB服务 1. 检查CRONTAB工具是否已经在主机上安装 : crontab - ...