(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. MySql基础笔记(三)其他重要的事情

    其他重要的事情 一)索引管理优化 1.把多条alter语句整合为一条 2.去除重复的索引 1)当一个索引的最左边部分包含到其他索引中时,被认定为重复索引 create table user( id i ...

  2. [CF1038D]Slime

    [CF1038D]Slime 题目大意: 有\(n(n\le5\times10^5)\)只史莱姆,每只史莱姆有一个分数\(w_i(|w_i|le10^9)\),每次一只史莱姆可以吞掉左边的或者右边的史 ...

  3. win7生成ssh key配置到gitlab

    测试服务上使用ip访问gitlab,比如http://192.168.0.2/,创建用户并登陆后创建一个项目,比如git@gitlab.demo.com:demo/helloworld.git 如果想 ...

  4. 无脑博士的试管们--dfs搜素

    无脑博士有三个容量分别是A,B,C升的试管,A,B,C分别是三个从1到20的整数,最初,A和B试管都是空的,而C试管是装满硫酸铜溶液的.有时,无脑博士把硫酸铜溶液从一个试管倒到另一个试管中,直到被灌试 ...

  5. oracle报错ORA-01653 dba_free_space中没有该表空间

    新建了一个表空间t101,在dba_tablespaces和dba_data_files都出现了,在dba_free_space却没有,这个很有可能是表空间满了. 插入数据会报错:ORA-01653: ...

  6. Atcoder4105 Same Integers(模拟)

    https://abc093.contest.atcoder.jp/tasks/arc094_a?lang=en 思路题还是不太会做哈.感觉数据不大,一开始dfs做但是发现不是最优解,一想确实是这么一 ...

  7. pygame 笔记-4 代码封装&发射子弹

    继续之前的内容,随着游戏的内容越来越复杂,有必要把代码优化一下,可以参考OOP的做法,把人物类抽象出来,弄成一个单独的类,这们便于代码维护,同时我们给小人儿,加个发射子弹的功能,代码如下:(看上去略长 ...

  8. Amazon Publisher Studio让产品推广更简单

    Amazon联盟最近推出了Publisher Studio新功能,只要在Amazon联盟网站后台添加一段特定的代码,以后推广所有Amazon产品的时候就不需要再访问Amazon Associates网 ...

  9. 如何在MyBatis中优雅的使用枚举

    问题 在编码过程中,经常会遇到用某个数值来表示某种状态.类型或者阶段的情况,比如有这样一个枚举:   public enum ComputerState { OPEN(10), //开启 CLOSE( ...

  10. fastjson序列化乱序问题

    1.初始化为有序json对象 JSONObject jsonOrdered= new JSONObject(true); 2.将String对象转换过程中,不要调整顺序 JSONObject json ...