7.pcl滤波(一)
文章目录
- 直通滤波
- 体素滤波(下采样)
- 均匀采样滤波
- 统计滤波器
- 半径滤波
- 条件滤波器
直通滤波
#include <pcl/filters/passthrough.h>
// Create the filtering object
pcl::PassThrough<pcl::PointXYZ> pass; // 声明直通滤波
pass.setInputCloud(cloud); // 传入点云数据
pass.setFilterFieldName("z"); // 设置操作的坐标轴
pass.setFilterLimits(0.0, 3.0); // 设置坐标范围
pass.setFilterLimitsNegative(true); // 保留数据函数
pass.filter(*cloud_filtered); // 进行滤波输出
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/passthrough.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <thread> // std::this_thread::sleep_for
#include <chrono> // std::chrono::millisecondsint main(int argc, char** argv)
{// 创建点云对象pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);// 加载点云文件if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:/PCL/cloud/bunny.pcd", *cloud) == -1) {PCL_ERROR("Couldn't read file bunny.pcd \n");return (-1);}// 创建并配置直通滤波器pcl::PassThrough<pcl::PointXYZ> pass;pass.setInputCloud(cloud);pass.setFilterFieldName("z");pass.setFilterLimits(0.0, 1.0); // 设置Z轴范围pass.filter(*cloud_filtered);// 可视化设置pcl::visualization::PCLVisualizer viewer("PCL Visualizer");// 定义两个视图int v1(0), v2(1);viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1); // 左边显示原始点云viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2); // 右边显示滤波后的点云// 添加原始点云到视图pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color_original(cloud, 0, 255, 0); // 绿色viewer.addPointCloud<pcl::PointXYZ>(cloud, single_color_original, "sample cloud original", v1);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud original");// 添加滤波后的点云到视图pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color_filtered(cloud_filtered, 255, 0, 0); // 红色viewer.addPointCloud<pcl::PointXYZ>(cloud_filtered, single_color_filtered, "sample cloud filtered", v2);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud filtered");// 设置背景颜色viewer.setBackgroundColor(0, 0, 0, v1);viewer.setBackgroundColor(0, 0, 0, v2);// 主循环while (!viewer.wasStopped()){viewer.spinOnce(100);std::this_thread::sleep_for(std::chrono::milliseconds(100));}return 0;
}
体素滤波(下采样)
体素滤波(Voxel Grid Filter)是点云处理中一种常用的下采样方法,通过将三维空间划分为规则的体素网格,并用每个体素网格内的点集的一个代表点(通常是质心)来近似表示该体素内的所有点,从而减少数据量并降低计算复杂度
#include <pcl/filters/voxel_grid.h>pcl::VoxelGrid<pcl::PointXYZ> vg; //创建滤波器对象vg.setInputCloud(cloud); //设置待滤波点云vg.setLeafSize(0.05f, 0.05f, 0.05f); //设置体素大小vg.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <thread>int main(int argc, char** argv)
{// 创建点云对象pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);// 加载点云文件if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:/PCL/cloud/bunny.pcd", *cloud) == -1) {PCL_ERROR("Couldn't read file input.pcd \n");return (-1);}std::cerr << "Cloud before filtering: " << std::endl;std::cerr << *cloud << std::endl;// 创建并配置体素滤波器pcl::VoxelGrid<pcl::PointXYZ> sor;sor.setInputCloud(cloud);sor.setLeafSize(0.01f, 0.01f, 0.01f); // 设置体素大小为1cm*1cm*1cmsor.filter(*cloud_filtered);std::cerr << "Cloud after filtering: " << std::endl;std::cerr << *cloud_filtered << std::endl;// 可视化设置pcl::visualization::PCLVisualizer viewer("PCL Visualizer");// 定义两个视图int v1(0), v2(1);viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1); // 左边显示原始点云viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2); // 右边显示滤波后的点云// 添加原始点云到视图pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color_original(cloud, 0, 255, 0); // 绿色viewer.addPointCloud<pcl::PointXYZ>(cloud, single_color_original, "sample cloud original", v1);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud original");// 添加滤波后的点云到视图pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color_filtered(cloud_filtered, 255, 0, 0); // 红色viewer.addPointCloud<pcl::PointXYZ>(cloud_filtered, single_color_filtered, "sample cloud filtered", v2);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud filtered");// 设置背景颜色viewer.setBackgroundColor(0, 0, 0, v1);viewer.setBackgroundColor(0, 0, 0, v2);// 主循环while (!viewer.wasStopped()){viewer.spinOnce(100);std::this_thread::sleep_for(std::chrono::milliseconds(100));}return 0;
}
均匀采样滤波
pcl::UniformSampling 不是随机采样,而是一种基于体素空间下采样的均匀化方法。它通过在点云空间中构建一个三维体素网格,然后在每个非空体素中最多保留一个点(通常是该体素内第一个被处理的点),从而实现空间分布更均匀的下采样。
#include <pcl/keypoints/uniform_sampling.h>pcl::UniformSampling<pcl::PointXYZ> us; //创建滤波器对象us.setInputCloud(cloud); //设置待滤波点云us.setRadiusSearch(0.05f); //设置滤波球体半径us.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/uniform_sampling.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <thread>
#include <chrono>int main(int argc, char** argv)
{// 创建点云对象pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);// 加载点云文件if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:/PCL/cloud/bunny.pcd", *cloud) == -1){PCL_ERROR("Couldn't read file input.pcd \n");return (-1);}std::cerr << "Points before filtering: " << cloud->size() << std::endl;// 创建 UniformSampling 滤波器对象pcl::UniformSampling<pcl::PointXYZ> us;us.setInputCloud(cloud);us.setRadiusSearch(0.01); // 设置采样半径(即“体素”直径),单位:米us.filter(*cloud_filtered);std::cerr << "Points after filtering: " << cloud_filtered->size() << std::endl;// ================== 可视化 ==================pcl::visualization::PCLVisualizer viewer("Uniform Sampling - Before and After");int v1(0), v2(1);viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1);viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);// 原始点云(绿色)pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> green(cloud, 0, 255, 0);viewer.addPointCloud(cloud, green, "original", v1);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "original");// 滤波后点云(红色)pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> red(cloud_filtered, 255, 0, 0);viewer.addPointCloud(cloud_filtered, red, "uniform_sampled", v2);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "uniform_sampled");viewer.setBackgroundColor(0, 0, 0);viewer.addText("Original", 10, 10, "v1_text", v1);viewer.addText("Uniform Sampling", 10, 10, "v2_text", v2);while (!viewer.wasStopped()){viewer.spinOnce(100);std::this_thread::sleep_for(std::chrono::milliseconds(100));}return 0;
}
统计滤波器
统计滤波(Statistical Outlier Removal, 简称 SOR)是点云处理中一种常用的去噪方法,用于移除离群点(outliers)。它基于这样一个假设:正常点周围的点密度较高,而离群点周围的邻居较少或距离较远,点云存在“毛刺”、“飞点”、“漂浮点”等噪声,统计滤波是一个非常推荐的预处理步骤。
#include <pcl/filters/statistical_outlier_removal.h>pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; //创建滤波器对象sor.setInputCloud(cloud); //设置待滤波点云sor.setMeanK(50); //设置查询点近邻点的个数sor.setStddevMulThresh(1.0); //设置标准差乘数,来计算是否为离群点的阈值//sor.setNegative(true); //默认false,保存内点;true,保存滤掉的离群点sor.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <thread>
#include <chrono>int main(int argc, char** argv)
{// 创建点云对象pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);// 加载点云文件if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:/PCL/cloud/bunny.pcd", *cloud) == -1){PCL_ERROR("Couldn't read file input.pcd \n");return (-1);}std::cerr << "Points before filtering: " << cloud->size() << std::endl;// 创建统计滤波器pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;sor.setInputCloud(cloud);sor.setMeanK(20); // 设置每个点查询的最近邻点数sor.setStddevMulThresh(1.0); // 设置标准差倍数阈值sor.filter(*cloud_filtered);std::cerr << "Points after filtering: " << cloud_filtered->size() << std::endl;// ================== 可视化 ==================pcl::visualization::PCLVisualizer viewer("Statistical Outlier Removal");int v1(0), v2(1);viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1);viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);// 原始点云(绿色)pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> green(cloud, 0, 255, 0);viewer.addPointCloud(cloud, green, "original", v1);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "original");// 滤波后点云(蓝色)pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> blue(cloud_filtered, 0, 0, 255);viewer.addPointCloud(cloud_filtered, blue, "stat_filtered", v2);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "stat_filtered");viewer.setBackgroundColor(0, 0, 0);viewer.addText("Original", 10, 10, "v1_text", v1);viewer.addText("After SOR", 10, 10, "v2_text", v2);// 主循环while (!viewer.wasStopped()){viewer.spinOnce(100);std::this_thread::sleep_for(std::chrono::milliseconds(100));}return 0;
}
半径滤波
半径滤波(Radius Outlier Removal, ROR)是点云处理中用于去除离群点的另一种方法。与统计滤波不同,它通过检查每个点周围指定半径内的邻居数量来判断该点是否为离群点。如果某个点在其指定半径内拥有的邻居数量少于设定的阈值,则认为该点为离群点并将其移除。
#include <pcl/filters/radius_outlier_removal.h>pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror; //创建滤波器对象ror.setInputCloud(cloud); //设置待滤波点云ror.setRadiusSearch(0.02); //设置查询点的半径范围ror.setMinNeighborsInRadius(5); //设置判断是否为离群点的阈值,即半径内至少包括的点数//ror.setNegative(true); //默认false,保存内点;true,保存滤掉的外点ror.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <thread>
#include <chrono>int main(int argc, char** argv)
{// 创建点云对象pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);// 加载点云文件if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:/PCL/cloud/bunny.pcd", *cloud) == -1){PCL_ERROR("Couldn't read file input.pcd \n");return (-1);}std::cerr << "Points before filtering: " << cloud->size() << std::endl;// 创建半径滤波器pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror;ror.setInputCloud(cloud);ror.setRadiusSearch(0.05); // 设置搜索半径为 5cmror.setMinNeighborsInRadius(2); // 设置在给定半径内至少需要的邻居数为 2ror.filter(*cloud_filtered);std::cerr << "Points after filtering: " << cloud_filtered->size() << std::endl;// ================== 可视化 ==================pcl::visualization::PCLVisualizer viewer("Radius Outlier Removal");int v1(0), v2(1);viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1);viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);// 原始点云(绿色)pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> green(cloud, 0, 255, 0);viewer.addPointCloud(cloud, green, "original", v1);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "original");// 滤波后点云(蓝色)pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> blue(cloud_filtered, 0, 0, 255);viewer.addPointCloud(cloud_filtered, blue, "radius_filtered", v2);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "radius_filtered");viewer.setBackgroundColor(0, 0, 0);viewer.addText("Original", 10, 10, "v1_text", v1);viewer.addText("After Radius Filter", 10, 10, "v2_text", v2);// 主循环while (!viewer.wasStopped()){viewer.spinOnce(100);std::this_thread::sleep_for(std::chrono::milliseconds(100));}return 0;
}
条件滤波器
#include <pcl/filters/conditional_removal.h>/*创建条件限定下的滤波器*/pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());//创建条件定义对象range_cond//为条件定义对象添加比较算子range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(newpcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::GT, -0.1)));//添加在x字段上大于 -0.1 的比较算子range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(newpcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::LT, 1.0)));//添加在x字段上小于 1.0 的比较算子pcl::ConditionalRemoval<pcl::PointXYZ> cr; //创建滤波器对象cr.setCondition(range_cond); //用条件定义对象初始化cr.setInputCloud(cloud); //设置待滤波点云//cr.setKeepOrganized(true); //设置保持点云的结构//cr.setUserFilterValue(5); //将过滤掉的点用(5,5,5)代替cr.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/conditional_removal.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <thread>
int main(int argc, char** argv)
{// 创建点云对象pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);// 加载点云文件if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:/PCL/cloud/bunny.pcd", *cloud) == -1){PCL_ERROR("Couldn't read file input.pcd \n");return (-1);}std::cerr << "Points before filtering: " << cloud->size() << std::endl;// 创建条件滤波器pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 0.0))); // Z > 0.0range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, 1.0))); // Z < 1.0// 构建滤波器并应用条件pcl::ConditionalRemoval<pcl::PointXYZ> condrem;condrem.setCondition(range_cond);condrem.setInputCloud(cloud);condrem.setKeepOrganized(false); // 如果你的点云是有序的,请设置为true以保持结构化输出condrem.filter(*cloud_filtered);std::cerr << "Points after filtering: " << cloud_filtered->size() << std::endl;// ================== 可视化 ==================pcl::visualization::PCLVisualizer viewer("Conditional Removal");int v1(0), v2(1);viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1);viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);// 原始点云(绿色)pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> green(cloud, 0, 255, 0);viewer.addPointCloud(cloud, green, "original", v1);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "original");// 滤波后点云(蓝色)pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> blue(cloud_filtered, 0, 0, 255);viewer.addPointCloud(cloud_filtered, blue, "conditional_filtered", v2);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "conditional_filtered");viewer.setBackgroundColor(0, 0, 0);viewer.addText("Original", 10, 10, "v1_text", v1);viewer.addText("After Conditional Filter", 10, 10, "v2_text", v2);// 主循环while (!viewer.wasStopped()){viewer.spinOnce(100);std::this_thread::sleep_for(std::chrono::milliseconds(100));}return 0;
}