PCL:投影滤波将点云投影至球面

Posted 没事就要敲代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PCL:投影滤波将点云投影至球面相关的知识,希望对你有一定的参考价值。

1 PCL投影滤波器实现点云向球面投影

PCL官方文档上指出,可以使用投影滤波器实现点云向平面、球面、圆锥面的投影。

在这之前,我们已经介绍了如何使用PCL中提供的投影滤波器实现点云向参数平面的投影。下面,参考平面模型投影的方式,实现点云向球面模型的投影。

首先,明确球面方程
( x − x 0 ) 2 + ( y − y 0 ) 2 + ( z − z 0 ) 2 = r 2 (x-x_0)^2+(y-y_0)^2+(z-z_0)^2=r^2 (xx0)2+(yy0)2+(zz0)2=r2
式中, ( x 0 , y 0 , z 0 ) (x_0,y_0,z_0) (x0,y0,z0) 为球心, r r r 为球半径。

PCL 提供了SACMODEL_SPHERE模型:定义为三维球体模型,共设置4个参数[center.x,center.y,center.z,radius],前三个参数为球心,第四个参数为半径。

下面将点云投影至球心为 ( 0 , 0 , − 1 ) (0,0,-1) (0,0,1),半径为 2 2 2 的球面,即
x 2 + y 2 + ( z + 1 ) 2 = 4 x^2+y^2+(z+1)^2=4 x2+y2+(z+1)2=4

代码实现:

#include <pcl/io/pcd_io.h>
#include <pcl/ModelCoefficients.h>			//模型系数定义头文件
#include <pcl/filters/project_inliers.h>	//投影滤波类头文件

using namespace std;

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

int main()

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

	//--------- 创建球面模型 (x - x0)^2 + (y - y0)^2 + (z - z0)^2 = r^2 -------------
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
	coefficients->values.resize(4);
	coefficients->values[0] = 0;
	coefficients->values[1] = 0;
	coefficients->values[2] = -1.0;
	coefficients->values[3] = 2.0;
	//========= 创建球面模型 (x - x0)^2 + (y - y0)^2 + (z - z0)^2 = r^2 ============

	//-------------------------------- 执行投影滤波 --------------------------------
	PointCloudT::Ptr cloud_projected(new PointCloudT);
	pcl::ProjectInliers<pcl::PointXYZ> proj;
	proj.setModelType(pcl::SACMODEL_SPHERE);		//球面模型
	proj.setInputCloud(cloud);
	proj.setModelCoefficients(coefficients);
	proj.filter(*cloud_projected);
	//================================ 执行投影滤波 ================================

	//保存滤波点云
	if (!cloud_projected->empty())
	
		pcl::io::savePCDFileBinary("sphere_project.pcd", *cloud_projected);
	
	else
	
		PCL_ERROR("\\a->投影滤波点云为空!\\n");
	

	return 0;

运行结果:

Unfortunately,PCL貌似没有实现点云向球面模型的投影,结果如下图。

既然PCL靠不住,我们只好自己实现了。

2 点云投影至指定球面

2.1 投影原理

(1)指定投影球面参数,即球心 p 0 ( x 0 , y 0 , z 0 ) p_0(x_0,y_0,z_0) p0(x0,y0,z0) 和半径 r r r
(2)计算点云中每一点与坐标原点 ( 0 , 0 , 0 ) (0,0,0) (0,0,0)的距离 d i d_i di
(3)点 p i ( x i , y i , z i ) p_i(x_i,y_i,z_i) pi(xi,yi,zi) 在球面的投影点 p s ( x s , y s , z s ) p_s(x_s,y_s,z_s) ps(xs,ys,zs)
x s = x i ∗ r d i + x 0 y s = y i ∗ r d i + y 0 z s = z i ∗ r d i + z 0 \\begincases x_s = \\cfracx_i*rd_i+x_0\\\\ y_s = \\cfracy_i*rd_i+y_0\\\\ z_s = \\cfracz_i*rd_i+z_0\\\\ \\endcases xs=dixir+x0ys=diyir+y0zs=dizir+z0

2.2 代码实现

代码:

#include <pcl/io/pcd_io.h>

using namespace std;

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

//定义球的结构体
struct Sphere

	float center_x;
	float center_y;
	float center_z;
	float radius;
;

int main()

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

	//---------------------------------- 指定球面 ----------------------------------
	Sphere s;		//x^2+y^2+(z+1)^2=4
	s.center_x = 0;
	s.center_y = 0;
	s.center_z = -1;
	s.radius = 2;
	//================================== 指定球面 ==================================

	//---------------------------------- 执行投影 ----------------------------------
	PointCloudT::Ptr cloud_proj(new PointCloudT);
	size_t pt_num = cloud->points.size();
	for (size_t i = 0; i < pt_num; i++)
	
		float d;
		d = sqrt(pow(cloud->points[i].x, 2) + pow(cloud->points[i].y, 2) + pow(cloud->points[i].z, 2));

		PointT proj_p;
		proj_p.x = cloud->points[i].x * s.radius / d + s.center_x;
		proj_p.y = cloud->points点云处理技术之PCL滤波器——参数化模型(投影点云,pcl::ProjectInliers)

PCL系列——三维重构之贪婪三角投影算法

隧道点云处理:投影边界提取(Boundary Estimation)

点云滤波相关

OpenLayers中的球面墨卡托投影

使用全景创建 360° x 180° 球面投影