[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—低层次视觉—点云分割(邻近信息)
分割给人最直观的影响大概就是邻居和我不一样.比如某条界线这边是中华文明,界线那边是西方文,最简单的分割方式就是在边界上找些居民问:"小伙子,你到底能不能上油管啊?”.然后把能上油管的居民坐标 ...
随机推荐
- 【iCore2双核心板视频教程】 AD模块(iM_AD_GP和iM_AD_SYNC)介绍及数据采集实验三
建议设定成 “超清” 模式并 “全屏” 观看. ============================== 技术论坛:http://www.eeschool.org 博客地址:http://xiao ...
- MySQL表的创建和表中数据操作
这篇文章主要介绍在navicat的命令界面操作mysql.主要涉及建立表结构,和对表中数据的增加删除修改查询等动作.站在一个新手角度的简单mysql表结构和数据操作. ☆ 准备工作 1,保证自己的电脑 ...
- 解析数据存储MySQL
为了适应不同项目对不同感兴趣属性的解析存储,数据存储结构采用纵向的属性列表方式,即一个url页面多个属性存储多条记录方式,并且按照text,html, data,num几大典型类型分别对应存储. 创建 ...
- yii2.0安装创建应用shiyong 归档文件安装
环境是wamp在本机开发 http://www.yiiframework.com/download/ Install from an Archive File Download one of the ...
- TCP移动端跟服务器数据交互
同一台笔记本下的客户端和服务端 TCPClient 客户端: // RootViewController.h#import <UIKit/UIKit.h>#import "As ...
- PHP开发绝对不能违背的安全铁则
PHP开发绝对不能违背的安全铁则 [来源] 达内 [编辑] 达内 [时间]2012-12-27 使用 mysql_real_escape_string() 作为用户输入的包装器,就可以避免用 ...
- WordPress博客教程:博客赚钱
稍有关注独立博客的人都应该知道,中文博客实现盈利非常艰难,至少对于大部分中文博客来说是这样的.但很多时候我们不得不往赚钱的方向前进,至少要交得起域名和空间的租用费吧.不过期待赚钱前,你必须思考下如何提 ...
- SSH 基础
什么是SSH? 传统的网络服务程序,如:ftp.pop和telnet在本质上都是不安全的,因为它们在网络上用明文传送口令和数据,别有用心的人非常容易就可以截获这些口令和数据.而且,这些服务程序的安全验 ...
- sqlserver log
DBCC LOGINFODBCC log('QSSys', TYPE=2)goselect * from sys.fn_dblog(null,null)select [Dirty Pages],[Mi ...
- 原生js实现跑马灯抽奖效果
目前好多的微信活动都有一些抽奖活动,其中就有跑马灯. <!DOCTYPE html> <html> <head> <title>跑马灯效果</ti ...