一个可视化函数
void viewPort2(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered)
{
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("滤波前后对比"));
/*-----视口1-----*/
int v1(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1); //设置第一个视口在X轴、Y轴的最小值、最大值,取值在0-1之间
viewer->setBackgroundColor(0, 0, 0, v1); //设置背景颜色,0-1,默认黑色(0,0,0)
viewer->addText("befor_filtered", 10, 10, "v1_text", v1);
viewer->addPointCloud<pcl::PointXYZ>(inputCloud, "befor_filtered_cloud", v1);
/*-----视口2-----*/
int v2(0);
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2);
viewer->setBackgroundColor(0.3, 0.3, 0.3, v2);
viewer->addText("after_filtered", 10, 10, "v2_text", v2);
viewer->addPointCloud<pcl::PointXYZ>(cloud_filtered, "after_filtered_cloud", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "befor_filtered_cloud", v1);
//设置点云的颜色为红色
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "befor_filtered_cloud", v1);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "after_filtered_cloud", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "after_filtered_cloud", v2);
viewer->resetCamera();
viewer->spin();
while (!viewer->wasStopped())
{
viewer->spinOnce();
}
}
1、pcl::PassThrough直通滤波
1.1 所需头文件
#include <pcl/filters/passthrough.h>
1.2 代码实现
流程:读入点云->创建直通滤波器->设置滤波字段->执行->保存并可视化
/*
* 接对点云的X、Y、Z轴的点云坐标约束来进行滤波,可以约束只在Z轴,或者XYZ三个坐标轴共同约束来达到点云滤波效果。
* 算法原理:对指定的某一维度进行滤波,去掉用户指定字段范围内(或外)的点
*/
void pcdPassthrough(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_z(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_y(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
cout << "<-正在进行直通滤波->" << endl;
pcl::PassThrough<pcl::PointXYZ> pt; // 创建直通滤波器对象
pt.setInputCloud(inputCloud); //设置输入点云
pt.setFilterFieldName("z"); //设置滤波所需字段z
pt.setFilterLimits(-3, 10); //设置y字段过滤范围
pt.setFilterLimitsNegative(true); //默认false,保留范围内的点云;true,保存范围外的点云
pt.filter(*cloud_filtered_z); //执行滤波,保存滤波后点云
pt.setFilterFieldName("y"); //设置滤波所需字段y
pt.setFilterLimits(-3, 10); //设置y字段过滤范围
pt.setFilterLimitsNegative(true); //默认false,保留范围内的点云;true,保存范围外的点云
pt.filter(*cloud_filtered_y); //执行滤波,保存滤波后点云
///保存滤波后点云
cout << "<-正在保存点云->\n";
if (cloud_filtered_z->empty() || cloud_filtered_y->empty())
{
PCL_ERROR("保存点云为空!\n");
return ;
}
else
{
pcl::io::savePCDFileBinary("../pcdFile//z_cloud_filtered.pcd", *cloud_filtered_z);
cout << "\t\t<字段z滤波后点云信息>\n" << *cloud_filtered_z << endl;
pcl::io::savePCDFileBinary("../pcdFile//y_cloud_filtered.pcd", *cloud_filtered_y);
cout << "\t\t<字段y滤波后点云信息>\n" << *cloud_filtered_y << endl;
}
//================================= 滤波前后对比可视化 =================================
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("滤波前后对比"));
/*-----视口1-----*/
int v1(0);
viewer->createViewPort(0.0, 0.0, 0.333, 1.0, v1); //设置第一个视口在X轴、Y轴的最小值、最大值,取值在0-1之间
viewer->setBackgroundColor(0, 0, 0, v1); //设置背景颜色,0-1,默认黑色(0,0,0)
viewer->addText("befor_filtered", 10, 10, "v1_text", v1);
viewer->addPointCloud<pcl::PointXYZ>(inputCloud, "befor_filtered_cloud", v1);
/*-----视口2-----*/
int v2(0);
viewer->createViewPort(0.3, 0.0, 0.666, 1.0, v2);
viewer->setBackgroundColor(0.3, 0.3, 0.3, v2);
viewer->addText("z_after_filtered", 10, 10, "v2_text", v2);
viewer->addPointCloud<pcl::PointXYZ>(cloud_filtered_z, "z_after_filtered_cloud", v2);
/*-----视口3-----*/
int v3(0);
viewer->createViewPort(0.666, 0.0, 1.0, 1.0, v3);
viewer->setBackgroundColor(0.4, 0.3, 0.5, v3);
viewer->addText("y_after_filtered", 10, 10, "v3_text", v3);
viewer->addPointCloud<pcl::PointXYZ>(cloud_filtered_y, "y_after_filtered_cloud", v3);
/*-----设置相关属性-----*/
//设置点云的点大小为 2 个单位。这将使点云中的每个点显示为较大的点。
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "befor_filtered_cloud", v1);
//设置点云的颜色为红色
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "befor_filtered_cloud", v1);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "z_after_filtered_cloud", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "z_after_filtered_cloud", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "y_after_filtered_cloud", v3);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.21, 0.35, 0.15, "y_after_filtered_cloud", v3);
viewer->resetCamera();
viewer->spin();
while (!viewer->wasStopped())
{
viewer->spinOnce();
}
}
1.3 输出结果:
2、体素滤波pcl::VoxelGrid
2.1 所需要的头文件
#include <pcl/filters/voxel_grid.h>
2.2 代码实现
/*
*创建一个三维体素栅格->在每个体素(三维立方体)里面,求取该立方体内的所有点云重心点来代表这个立方体的表示,以此达到下采样的目的。
*/
void pcdVoxelGrid(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
cout << "<-正在体素下采样->" << endl;
pcl::VoxelGrid<pcl::PointXYZ> vg; //创建滤波器对象
vg.setInputCloud(inputCloud); //设置待滤波点云
vg.setLeafSize(0.5f, 0.6f, 0.6f); //设置体素大小
vg.filter(*cloud_filtered); //执行滤波,保存滤波结果在cloud_filtered
cout << "\t\t<滤波后的点云信息>\n" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
}
2.3 输出结果
3、均匀采样UniformSampling
3.1 所需要的头文件
#include <pcl/keypoints/uniform_sampling.h>
3.2 代码实现
/*
* 对点云数据创建一个滤波球体,然后在每个体素保留一个最接近体素中心的点,代替体素中所有点。
*/
void pcdUniformSampling(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
cout << "<-均匀下采样->" << endl;
pcl::UniformSampling<pcl::PointXYZ> us; //创建均匀采样滤波器对象
us.setInputCloud(inputCloud); //设置待滤波点云
us.setRadiusSearch(3.0f); //设置滤波球半径
us.filter(*cloud_filtered); //执行滤波,保存滤波结果在cloud_filtered
cout << "\t\t<滤波后的点云信息>\n" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
}
3.3 输出结果
4、统计滤波
4.1 所需头文件
#include <pcl/filters/statistical_outlier_removal.h>
4.2 代码实现
/*
对每一点的邻域进行统计分析,基于点到所有邻近点的距离分布特征,过滤掉一些不满足要求的离群点。
弊端:
是对于离群点具有小范围聚集的情况,算法为保证过滤效果需要更大的耗时;二是在过滤离群点的同时,会把边界点过滤。
*/
void pcdSOR(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud) {
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
cout << "<-统计滤波->" << endl;
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; //创建统计滤波器对象
sor.setInputCloud(inputCloud); //设置待滤波点云
sor.setMeanK(20); //设置查询点近邻点的个数
sor.setNegative(true);//默认false,保存内点;true,保存滤掉的离群点
sor.setStddevMulThresh(0.1);//设置标准差乘数,来计算是否为离群点的阈值
sor.filter(*cloud_filtered); //执行滤波,保存滤波结果在cloud_filtered
cout << "\t\t<滤波后的点云信息>\n" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
}
4.3 输出结果
主函数
int main()
{
// 输入点云 源点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
///读入点云
cout << "<-正在读入点云->" << endl;
string cloudPath = "../pcdFile//001.pcd";
if (pcl::io::loadPCDFile(cloudPath, *cloud) < 0)
{
PCL_ERROR("点云文件不存在!\n");
system("pause");
return -1;
}
cout << "\t\t<读入点云信息>\n" << *cloud << endl;
//pcdVoxelGrid(cloud);
pcdSOR(cloud);
return 0;
}