PCL点云压薄

该文介绍了一种使用PCL库进行点云处理的方法,首先读取LAS格式的点云数据,然后利用KdTree和法向量估计进行点云的压薄操作。通过对每个点的邻域平均和法向量计算,将点云沿其法线方向移动,达到压薄效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、算法原理

二、代码实现
三、结果展示

一、算法原理

1.概述

在对地面点云或者墙壁进行分类后需要对分类后的数据进行压薄。

2.参考文献或代码

https://github.com/csiro-robotics/raycloudtools

二、代码实现

main.cpp

int main()
{
	std::string inputCloud= "E:/test.las";
	std::string outputCloud= "E:/out.las";
	//读取点云文件
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>(inputCloud, *cloud) == -1)//*打开点云文件
	{
		PCL_ERROR("Couldn't read file test_pcd.pcd\n");
		return(-1);
	}
	pcl::KdTreeFLANN<pcl::PointXYZ> kdTree;
	kdTree.setInputCloud(cloud);
	const int K = 50;

	pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;   
	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
	
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
	n.setNumberOfThreads(8);
	//n.setViewPoint(0,0,0);//设置视点,默认为(0,0,0)
	n.setInputCloud(cloud);
	n.setSearchMethod(tree);
	n.setKSearch(K);//点云法向计算时,需要所搜的近邻点大小
	n.compute(*normals);//开始进行法向计算
	const int num_neighbours = 50;
	Eigen::MatrixXi neighbour_indices;

	std::vector<Eigen::Vector3d> centroids(cloud->points.size(), { 0,0,0 });
	std::vector<Eigen::Vector3d> eigen_normals;
	eigen_normals.resize(cloud->points.size());

	for (int n = 0; n < cloud->points.size(); ++n)
	{
		Eigen::Vector3d normall;
		normall.x() = normals->at(n).normal[0];
		normall.y() = normals->at(n).normal[1];
		normall.z() = normals->at(n).normal[2];
		eigen_normals[n] = normall;
	}

	int number = 0;
	for (size_t i = 0; i < cloud->points.size(); i++)
	{
		double total_weight = 0.2;  // more averaging if it uses less of the central position, but 0 risks a divide by 0

		Eigen::Vector3d curPoint1;
		curPoint1.x() = cloud->points[i].x;
		curPoint1.y() = cloud->points[i].y;
		curPoint1.z() = cloud->points[i].z;

		Eigen::Vector3d weighted_sum = curPoint1 * total_weight;

		std::vector<int> pointIdxNKNSearch(K);
		std::vector<float>pointNKNSquaredDistance(K);
		if (kdTree.nearestKSearch(cloud->points[i], K, pointIdxNKNSearch, pointNKNSquaredDistance) > /*0*/40)
		{
			Eigen::Vector3d meanPoint = Eigen::Vector3d::Zero();

			for (int j = 0; j < num_neighbours; j++)
			{
				int k = pointIdxNKNSearch[j];
				meanPoint.x() += cloud->points[k].x;
				meanPoint.y() += cloud->points[k].y;
				meanPoint.z() += cloud->points[k].z;
			}
			centroids[i] = meanPoint / num_neighbours;
			//沿着中心点的方向进行移动
			curPoint1 += eigen_normals[i] * (centroids[i] - curPoint1).dot(eigen_normals[i]);
			//curPoint1 += eigen_normals[i] * (curPoint1 - centroids[i]).dot(eigen_normals[i]);  //将点云拉厚了。

			cloud->points[i].x = curPoint1.x();
			cloud->points[i].y = curPoint1.y();
			cloud->points[i].z = curPoint1.z();
		}
	}
	cout << number << std::endl;
	pcl::PCDWriter writer;
	writer.write(outputCloud, *cloud);
	return 0;
}

三、结果展示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值