(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. 01背包-dp

    一 问题分析 二 代码实现 package Dp_0_1_bag; import java.io.BufferedWriter; import java.io.FileWriter; import j ...

  2. mongoose查询

    Model.findOne({ age:5},function(err, doc){// doc 是单个文档}); 与 findOne 相同,但它接收文档的 _id 作为参数,返回单个文档._id 可 ...

  3. 【OpenCV】访问Mat中的每个像素值

    其中注意i,j的位置,写错了好几次.第二个for循环中的if语句用异或来判断图像中哪些像素点发生了改变.

  4. PHP判断iPhone、iPad、Android、PC设备的方法

    因为工作需要我们需要知道是什么样了用户访问了我网站了,现在的移动设备种类多了,下面我们一起来看小编整理的一段php判断iPhone.iPad.Android.PC设备的例子. 注意:本代码的PC系统为 ...

  5. .net异常机制

    异常机制简介 当CPU运行到一些非法的指令,例如除零错误,访问内存页失败等指令,CPU会生成一个硬件异常,不同的异常有固定的异常代码作为标识符,异常产生以后CPU暂时不能继续执行后续的指令—因为后续的 ...

  6. array中key所对应的value

    获取数组中的键对应的值 class Test{ public function index(){ $info = array( 'name' => 'daicr', 'age' => 24 ...

  7. R语言语法基础二

    R语言语法基础二 重塑数据 增加行和列 # 创建向量 city = c("Tampa","Seattle","Hartford"," ...

  8. vue使用babel+sass出错解决

    按照官网的步骤先将vue项目建立好,这时如果使用lang="babel",lang="scss"会报错. 这时终端进入项目文件夹下输入以下命令: npm ins ...

  9. MUI学习02-顶部导航栏

    建议:先看一下MUI注意事项 连接:http://ask.dcloud.net.cn/article/122 固定栏靠前 所谓的固定栏,也就是带有.mui-bar属性的节点,都是基于fixed定位的元 ...

  10. 1.3 java8新特性总结

    java8中重要的4个新特性: Lambda Stream Optional 日期时间API 接口方法(default和static方法,jdk9可定义private方法) 一.Lambda impo ...