目录
一、概述
1.1原理
1.2实现步骤
1.3应用场景
二、代码实现
2.1关键函数
2.1.1 生成点云数据
2.1.2 模型滤波函数
2.1.3 可视化函数
2.2完整代码
三、实现效果
PCL点云算法汇总及实战案例汇总的目录地址链接:
PCL点云算法与项目实战案例汇总(长期更新)
一、概述
模型点云滤波 是通过基于特定几何形状的模型(例如球体、平面等)来识别点云中符合该模型的点,并将它们从点云中提取出来或者移除。这种滤波技术广泛应用于点云数据的分割、去噪和特征提取等任务。
1.1原理
通过预设几何模型(如球体、平面等),在点云数据中搜索与该模型拟合度高的点,并将其从点云中提取出来或过滤掉。具体的滤波过程依赖于模型系数以及距离阈值,以确保提取的点符合指定的几何特征。
1.2实现步骤
- 生成包含噪声和球体的模拟点云数据。
- 定义球体模型,并设定模型参数(如球心和半径)。
- 使用 pcl::ModelOutlierRemoval 对点云数据进行模型滤波,提取符合球体模型的点云。
- 可视化原始点云与滤波后的点云对比。
1.3应用场景
- 几何特征提取:从点云数据中提取特定几何形状(如平面、球体等)。
- 去除噪声点:移除不符合模型的噪声点。
- 点云分割:将点云划分为符合模型的点和不符合模型的点。
二、代码实现
2.1关键函数
2.1.1 生成点云数据
生成包含噪声点和球体点的模拟点云数据
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>// 生成噪声点和球体点的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr generatePointCloud(int noise_size, int sphere_size)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);cloud->width = noise_size + sphere_size;cloud->height = 1;cloud->points.resize(cloud->width * cloud->height);// 生成噪声点for (size_t i = 0; i < noise_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);}// 生成球体点double rand_x1 = 1, rand_x2 = 1;for (size_t i = noise_size; i < noise_size + sphere_size; ++i){while (pow(rand_x1, 2) + pow(rand_x2, 2) >= 1){rand_x1 = (rand() % 100) / (50.0f) - 1;rand_x2 = (rand() % 100) / (50.0f) - 1;}double pre_calc = sqrt(1 - pow(rand_x1, 2) - pow(rand_x2, 2));cloud->points[i].x = 2 * rand_x1 * pre_calc;cloud->points[i].y = 2 * rand_x2 * pre_calc;cloud->points[i].z = 1 - 2 * (pow(rand_x1, 2) + pow(rand_x2, 2));rand_x1 = 1;rand_x2 = 1;}return cloud;
}
2.1.2 模型滤波函数
根据定义的球体模型,对点云数据进行模型滤波,提取符合球体模型的点。
#include <pcl/filters/model_outlier_removal.h>
#include <pcl/model_coefficients.h>// 对点云进行模型滤波,提取符合球体模型的点
pcl::PointCloud<pcl::PointXYZ>::Ptr applyModelFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{pcl::ModelCoefficients sphere_coeff;sphere_coeff.values.resize(4); // 定义球体模型参数sphere_coeff.values[0] = 0; // 球心的 x 坐标sphere_coeff.values[1] = 0; // 球心的 y 坐标sphere_coeff.values[2] = 0; // 球心的 z 坐标sphere_coeff.values[3] = 1; // 球体的半径pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);pcl::ModelOutlierRemoval<pcl::PointXYZ> filter;filter.setModelCoefficients(sphere_coeff); // 设置球体模型参数filter.setThreshold(0.05); // 设置距离阈值filter.setModelType(pcl::SACMODEL_SPHERE); // 设置模型类型为球体filter.setInputCloud(cloud);filter.filter(*cloud_filtered); // 滤波操作return cloud_filtered;
}
2.1.3 可视化函数
#include <pcl/visualization/pcl_visualizer.h>// 可视化原始点云和滤波后的点云
void visualizePointClouds(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, // 原始点云pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud // 滤波后的点云
)
{pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Model Filter Viewer"));int vp_1, vp_2;viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1); // 创建左侧窗口viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1); // 设置白色背景viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(cloud, 255, 0, 0); // 原始点云红色viewer->addPointCloud(cloud, cloud_color, "original_cloud", vp_1);viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2); // 创建右侧窗口viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2); // 浅灰色背景viewer->addText("Filtered PointCloud", 10, 10, "vp2_text", vp_2);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> filtered_color(filtered_cloud, 0, 255, 0); // 滤波点云绿色viewer->addPointCloud(filtered_cloud, filtered_color, "filtered_cloud", vp_2);viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud", vp_1);viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "filtered_cloud", vp_2);while (!viewer->wasStopped()){viewer->spinOnce(100);}
}
2.2完整代码
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/model_outlier_removal.h>
#include <pcl/visualization/pcl_visualizer.h>// 生成包含噪声和球体点的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr generatePointCloud(int noise_size, int sphere_size)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);cloud->width = noise_size + sphere_size;cloud->height = 1;cloud->points.resize(cloud->width * cloud->height);// 生成噪声点for (size_t i = 0; i < noise_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);}// 生成球体点double rand_x1 = 1, rand_x2 = 1;for (size_t i = noise_size; i < noise_size + sphere_size; ++i){while (pow(rand_x1, 2) + pow(rand_x2, 2) >= 1){rand_x1 = (rand() % 100) / (50.0f) - 1;rand_x2 = (rand() % 100) / (50.0f) - 1;}double pre_calc = sqrt(1 - pow(rand_x1, 2) - pow(rand_x2, 2));cloud->points[i].x = 2 * rand_x1 * pre_calc;cloud->points[i].y = 2 * rand_x2 * pre_calc;cloud->points[i].z = 1 - 2 * (pow(rand_x1, 2) + pow(rand_x2, 2));rand_x1 = 1;rand_x2 = 1;}return cloud;
}// 对点云进行模型滤波,提取符合球体模型的点
pcl::PointCloud<pcl::PointXYZ>::Ptr applyModelFilter(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{pcl::ModelCoefficients sphere_coeff;sphere_coeff.values.resize(4);sphere_coeff.values[0] = 0;sphere_coeff.values[1] = 0;sphere_coeff.values[2] = 0;sphere_coeff.values[3] = 1;pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);pcl::ModelOutlierRemoval<pcl::PointXYZ> filter;filter.setModelCoefficients(sphere_coeff);filter.setThreshold(0.05);filter.setModelType(pcl::SACMODEL_SPHERE);filter.setInputCloud(cloud);filter.filter(*cloud_filtered);return cloud_filtered;
}// 可视化原始点云和滤波后的点云
void visualizePointClouds(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud
)
{pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Model Filter Viewer"));int vp_1, vp_2;viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1);viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(cloud, 255, 0, 0);viewer->addPointCloud(cloud, cloud_color, "original_cloud", vp_1);viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2);viewer->addText("Filtered PointCloud", 10, 10, "vp2_text", vp_2);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> filtered_color(filtered_cloud, 0, 255, 0);viewer->addPointCloud(filtered_cloud, filtered_color, "filtered_cloud", vp_2);viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud", vp_1);viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "filtered_cloud", vp_2);while (!viewer->wasStopped()){viewer->spinOnce(100);}
}int main()
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = generatePointCloud(500, 10000); // 生成点云数据pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud = applyModelFilter(cloud); // 应用模型滤波visualizePointClouds(cloud, filtered_cloud); // 可视化原始点云和滤波后的点云return 0;
}