一、简介
本小节将学习如何将点投影到一个参数化模型(例如平面或球等)。参数化模型通过一组参数来设定,对于平面来说,使用其等式形式 ax + by + cz + d = 0,在PCL中有特意存储常见模型系数的数据结构。
二、代码分析
1)首先声明了ModelCoeffcients结构和ProjectInliers滤波器对应头文件。
#include <pcl/ModelCoefficients.h>//模型系数定义头文件
#include <pcl/filters/project_inliers.h>//投影滤波类头文件
2)随后我们创建了点云结构,填充了相应的值,并将其内容打印出来:
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;
3)填充ModelCoefficients的值,本例中我们使用一个 ax + by + cz + d = 0 的平面模型,其中 a = b = d = 0,c = 1 ,换句话说,也就是X-Y平面,用户可以任意定义PCL中支持的模型(圆球、圆柱、锥型等)进行投影滤波。
// 创建一个系数为X=Y=0,Z=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;
4)创建ProjectInliers对象,并使用刚才定义好的ModelCoefficients作为投影对象的模型参数:
pcl::ProjectInliers<pcl::PointXYZ> proj;
proj.setModelType (pcl::SACMODEL_PLANE);
proj.setInputCloud (cloud);
proj.setModelCoefficients (coefficients);
proj.filter (*cloud_projected);
5)最后打印出投影后的点云:
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;
6)整体代码如下:
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/ModelCoefficients.h> //模型系数定义头文件
#include <pcl/filters/project_inliers.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>);
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;
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;
return (0);
}
三、编译结果
编译前的点云包含Z轴的点云数据,但是经过向X-Y平面进行投影后,点云的Z向数据均为0,符合程序的逻辑: