EuclideanClusterExtraction这个名字起的很奇怪,欧式距离聚类这个该如何理解?欧式距离只是一种距离测度的方法呀!有了一个Cluster在里面,我以为是某一种聚类算法,层次聚类?k-NN聚类?K-Means?还是模糊聚类?感觉很奇怪,看下代码吧。

找一个实例cluster_extraction.cpp的main入口函数。

找到computer函数,该方法中定义了一个pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;对象,接着就是参数赋值。

具体的算法执行在ec.extract (cluster_indices)中。因此进入EuclideanClusterExtraction查看具体的方法。

 void compute (const pcl::PCLPointCloud2::ConstPtr &input, std::vector<pcl::PCLPointCloud2::Ptr> &output,
int min, int max, double tolerance)
{
// Convert data to PointCloud<T>
PointCloud<pcl::PointXYZ>::Ptr xyz (new PointCloud<pcl::PointXYZ>);
fromPCLPointCloud2 (*input, *xyz); // Estimate
TicToc tt;
tt.tic (); print_highlight (stderr, "Computing "); // Creating the KdTree object for the search method of the extraction
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud (xyz); std::vector<pcl::PointIndices> cluster_indices;
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
ec.setClusterTolerance (tolerance);
ec.setMinClusterSize (min);
ec.setMaxClusterSize (max);
ec.setSearchMethod (tree);
ec.setInputCloud (xyz);
ec.extract (cluster_indices); print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", cluster_indices.size ()); print_info (" clusters]\n"); output.reserve (cluster_indices.size ());
for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
{
pcl::ExtractIndices<pcl::PCLPointCloud2> extract;
extract.setInputCloud (input);
extract.setIndices (boost::make_shared<const pcl::PointIndices> (*it));
pcl::PCLPointCloud2::Ptr out (new pcl::PCLPointCloud2);
extract.filter (*out);
output.push_back (out);
}
}

可以在pcl_segmentation项目下的extract_clusters.h文件中查看EuclideanClusterExtraction的定义,可知这是一个模板类。

template <typename PointT> class EuclideanClusterExtraction: public PCLBase<PointT>

实现文件在项目下的extract_clusters.hpp中,(还有一个extract_clusters.cpp文件),查看其中的extract方法:

 template <typename PointT> void pcl::EuclideanClusterExtraction<PointT>::extract (std::vector<PointIndices> &clusters)
{
if (!initCompute () ||
(input_ != && input_->points.empty ()) ||
(indices_ != && indices_->empty ()))
{
clusters.clear ();
return;
} // Initialize the spatial locator
if (!tree_)
{
if (input_->isOrganized ())
tree_.reset (new pcl::search::OrganizedNeighbor<PointT> ());
else
tree_.reset (new pcl::search::KdTree<PointT> (false));
} // Send the input dataset to the spatial locator
tree_->setInputCloud (input_, indices_);
extractEuclideanClusters (*input_, *indices_, tree_, static_cast<float> (cluster_tolerance_), clusters, min_pts_per_cluster_, max_pts_per_cluster_);

//tree_->setInputCloud (input_);
//extractEuclideanClusters (*input_, tree_, cluster_tolerance_, clusters, min_pts_per_cluster_, max_pts_per_cluster_); // Sort the clusters based on their size (largest one first)
std::sort (clusters.rbegin (), clusters.rend (), comparePointClusters); deinitCompute ();
}

注意在extract_clusters.h中定义了四个

  template <typename PointT> void
extractEuclideanClusters (
const PointCloud<PointT> &cloud, const boost::shared_ptr<search::Search<PointT> > &tree,
float tolerance, std::vector<PointIndices> &clusters,
unsigned int min_pts_per_cluster = , unsigned int max_pts_per_cluster = (std::numeric_limits<int>::max) ());
 template <typename PointT> void
extractEuclideanClusters (
const PointCloud<PointT> &cloud, const std::vector<int> &indices,
const boost::shared_ptr<search::Search<PointT> > &tree, float tolerance, std::vector<PointIndices> &clusters,
unsigned int min_pts_per_cluster = , unsigned int max_pts_per_cluster = (std::numeric_limits<int>::max) ());
  template <typename PointT, typename Normal> void
extractEuclideanClusters (
const PointCloud<PointT> &cloud, const PointCloud<Normal> &normals,
float tolerance, const boost::shared_ptr<KdTree<PointT> > &tree,
std::vector<PointIndices> &clusters, double eps_angle,
unsigned int min_pts_per_cluster = ,
unsigned int max_pts_per_cluster = (std::numeric_limits<int>::max) ())
  template <typename PointT, typename Normal>
void extractEuclideanClusters (
const PointCloud<PointT> &cloud, const PointCloud<Normal> &normals,
const std::vector<int> &indices, const boost::shared_ptr<KdTree<PointT> > &tree,
float tolerance, std::vector<PointIndices> &clusters, double eps_angle,
unsigned int min_pts_per_cluster = ,
unsigned int max_pts_per_cluster = (std::numeric_limits<int>::max) ())

前两个的方法实现在文件extract_clusters.hpp中,后两个直接在头文件中就以内联函数的形式实现了,两个大同小异。择其中第一个加点注释,发现其实是采用的区域生长算法实现的分割。理解错误了,区域生长需要种子点,这里应该叫层次聚类方法。

  template <typename PointT, typename Normal> void
extractEuclideanClusters (
const PointCloud<PointT> &cloud, const PointCloud<Normal> &normals,
float tolerance, const boost::shared_ptr<KdTree<PointT> > &tree,
std::vector<PointIndices> &clusters, double eps_angle,
unsigned int min_pts_per_cluster = ,
unsigned int max_pts_per_cluster = (std::numeric_limits<int>::max) ())
{
if (tree->getInputCloud ()->points.size () != cloud.points.size ())
{
PCL_ERROR ("[pcl::extractEuclideanClusters] Tree built for a different point cloud dataset (%lu) than the input cloud (%lu)!\n", tree->getInputCloud ()->points.size (), cloud.points.size ());
return;
}
if (cloud.points.size () != normals.points.size ())
{
PCL_ERROR ("[pcl::extractEuclideanClusters] Number of points in the input point cloud (%lu) different than normals (%lu)!\n", cloud.points.size (), normals.points.size ());
return;
} // Create a bool vector of processed point indices, and initialize it to false
std::vector<bool> processed (cloud.points.size (), false); std::vector<int> nn_indices;
std::vector<float> nn_distances;
// Process all points in the indices vector
for (size_t i = ; i < cloud.points.size (); ++i)//遍历点云中的每一个点
{
if (processed[i])//如果该点已经处理则跳过
continue; std::vector<unsigned int> seed_queue;//定义一个种子队列
int sq_idx = ;
seed_queue.push_back (static_cast<int> (i));//加入一个种子 processed[i] = true; while (sq_idx < static_cast<int> (seed_queue.size ()))//遍历每一个种子
{
// Search for sq_idx
if (!tree->radiusSearch (seed_queue[sq_idx], tolerance, nn_indices, nn_distances))//没找到近邻点就继续
{
sq_idx++;
continue;
} for (size_t j = ; j < nn_indices.size (); ++j) // nn_indices[0] should be sq_idx
{
if (processed[nn_indices[j]]) // Has this point been processed before ?种子点的近邻点中如果已经处理就跳出此次循环继续
continue; //processed[nn_indices[j]] = true;
// [-1;1]
double dot_p = normals.points[i].normal[] * normals.points[nn_indices[j]].normal[] +
normals.points[i].normal[] * normals.points[nn_indices[j]].normal[] +
normals.points[i].normal[] * normals.points[nn_indices[j]].normal[];
if ( fabs (acos (dot_p)) < eps_angle ) //根据内积求夹角,法向量都是单位向量,种子点和近邻点的法向量夹角小于阈值,
{
processed[nn_indices[j]] = true;
seed_queue.push_back (nn_indices[j]);//将此种子点的临近点作为新的种子点。
}
} sq_idx++;
} // If this queue is satisfactory, add to the clusters
if (seed_queue.size () >= min_pts_per_cluster && seed_queue.size () <= max_pts_per_cluster)
{
pcl::PointIndices r;
r.indices.resize (seed_queue.size ());
for (size_t j = ; j < seed_queue.size (); ++j)
r.indices[j] = seed_queue[j]; // These two lines should not be needed: (can anyone confirm?) -FF
std::sort (r.indices.begin (), r.indices.end ());
r.indices.erase (std::unique (r.indices.begin (), r.indices.end ()), r.indices.end ()); r.header = cloud.header;
clusters.push_back (r); // We could avoid a copy by working directly in the vector
}
}
}

[PCL]3 欧式距离分类EuclideanClusterExtraction的更多相关文章

  1. 剑指Offer——网易笔试之不要二——欧式距离的典型应用

    剑指Offer--网易笔试之不要二--欧式距离的典型应用 前言 欧几里得度量(euclidean metric)(也称欧氏距离)是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的 ...

  2. 机器学习进阶-疲劳检测(眨眼检测) 1.dist.eculidean(计算两个点的欧式距离) 2.dlib.get_frontal_face_detector(脸部位置检测器) 3.dlib.shape_predictor(脸部特征位置检测器) 4.Orderdict(构造有序的字典)

    1.dist.eculidean(A, B) # 求出A和B点的欧式距离 参数说明:A,B表示位置信息 2.dlib.get_frontal_face_detector()表示脸部位置检测器 3.dl ...

  3. l2-loss,l2正则化,l2范数,欧式距离

    欧式距离: l2范数: l2正则化: l2-loss(也叫平方损失函数): http://openaccess.thecvf.com/content_cvpr_2017/papers/Li_Mimic ...

  4. PIE SDK 距离分类和最大似然分类

       1.算法功能简介 监督分类,也叫训练场地法.训练分类法,是遥感图像分类的一种,用被确认类别的样本像元去识别其他未知类别像元的过程.监督分类算法有平行算法.平行六面体法.最小距离法.最大似然法.马 ...

  5. cos距离与欧式距离

    1. 欧氏距离(EuclideanDistance) 欧氏距离是最易于理解的一种距离计算方法,源自欧氏空间中两点间的距离公式. (1)二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离: ( ...

  6. Acwing 社交距离 分类讨论+贪心

    一种新型疾病,COWVID-19,开始在全世界的奶牛之间传播. Farmer John 正在采取尽可能多的预防措施来防止他的牛群被感染. Farmer John 的牛棚是一个狭长的建筑物,有一排共 N ...

  7. 两个向量之间的欧式距离及radial-basis-functions(RBF)

    template <class DataType1, class DataType2>double EuclideanDistance(std::vector<DataType1&g ...

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

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

  9. PCL—低层次视觉—点云分割(邻近信息)

    分割给人最直观的影响大概就是邻居和我不一样.比如某条界线这边是中华文明,界线那边是西方文,最简单的分割方式就是在边界上找些居民问:"小伙子,你到底能不能上油管啊?”.然后把能上油管的居民坐标 ...

随机推荐

  1. 《GK101任意波发生器》升级固件发布(版本:1.0.2build851)

    一.固件说明: 硬件版本:0,logic.3 固件版本:1.0.2.build851 编译日期:2015-06-26 ====================================== 二. ...

  2. HDU 2795 Billboard(线段树的另类应用)

    Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. hdu 1116 并查集和欧拉路径

    ---恢复内容开始--- 把它看成是一个图 只是需要欧拉路径就可以了 首尾能连成一条线即可 如果要判断这个图是否连通 得用并查集 在hrbust oj里面看答案学到的方法 不用各种for循环套着判断能 ...

  4. storm在linux系统下安装调试

    安装: 安装 zookeeper : 下载 zookeeper :http://zookeeper.apache.org/releases.html#download. 将 zookeeper-3.4 ...

  5. [ZZ] D3D中的模板缓存(3)

    http://www.cppblog.com/lovedday/archive/2008/03/25/45334.html http://www.cppblog.com/lovedday/ D3D中的 ...

  6. PHP 错误与异常 笔记与总结(1)错误(Deprecated,Notice,Warning)

    [常见的错误类型] ① 语法错误 [例1]程序语句结尾少了';' <?php $username = "dee" //少了分号; echo $username; 输出: ( ...

  7. 【CEDEC 2015】【夏日课堂】制作事宜技术篇,新手职员挑战VR Demo开发的真相

    日文原文地址 http://www.4gamer.net/games/277/G027751/20150829002/ PS:CEDEC 2015的PPT有些要到10月才有下载,目前的都是记者照片修图 ...

  8. 【翻译】Kinect v1和Kinect v2的彻底比较

      本连载主要是比较Kinect for Windows的现行版(v1)和次世代型的开发者预览版(v2),以C++开发者为背景介绍进化的硬件和软件.本文主要是对传感的配置和运行条件进行彻底的比较.   ...

  9. 用 BigDump 工具导入超大 MySQL 数据库备份文件

    用 BigDump 工具导入超大 MySQL 数据库备份文件  创建于 2010-07-01, 周四 00:00  作者 白建鹏 在<Joomla! 1.5 网站防黑9条戒律>这篇文章中, ...

  10. 迷宫dfs

    #include<stdio.h>int mov1[4]={0,0,1,-1};int mov2[4]={1,-1,0,0};int map[5][5]={0,1,0,0,1,      ...