欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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点云库学习