(1)Euclidean分割

欧几里德分割法是最简单的。检查两点之间的距离。如果小于阈值,则两者被认为属于同一簇。它的工作原理就像一个洪水填充算法:在点云中的一个点被“标记”则表示为选择在一个的集群中。然后,它像病毒一样扩散到其他足够近的点,从这些点到更多点,直到没有新的添加为止。这样,就是一个初始化的新的群集,并且该过程将以剩余的无标记点再次进行。

在PCL中,Euclidean分割法如下:

#include <pcl/io/pcd_io.h>
#include <pcl/segmentation/extract_clusters.h> #include <iostream> int
main(int argc, char** argv)
{
// 申明存储点云的对象.
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 读取一个PCD文件
if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[], *cloud) != )
{
return -;
} // 建立kd-tree对象用来搜索 .
pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>);
kdtree->setInputCloud(cloud); // Euclidean 聚类对象.
pcl::EuclideanClusterExtraction<pcl::PointXYZ> clustering;
// 设置聚类的最小值 2cm (small values may cause objects to be divided
// in several clusters, whereas big values may join objects in a same cluster).
clustering.setClusterTolerance(0.02);
// 设置聚类的小点数和最大点云数
clustering.setMinClusterSize();
clustering.setMaxClusterSize();
clustering.setSearchMethod(kdtree);
clustering.setInputCloud(cloud);
std::vector<pcl::PointIndices> clusters;
clustering.extract(clusters); // For every cluster...
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++;
}
}

那么 比如我要分割一张点云文件可视化如下

那么可以看到结果

很明显每一个英文字幕都会被提取出来,比如我们显示其中的一个聚类

当然我们把点云中的所有聚类生成了一个个的单独文件,那么有人在我的微信公众号后台提问,如何把所有的聚类的结果,在一个可视化窗口中显示呢?所以该如何解决,个人理解就是虽然聚类的结果分解出来了,但是,每一个聚类对象相对与原来点云的坐标以及性质都没有改变所以我们直接就把聚类的结果相加就可以实现了,那么我们只需要在结尾的地方添加如下几行代码

  *add_cloud+=*cloud_cluster;
pcl::io::savePCDFileASCII("add_cloud.pcd",*add_cloud);

当然前面要声明add_cloud的数据格式,所以我们就看一下显示的试验结果。我们用table_scene_lms400.pcd文件来查看结果

原始PCD文件可视化的结果

那么我们只想看除去两个平面的其他聚类,所以我们只需要添加两行代码即可,可视化的结果如下

(2)Conditional Euclidean分割

条件欧几里德分割的工作方式与(1)所示的标准的欧几里德分割方法基本一样,条件分割除了要距离检查,点还需要满足一个特殊的,可以自定义的要求的限制,这样它们被添加到一个集群。此条件是用户指定的。它归结为如下:对于每一对点(第一个点,作为种子点,第二个点,作为候选点,是一个临近点的选择与计算比较等操作)将会有自定义函数。此函数具有一定的特性:这两个点具有副本,以便我们可以执行我们自己的选择计算的平方距离
函数并返回布尔值。如果值为true,则可以将候选添加到群集。如果假,它不会被添加,即使它通过距离检查。

#include <pcl/io/pcd_io.h>
#include <pcl/segmentation/conditional_euclidean_clustering.h> #include <iostream> // 如果这个函数返回的是真,这这个候选点将会被加入聚类中
bool
customCondition(const pcl::PointXYZ& seedPoint, const pcl::PointXYZ& candidatePoint, float squaredDistance)
{
// Do whatever you want here.做你想做的条件的筛选
if (candidatePoint.y < seedPoint.y) //如果候选点的Y的值小于种子点的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)
{
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点云分割(3)的更多相关文章

  1. PCL点云分割(1)

    点云分割是根据空间,几何和纹理等特征对点云进行划分,使得同一划分内的点云拥有相似的特征,点云的有效分割往往是许多应用的前提,例如逆向工作,CAD领域对零件的不同扫描表面进行分割,然后才能更好的进行空洞 ...

  2. PCL—点云分割(基于凹凸性) 低层次点云处理

    博客转载自:http://www.cnblogs.com/ironstark/p/5027269.html 1.图像分割的两条思路 场景分割时机器视觉中的重要任务,尤其对家庭机器人而言,优秀的场景分割 ...

  3. PCL—点云分割(基于形态学) 低层次点云处理

    博客转载自:http://www.cnblogs.com/ironstark/p/5017428.html 1.航空测量与点云的形态学 航空测量是对地形地貌进行测量的一种高效手段.生成地形三维形貌一直 ...

  4. PCL—点云分割(超体聚类) 低层次点云处理

    博客转载自:http://www.cnblogs.com/ironstark/p/5013968.html 1.超体聚类——一种来自图像的分割方法 超体(supervoxel)是一种集合,集合的元素是 ...

  5. PCL—点云分割(最小割算法) 低层次点云处理

    1.点云分割的精度 在之前的两个章节里介绍了基于采样一致的点云分割和基于临近搜索的点云分割算法.基于采样一致的点云分割算法显然是意识流的,它只能割出大概的点云(可能是杯子的一部分,但杯把儿肯定没分割出 ...

  6. PCL—点云分割(RanSaC)低层次点云处理

    博客转载自:http://blog.csdn.net/app_12062011/article/details/78131318 点云分割 点云分割可谓点云处理的精髓,也是三维图像相对二维图像最大优势 ...

  7. PCL点云分割(2)

    关于点云的分割算是我想做的机械臂抓取中十分重要的俄一部分,所以首先学习如果使用点云库处理我用kinect获取的点云的数据,本例程也是我自己慢慢修改程序并结合官方API 的解说实现的,其中有很多细节如果 ...

  8. PCL—点云分割(邻近信息) 低层次点云处理

    博客转载自:http://www.cnblogs.com/ironstark/p/5000147.html 分割给人最直观的影响大概就是邻居和我不一样.比如某条界线这边是中华文明,界线那边是西方文,最 ...

  9. PCL—低层次视觉—点云分割(基于凹凸性)

    1.图像分割的两条思路 场景分割时机器视觉中的重要任务,尤其对家庭机器人而言,优秀的场景分割算法是实现复杂功能的基础.但是大家搞了几十年也还没搞定——不是我说的,是接下来要介绍的这篇论文说的.图像分割 ...

随机推荐

  1. 2017-9-8-visio制作lcd液晶背景

    看到别人的帖子有用visio做tft的背景图片的,十分感兴趣,电脑上也有visio,搞起.. 按照下图找到合适的模板(visio2010版本,其他版本应该会略有不同).​ 拖动界面左侧的各种丰富的小插 ...

  2. 流畅的Python读书笔记(二)

    2.1 可变序列与不可变序列 可变序列 list. bytearray. array.array. collections.deque 和 memoryview. 不可变序列 tuple. str 和 ...

  3. node cluster模块,仿多线程并发调用,

    worker.js var cluster = require('cluster')function fibo(n) { return n == 0 ? 0 : n > 1 ? fibo(n - ...

  4. ACM/IOI 历年国家集训队论文集和论文算法分类整理

    国家集训队1999论文集 陈宏:<数据结构的选择与算法效率--从IOI98试题PICTURE谈起> 来煜坤:<把握本质,灵活运用--动态规划的深入探讨> 齐鑫:<搜索方法 ...

  5. day7接口开发

    一.数据库操作, 1.创建游标时指定游标类型为字典,返回值类型为字典,方便取值 cur = coon.cursor(cursor=pymysql.cursor.Dictursor) 2.获取执行查询S ...

  6. Kafka Streams简介: 让流处理变得更简单

    Introducing Kafka Streams: Stream Processing Made Simple 这是Jay Kreps在三月写的一篇文章,用来介绍Kafka Streams.当时Ka ...

  7. HDU 4786 Fibonacci Tree 最小生成树

    Fibonacci Tree 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4786 Description Coach Pang is intere ...

  8. vue中的v-cloak

    问题 在使用vue时,HTML 绑定 Vue实例,在页面加载时会闪烁类似{{msg}}这样的信息.可能会导致用户体验不好. 使用v-cloak v-cloak就能解决这个问题. (1)用法 这个指令保 ...

  9. vim设置一个tab为4个空格,设置行号

    这我就再当前用户下,不是root权限.本身是没有.vimrc这个文件的 vim  ~/.vimrc 新建了这个文件 然后在其中输入 保存. 这样设置完就一个tab是4个空格,并且就有行号了.重新打开v ...

  10. Vue(九)小案例 - 百度搜索列表(跨域)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...