目录
一、概述
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;
}