[PCL]3 欧式距离分类EuclideanClusterExtraction
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的更多相关文章
- 剑指Offer——网易笔试之不要二——欧式距离的典型应用
剑指Offer--网易笔试之不要二--欧式距离的典型应用 前言 欧几里得度量(euclidean metric)(也称欧氏距离)是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的 ...
- 机器学习进阶-疲劳检测(眨眼检测) 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 ...
- l2-loss,l2正则化,l2范数,欧式距离
欧式距离: l2范数: l2正则化: l2-loss(也叫平方损失函数): http://openaccess.thecvf.com/content_cvpr_2017/papers/Li_Mimic ...
- PIE SDK 距离分类和最大似然分类
1.算法功能简介 监督分类,也叫训练场地法.训练分类法,是遥感图像分类的一种,用被确认类别的样本像元去识别其他未知类别像元的过程.监督分类算法有平行算法.平行六面体法.最小距离法.最大似然法.马 ...
- cos距离与欧式距离
1. 欧氏距离(EuclideanDistance) 欧氏距离是最易于理解的一种距离计算方法,源自欧氏空间中两点间的距离公式. (1)二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离: ( ...
- Acwing 社交距离 分类讨论+贪心
一种新型疾病,COWVID-19,开始在全世界的奶牛之间传播. Farmer John 正在采取尽可能多的预防措施来防止他的牛群被感染. Farmer John 的牛棚是一个狭长的建筑物,有一排共 N ...
- 两个向量之间的欧式距离及radial-basis-functions(RBF)
template <class DataType1, class DataType2>double EuclideanDistance(std::vector<DataType1&g ...
- PCL中分割_欧式分割(1)
基于欧式距离的分割和基于区域生长的分割本质上都是用区分邻里关系远近来完成的.由于点云数据提供了更高维度的数据,故有很多信息可以提取获得.欧几里得算法使用邻居之间距离作为判定标准,而区域生长算法则利用了 ...
- PCL—低层次视觉—点云分割(邻近信息)
分割给人最直观的影响大概就是邻居和我不一样.比如某条界线这边是中华文明,界线那边是西方文,最简单的分割方式就是在边界上找些居民问:"小伙子,你到底能不能上油管啊?”.然后把能上油管的居民坐标 ...
随机推荐
- Ubuntu输入密码登陆后又跳回到登录界面
现象:在Ubuntu登陆界面输入密码之后,黑屏一闪并且出现了check battery state之类的文字之后,又跳转到登录界面.原因:主目录下的.Xauthority文件拥有者变成了root,从而 ...
- eclipse远程调试
-Xdebug -Xrunjdwp:transport=dt_socket,address=127.0.0.1:8000Eclipse 菜单上的 Window > Preferences > ...
- Nginx 笔记与总结(1)编译安装
Nginx 可以承受 3 万并发连接数,Apache 默认最大连接数是 256 个. 编译安装 ① 下载 在 Nginx 的主页 http://nginx.org/ 下载最新的 stable vers ...
- Visual Studio快捷键不能使用解决办法
环境: Visual Studio 2010,windows 7 使用Visual Studio查找变量或方法时常用到[定位到]功能 但该功能的快捷键却不能使用,解决办法如下所示: 1.工具--> ...
- SMS模型格网转换为MIKE21的格网源代码
program main !sms网格转换成mike21网格 DIMENSION X(),Y(),H(),NDNN(,),ncbd() dimension NBS(),NOBD(,),NSED(,), ...
- 我的第一个chrome扩展(3)——继续读样例
1.操作用户正在浏览的界面 http://www.ituring.com.cn/article/60212 问题:1.google未定义ID,用name为何无法找到? 2.如何让整个按钮一起动?原函数 ...
- Java实验报告五:Java网络编程及安全
Java实验报告五:Java网络编程及安全 ...
- zepto源码--整体框架--学习笔记
为了深入学习javascript,根据别人推荐的方法之一:研究源码. 相对而言,之前的项目中仅仅使用过zepto和jquery,当前阶段,看到好几千行的jquery源码,心生敬畏,望而却步,所以选择相 ...
- android提供ToolBar实现划动菜单的陷阱
代码如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android: ...
- Cocos2d-JS目录说明
frameworks---- 引擎所在,包含两个文件夹cocos2d-html5 和js-bindings.前者是html5引擎,后者是-x的引擎,外部接口是js写,但基础模块却是cpp来实现. sa ...