基于欧式聚类的车载路面点云扫描线提取

Posted 没事就要敲代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于欧式聚类的车载路面点云扫描线提取相关的知识,希望对你有一定的参考价值。

1 扫描线示意图

车载激光扫描系统主要的扫描方式为线形扫描【方莉娜,等:车载激光扫描数据的结构化道路自动提取方法,测绘学报】

下面,给出基于欧式聚类分割的车载路面点云扫描线提取方法。此方法较为简单,其原理根据“同一扫描线上的点间隔小,不同扫描线上的点间隔大”,进行扫描线提取。该方法只适用于扫描线之间间隔大于扫描线上点间隔的情况,否则无法有效提取。

关于欧式聚类分割,可参考 https://blog.csdn.net/weixin_46098577/article/details/116129817

2 基于欧式聚类的车载路面点云扫描线提取

描述:基于欧式聚类,进行扫描线提取,并为每一条扫描线赋单一颜色,以便区分不同的扫描线。关于点云赋色。可参考https://blog.csdn.net/weixin_46098577/article/details/122330201

代码:

#include <pcl/io/pcd_io.h>
#include <pcl/segmentation/extract_clusters.h>

using namespace std;

typedef pcl::PointXYZRGB PointT;
typedef pcl::PointCloud<PointT> PointCloudT;

int main()

	

	//------------------------ 参数设置 ------------------------
	double scanlineInterval;	//扫描线间隔
	int pointsMinNum;			//一条扫描线最小点数
	int pointsMaxNum;			//一条扫描线最大点数
	scanlineInterval = 0.04;
	pointsMinNum = 100;
	pointsMaxNum = 200;
	//======================== 参数设置 ========================

	//------------------------ 加载点云 ------------------------
	PointCloudT::Ptr cloud(new PointCloudT);
	if (pcl::io::loadPCDFile("road.pcd", *cloud) < 0)
	
		PCL_ERROR("->\\a点云文件不存在!\\n");
		return -1;
	
	cout << "->加载点云详情:\\n" << *cloud << endl;
	//======================== 加载点云 ========================

	//--------------- 定义颜色数组,用于扫描线附色 ---------------
	const int colors[][3]=
	
		255, 0,   0,	// red 			1
		0,   255, 0,	// green		2
		0,   0,   255,	// blue			3
		255, 255, 0,	// yellow		4
		0,   255, 255,	// light blue	5
		255, 0,   255,	// magenta		6
		255, 255, 255,	// white		7
		255, 128, 0,	// orange		8
		255, 153, 255,	// pink			9
		155, 48, 255,	// purple		10
	;
	//=============== 定义颜色数组,用于扫描线附色 ===============

	//------------------- 欧式聚类提取扫描线 --------------------
	pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>);
	tree->setInputCloud(cloud);
	vector<pcl::PointIndices> cluster_indices;
	pcl::EuclideanClusterExtraction<PointT> ec;
	ec.setInputCloud(cloud);
	ec.setClusterTolerance(scanlineInterval);
	ec.setMinClusterSize(pointsMinNum);
	ec.setMaxClusterSize(pointsMaxNum);
	ec.setSearchMethod(tree);
	ec.extract(cluster_indices);

	int num = 0;	//扫描线个数
	for (vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it)
	
		PointCloudT::Ptr cloud_cluster(new PointCloudT);	//扫描线

		int i = 0;
		for (vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); pit++)
		
			//扫描线提取
			cloud_cluster->points.push_back(cloud->points[*pit]);
			//扫描线单一附色
			cloud_cluster->points[i].r = (uint8_t)colors[num % 10][0];
			cloud_cluster->points[i].g = (uint8_t)colors[num % 10][1];
			cloud_cluster->points[i].b = (uint8_t)colors[num % 10][2];

			i++;
		
		
		//依次保存扫描线点云
		stringstream ss;
		ss << "scanline_" << num + 1 << ".pcd";
		pcl::io::savePCDFileBinary(ss.str(), *cloud_cluster);
		num++;
	
	cout << "->共提取扫描线" << num << "条" << endl;
	//=================== 欧式聚类提取扫描线 ====================

	return 0;

输出结果:

->加载点云详情:
points[]: 25955
width: 25955
height: 1
is_dense: 1
sensor origin (xyz): [0, 0, 0] / orientation (xyzw): [-0.707107, 0, 0, 0.707107]

->共提取扫描线145

扫描线提取效果展示:

图1 原始点云

图2 扫描线提取结果

图3 扫描线与原始点云(黑色为原始点云)

3 实验结果分析

  • 未成功提取的扫描线,是由于此处距离扫描仪较远,同一扫描线上的点间隔较大,超过欧式聚类的搜索范围
  • 将两条扫描线误分为同一条扫描线的原因是,由于车辆行驶不稳等原因造成相邻扫描线的间隔小于欧式聚类的搜索范围。
  • 想要获取鲁棒性更高的扫描线,需要根据GPSTime进行扫描线提取。

以上是关于基于欧式聚类的车载路面点云扫描线提取的主要内容,如果未能解决你的问题,请参考以下文章

点云处理技术之PCL点云分割算法1——平面模型分割圆柱模型分割和欧式聚类提取(含欧式聚类原理)

MATLAB点云处理进阶:欧式聚类分割❤️独立窗口显示每一聚类结果❤️保存聚类点云

3D,点云分割,不要割个寂寞

3D,点云分割,不要割个寂寞

基于曲率的体素聚类的三维激光雷达点云实时鲁棒分割方法

PCL:基于区域生长的点云分割——保存分割结果