PCL点云库——欧式聚类分割

9 篇文章 2 订阅
3 篇文章 1 订阅

欧式聚类分割


  pcl::EuclideanClusterExtraction是基于欧式距离提取集群的方法,仅依据距离,将小于距离阈值的点云作为一个集群。
  具体的实现方法大致是:
  (1) 找到空间中某点p10,由kdTree找到离他最近的n个点,判断这n个点到p的距离;
  (2) 将距离小于阈值r的点p12、p13、p14…放在类Q里;
  (3) 在 Q\p10 里找到一点p12,重复1;
  (4) 在 Q\p10、p12 找到一点,重复1,找到p22、p23、p24…全部放进Q里;
  (5) 当 Q 再也不能有新点加入了,则完成搜索了。

//****欧式聚类分割****//

#include <pcl/io/pcd_io.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/visualization/cloud_viewer.h>
#include <string>
#include <atlstr.h>//CString头文件
using namespace std;

int 
main (int argc, char** argv)
{
  // 读取点云数据
  pcl::PCDReader reader;
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  reader.read ("test.pcd", *cloud);

  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
  tree->setInputCloud(cloud);

  std::vector<pcl::PointIndices> cluster_indices;
  pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;//创建欧式聚类分割对象
  ec.setClusterTolerance(3); //设置近邻搜索的搜索半径
  ec.setMinClusterSize(5000); //设置最小聚类尺寸
  ec.setMaxClusterSize(100000);
  ec.setSearchMethod(tree);
  ec.setInputCloud(cloud);
  ec.extract(cluster_indices);

  std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> Eucluextra; //用于储存欧式分割后的点云
  for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
  {
	  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>);
    for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++)
		cloud_cluster->points.push_back(cloud->points[*pit]);
    cloud_cluster->width = cloud_cluster->points.size ();
    cloud_cluster->height = 1;
    cloud_cluster->is_dense = true;
	Eucluextra.push_back(cloud_cluster);
  }

  //可视化
  pcl::visualization::PCLVisualizer viewer("PCLVisualizer");
  viewer.initCameraParameters();

  int v1(0);
  viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1);
  viewer.setBackgroundColor(128.0 / 255.0, 138.0 / 255.0, 135.0 / 255.0, v1);
  viewer.addText("Cloud before segmenting", 10, 10, "v1 test", v1);
  viewer.addPointCloud<pcl::PointXYZ>(cloud, "cloud", v1);

  int v2(0);
  viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);
  viewer.setBackgroundColor(128.0 / 255.0, 138.0 / 255.0, 135.0 / 255.0, v2);
  viewer.addText("Cloud after segmenting", 10, 10, "v2 test", v2);
  for (int i = 0; i < Eucluextra.size(); i++)
  {
	  CString cstr;
	  cstr.Format(_T("cloud_segmented%d"), i);
	  cstr += _T(".pcd");
	  string str_filename = CStringA(cstr);
	  //显示分割得到的各片点云 
	  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color(Eucluextra[i], 255 * (1 - i)*(2 - i) / 2, 255 * i*(2 - i), 255 * i*(i - 1) / 2);
	  viewer.addPointCloud(Eucluextra[i], color, str_filename, v2);
  }

  while (!viewer.wasStopped())
  { 
	  viewer.spinOnce(100);
	  boost::this_thread::sleep(boost::posix_time::microseconds(100000));
  }
  return (0);
}

在这里插入图片描述

图1 分割实例一

以下为麦粒的分割实例。

//****欧式聚类分割****//

#include <pcl/io/pcd_io.h>//点云pcd输入输出头文件
#include <pcl/segmentation/extract_clusters.h>//欧式聚类分割头文件
#include <pcl/visualization/cloud_viewer.h>//点云可视化头文件
#include <string>
#include <atlstr.h>//CString头文件
//#include <iomanip>
using namespace std;
clock_t start_time, end_time;

int
main(int argc, char** argv)
{
	// 读取点云数据
	pcl::PCDReader reader;//pcd文件读取对象
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	reader.read("wheat_data.pcd", *cloud);//读取点云文件

	start_time = clock();//程序开始计时
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);//kd树对象
	tree->setInputCloud(cloud);

	std::vector<pcl::PointIndices> cluster_indices;
	pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;//创建欧式聚类分割对象
	ec.setClusterTolerance(0.2); //设置近邻搜索的搜索半径
	ec.setMinClusterSize(100); //设置最小聚类尺寸
	ec.setMaxClusterSize(100000); //设置最大聚类尺寸
	ec.setSearchMethod(tree);
	ec.setInputCloud(cloud);
	ec.extract(cluster_indices);

	std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> Eucluextra; //用于储存欧式分割后的点云
	for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it)
	{
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>);
		for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); pit++)
			cloud_cluster->points.push_back(cloud->points[*pit]);
		cloud_cluster->width = cloud_cluster->points.size();
		cloud_cluster->height = 1;
		cloud_cluster->is_dense = true;
		Eucluextra.push_back(cloud_cluster);
	}
	end_time = clock();//程序结束用时
	double endtime = (double)(end_time - start_time) / CLOCKS_PER_SEC;
	cout << "Total time:" << endtime << "s" << endl;//s为单位
	cout << "Total time:" << endtime * 1000 << "ms" << endl;//ms为单位

	//可视化
	pcl::visualization::PCLVisualizer viewer("PCLVisualizer");
	viewer.initCameraParameters();

	int v1(0);//窗口一
	viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1);
	viewer.setBackgroundColor(128.0 / 255.0, 138.0 / 255.0, 135.0 / 255.0, v1);
	viewer.addText("Cloud before segmenting", 10, 10, "v1 test", v1);
	viewer.addPointCloud<pcl::PointXYZ>(cloud, "cloud", v1);

	int v2(0);//窗口二
	viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);
	viewer.setBackgroundColor(128.0 / 255.0, 138.0 / 255.0, 135.0 / 255.0, v2);
	viewer.addText("Cloud after segmenting", 10, 10, "v2 test", v2);
	for (int i = 0; i < Eucluextra.size(); i++)
	{
		CString cstr;
		cstr.Format(_T("cloud_segmented_%d.pcd"), i);
		string str_filename = CStringA(cstr);
		pcl::io::savePCDFile(str_filename, *Eucluextra[i]);//保存点云
		//显示分割得到的各片点云 
		pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color(Eucluextra[i], 255 * (1 - i)*(2 - i)*(3 - i), 255 * i*(2 - i) * 2 * (0 - i), 255 * i*(i - 1)*(4 - i));
		viewer.addPointCloud(Eucluextra[i], color, str_filename, v2);
	}

	ofstream fout;//文件流
	fout.open("wheat_data.txt");
	int i = 0;
	while (i < cloud->size())
	{
		int index = 0;
		for (int j = 0; j < Eucluextra.size(); j++)
		{
			for (int k = 0; k < Eucluextra[j]->size(); k++)
			{
				if (cloud->points[i].x == Eucluextra[j]->points[k].x&&cloud->points[i].y == Eucluextra[j]->points[k].y&&cloud->points[i].z == Eucluextra[j]->points[k].z)
					index = j;//获取每个点属于分割出的哪个麦粒
			}
		}
		//每个数保存为5位小数
		fout << setiosflags(ios::fixed) << setprecision(5) << cloud->points[i].x << " " 
			<< setiosflags(ios::fixed) << setprecision(5) << cloud->points[i].y << " " 
			<< setiosflags(ios::fixed) << setprecision(5) << cloud->points[i].z << " " 
			<< index << endl;
		i++;
	}
	fout.close();

	//可视化窗口停留
	while (!viewer.wasStopped())
	{
		viewer.spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}
	return (0);
}
图2 分割实例二——麦粒分割
  • 7
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
PCL点云中的欧式聚类分割是一种通过计算点云中点之间的欧氏距离来将点云分割成不同的聚类的方法。在这种方法中,首先对点云进行预处理,包括去除离群点和平面模型分割。然后,使用pcl::EuclideanClusterExtraction类对点云进行欧式聚类分割。该类通过设置聚类的最小和最大尺寸,以及聚类的距离阈值来提取聚类。 在使用欧式聚类分割的过程中,首先对点云进行预处理,包括去除离群点和平面模型分割。然后,根据设定的距离阈值,将点云中的点分成不同的聚类聚类的最小和最大尺寸可以用来控制聚类的大小。最后,可以通过获取每个聚类中的点的数量,进一步分析和处理聚类。 通过使用PCL点云中的欧式聚类分割方法,可以对点云数据进行有效的分割聚类,从而实现对点云数据的进一步分析和应用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [PCL点云-欧式聚类分割-麦粒](https://download.csdn.net/download/fei_12138/87570560)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [PCL教程-点云分割欧式聚类分割](https://blog.csdn.net/luolaihua2018/article/details/120184539)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值