PCL教程-点云滤波之投影滤波

本文介绍了如何使用PCL库在PCA中将三维点云投影到平面模型,如x-y平面上,并展示了通过随机点云操作和系数设置实现的投影效果。重点在于理解投影原理和实际编程应用。

原文链接:Projecting points using a parametric model

本小节将学习如何将点投影到一个参数化模型上(例如平面或球等)。参数化模型通过一组参数来设定,对于平面来说使用其等式形式ax+by+cz+d=0,在PCI中有专门存储常见模型系数的数据结构。

程序代码

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/project_inliers.h>
#include<pcl/visualization/pcl_visualizer.h>
int
main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>);

	pcl::visualization::PCLVisualizer viewer("project inliers");
	int v1(1);
	int v2(2);
	viewer.createViewPort(0, 0, 0.5, 1, v1);
	viewer.createViewPort(0.5, 0, 1, 1, v2);


	// 填入点云数据
	cloud->width = 5;
	cloud->height = 1;
	cloud->points.resize(cloud->width * cloud->height);
	for (size_t i = 0; i < cloud->points.size(); ++i)
	{
		cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
	}
	std::cerr << "Cloud before projection: " << std::endl;
	for (size_t i = 0; i < cloud->points.size(); ++i)
		std::cerr << "    " << cloud->points[i].x << " "
		<< cloud->points[i].y << " "
		<< cloud->points[i].z << std::endl;
	// 平面公式:ax + by + cz + d = 0
	// 创建一个系数为X=Y=0,Z=1的平面,相当于是x-y平面
	// a = b = d = 0, c = 1;
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
	coefficients->values.resize(4);
	coefficients->values[0] = coefficients->values[1] = 0;
	coefficients->values[2] = 1.0;
	coefficients->values[3] = 0;
	// 创建滤波器对象
	pcl::ProjectInliers<pcl::PointXYZ> proj;//创建滤波器对象
	proj.setModelType(pcl::SACMODEL_PLANE); //设置对象对应的投影模型
	proj.setInputCloud(cloud);
	proj.setModelCoefficients(coefficients);//设置投影模型的参数因子
	proj.filter(*cloud_projected);

	std::cerr << "Cloud after projection: " << std::endl;
	for (size_t i = 0; i < cloud_projected->points.size(); ++i)
		std::cerr << "    " << cloud_projected->points[i].x << " "
		<< cloud_projected->points[i].y << " "
		<< cloud_projected->points[i].z << std::endl;

	viewer.addPointCloud(cloud, "c1", v1);
	viewer.addPointCloud(cloud_projected, "c2", v2);
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1000, "c1", v1);
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1000, "c2", v2);
	viewer.addCoordinateSystem(1000, cloud_projected->points[0].x, cloud_projected->points[0].y, cloud_projected->points[0].z, v2);
	viewer.addCoordinateSystem(1000, cloud->points[0].x, cloud->points[0].y, cloud->points[0].z, v1);

	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}
	return (0);
}

 在本程序中使用的投影模型为平面。

平面公式:ax + by + cz + d = 0

创建一个系数为X=Y=0,Z=1的平面,相当于是x-y平面
系数设置为:a = b = d = 0, c = 1;

	// 平面公式:ax + by + cz + d = 0
	// 创建一个系数为X=Y=0,Z=1的平面,相当于是x-y平面
	// a = b = d = 0, c = 1;
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
	coefficients->values.resize(4);
	coefficients->values[0] = coefficients->values[1] = 0;
	coefficients->values[2] = 1.0;
	coefficients->values[3] = 0;
	// 创建滤波器对象
	pcl::ProjectInliers<pcl::PointXYZ> proj;//创建滤波器对象
	proj.setModelType(pcl::SACMODEL_PLANE); //设置对象对应的投影模型
	proj.setInputCloud(cloud);
	proj.setModelCoefficients(coefficients);//设置投影模型的参数因子
	proj.filter(*cloud_projected);

 实验结果

首先随机生成五个点,如左图。

然后将所有点全部投影到X-Y平面(Z=1):如右图:

 

 

 Cloud before projection:
    1.28125 577.094 197.938
    828.125 599.031 491.375
    358.688 917.438 842.562
    764.5 178.281 879.531
    727.531 525.844 311.281
Cloud size before projection: 5
Cloud after projection:
    1.28125 577.094 0
    828.125 599.031 0
    358.688 917.438 0
    764.5 178.281 0
    727.531 525.844 0
Cloud size after projection: 5

由上述结果可知:将点云投影到一个平面,会使点云的某个坐标失去意义(坐标值相同),将三维的点云变成了二维的图像。 

 同理,对点云数据 table_scene_lms400.pcd进行投影滤波的结果如下:

 

 

 三维的点云图像已经失去了一个坐标的数据,变成了二维扁平的点云图像。

抱歉,我是一个语言模型AI,无法提供您所需的代码。但是,我可以给您一些参考思路。 点云滤波是指对点云数据进行去噪或平滑处理,以提高其质量和准确性。常用的点云滤波方法包括高斯滤波、中值滤波、统计滤波等。 误差计算是指对点云数据进行误差分析,以评估其准确性和可靠性。常用的误差计算方法包括重投影误差计算、最小二乘法拟合、卡方检验等。 下面是一个简单的点云滤波和误差计算的代码示例: ``` #include <iostream> #include <pcl/point_types.h> #include <pcl/filters/statistical_outlier_removal.h> #include <pcl/filters/voxel_grid.h> #include <pcl/registration/icp.h> int main() { // 读取点云数据 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile("cloud.pcd", *cloud); // 高斯滤波 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; sor.setInputCloud(cloud); sor.setMeanK(50); sor.setStddevMulThresh(1.0); sor.filter(*cloud_filtered); // 体素滤波 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_downsampled(new pcl::PointCloud<pcl::PointXYZ>); pcl::VoxelGrid<pcl::PointXYZ> vg; vg.setInputCloud(cloud_filtered); vg.setLeafSize(0.01f, 0.01f, 0.01f); vg.filter(*cloud_downsampled); // ICP匹配 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_registered(new pcl::PointCloud<pcl::PointXYZ>); pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp; icp.setInputSource(cloud_downsampled); icp.setInputTarget(cloud_filtered); icp.align(*cloud_registered); // 输出误差 std::cout << "ICP has converged:" << icp.hasConverged() << std::endl; std::cout << "ICP score:" << icp.getFitnessScore() << std::endl; return 0; } ``` 该代码使用了PCL库实现点云滤波和误差计算。具体步骤包括: 1. 读取点云数据。 2. 高斯滤波和统计滤波去噪。 3. 体素滤波平滑处理。 4. 使用ICP算法进行点云匹配。 5. 输出匹配误差。 您可以根据您的具体需求和数据来调整代码中的参数和方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值