PCL循环分割并提取平面点云——小于阈值数量时停止
程序员文章站
2024-03-25 10:41:36
...
PCL循环分割平面点云
PCL提供了 分割点云的算法,分割的点云为平面最大的点云。下面是实现循环分割的代码
#define _USE_MATH_DEFINES
#include <math.h>//pi为M_PI
#include <iostream>
#include <string>
#include <pcl/point_types.h>
#include <pcl/io/ply_io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/PCLPointCloud2.h>
#include <pcl/visualization/cloud_viewer.h>//可视化
#include <pcl/filters/voxel_grid.h> //体素滤波相关 下采样
#include <pcl/console/time.h>//计时器
//pcl segmentation
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/segmentation/extract_clusters.h>
//按照索引提取点云
#include <pcl/filters/extract_indices.h>
//点云移动
#include <pcl/common/transforms.h>
//点云配准
#define BOOST_TYPEOF_EMULATION
#include <pcl/registration/icp.h>
这部分头文件还包含了点云与处理 和点云移动 还有点云配准
using namespace pcl;
using namespace pcl::io;
using namespace std;
int main() {
pcl::console::TicToc timer;
//读取保存的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_voxel_filter(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("iphonetest7_sample_filter.pcd", *cloud_voxel_filter) == -1) //* load the file
{
PCL_ERROR("Couldn't read file test_pcd.pcd \n");
return (-1);
}
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>);
//循环用到的
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_p(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_f(new pcl::PointCloud<pcl::PointXYZ>);
pcl::SACSegmentation<pcl::PointXYZ> seg;// 采样一致性分割对象
pcl::PointIndices::Ptr inliers(new pcl::PointIndices);//存储内点的点索引集合对象inliers
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);//创建分割时所需要的模型系数对象coefficients
seg.setOptimizeCoefficients(true);////可选择配置,设置模型系数需要优化
//必须配置,设置分割的模型类型、所用的随机参数估计方法、距离阈值、输入点云
seg.setModelType(pcl::SACMODEL_PLANE);//所提取目标模型的属性 分割平面
seg.setMethodType(pcl::SAC_RANSAC);//ransac法
seg.setMaxIterations(100);// 最大迭代次数
seg.setDistanceThreshold(0.5);//查询点到目标模型的距离阈值
//*******提取表面
pcl::ExtractIndices<pcl::PointXYZ> extract;
int i = 0, nr_points = (int)cloud_voxel_filter->points.size();
//为了处理点云中包含多个模型,在一个循环中执行该过程,
//并在每次模型被提取后,我们保存剩余的点,进行迭代;
//模型内点通过分割过程获取;
//当还有30%原始点云数据时退出循环
while (cloud_voxel_filter->points.size() > 0.2 * nr_points)
{
cout << "model points before segt" << i << "is" << cloud_voxel_filter->points.size() << endl;
// Segment the largest planar component from the remaining cloud
seg.setInputCloud(cloud_voxel_filter);
//引发分割实现,并存储分割结果到点集合inliers及存储平面模型的系数coefficients
seg.segment(*inliers, *coefficients);
if (inliers->indices.size() == 0)
{
std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
break;
}
// 分离内层
extract.setInputCloud(cloud_voxel_filter);
extract.setIndices(inliers);
extract.setNegative(false);
extract.filter(*cloud_p);
std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl;
std::stringstream ss;
ss << "cloud_plane" << i << ".pcd";
pcl::io::savePCDFile<pcl::PointXYZ>(ss.str(), *cloud_p);
// 创建滤波器对象
extract.setNegative(true);
extract.filter(*cloud_f);
cloud_voxel_filter.swap(cloud_f);
i++;
}
return 0;
}
上一篇: PCL点云分割---平面模型分割
下一篇: 视觉SLAM:生成点云部分学习