PCL 随机采样一致方法(RANSAC)分割

本文详细介绍了如何使用PCL库进行点云数据的预处理、体素滤波、随机采样一致(RANSAC)方法进行平面分割。通过RANSAC算法迭代选择内点,计算模型参数,不断优化模型,最终实现点云数据中平面的精确分割。同时,展示了C++代码实现过程,包括点云读取、统计离群点滤波、平面和圆柱体分割等步骤,以及可视化结果。
摘要由CSDN通过智能技术生成

随机采样一致方法(RANSAC)

采用迭代的方式从一组包含离群的被观测数据中估算出数学模型的参数。RANSAC算法假设数据中包含正确数据和异常数据(或称为噪声)。正确数据记为内点(inliers),异常数据记为外点(outliers)。同时RANSAC也假设,给定一组正确的数据,存在可以计算出符合这些数据的模型参数的方法。该算法核心思想就是随机性和假设性,随机性是根据正确数据出现概率去随机选取抽样数据,根据大数定律,随机性模拟可以近似得到正确结果。假设性是假设选取出的抽样数据都是正确数据,然后用这些正确数据通过问题满足的模型,去计算其他点,然后对这次结果进行一个评分。

算法流程:

1. 要得到一个直线模型,需要两个点唯一确定一个直线方程。所以第一步随机选择两个点。

2. 通过这两个点,可以计算出这两个点所表示的模型方程y=ax+b。

3. 将所有的数据点套到这个模型中计算误差。

4. 找到所有满足误差阈值的点。

5. 然后我们再重复1~4这个过程,直到达到一定迭代次数后,选出那个被支持的最多的模型,作为问题的解。

 

#include <iostream> //标准C++库中的输入输出
#include <pcl/ModelCoefficients.h>	//采样一致性模型头文件
#include <pcl/io/pcd_io.h>//pcd文件输入输出头文件
#include <pcl/point_types.h>//支持点类型头文件
#include <pcl/sample_consensus/method_types.h>//随机参数估计方法
#include <pcl/sample_consensus/model_types.h>//模型定义
#include <pcl/segmentation/sac_segmentation.h>//基于采样一致性分割的类的头文件
#include <pcl/filters/voxel_grid.h>//基于体素网格化的滤波
#include <pcl/filters/extract_indices.h>//索引提取
#include <pcl/visualization/pcl_visualizer.h>//可视化支持头文件
#include <pcl/filters/statistical_outlier_removal.h> //统计离群点
int
main(int argc, char** argv) 
{
	pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2), cloud_filtered_blob(new pcl::PCLPointCloud2);//创建指针cloud_blob cloud_filtered_blob
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>), cloud_p(new pcl::PointCloud<pcl::PointXYZ>), cloud_f(new pcl::PointCloud<pcl::PointXYZ>);
	// 填入点云数据
	pcl::PCDReader reader;//pcd读取
	reader.read("D:\\pclcode\\pcl_segmentation\\planar_segmentation\\source\\table_scene_lms400.pcd", *cloud_blob);
	std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl;
	// 创建滤波器对象:使用叶大小为1cm的下采样
	pcl::VoxelGrid<pcl::PCLPointCloud2> sor;//创建体素滤波器对象
	sor.setInputCloud(cloud_blob);//设置输入点云
	sor.setLeafSize(0.01f, 0.01f, 0.01f);//设置叶大小为1cm
	sor.filter(*cloud_filtered_blob);//执行滤波,将体素滤波(下采样)后的点云放置到cloud_filtered_blob

	std::cerr << cloud_filtered_blob->width*cloud_filtered_blob->height << std::endl;//体素滤波后cloud_filtered_blob的总点数

	// 转化为模板点云
	pcl::fromPCLPointCloud2(*cloud_filtered_blob, *cloud_filtered);//将下采样后的点云转换为PoinCloud类型
	std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;//滤波后的总点数
	// 将下采样后的数据存入磁盘
	pcl::PCDWriter writer;//pcd写操作
	writer.write<pcl::PointXYZ>("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());//创建采样一致性模型指针
	pcl::PointIndices::Ptr inliers(new pcl::PointIndices());  //创建一个PointIndices结构体指针
	// 创建分割对象
	pcl::SACSegmentation<pcl::PointXYZ> seg;//创建分割对象seg
	// 可选
	seg.setOptimizeCoefficients(true); //设置对估计的模型做优化处理
	// 必选
	seg.setModelType(pcl::SACMODEL_PLANE);//设置分割模型类别
	seg.setMethodType(pcl::SAC_RANSAC);//设置使用那个随机参数估计方法为随机样本共识
	seg.setMaxIterations(1000);//迭代次数
	seg.setDistanceThreshold(0.01);//设置是否为模型内点的距离阈值
	// 创建滤波器对象
	pcl::ExtractIndices<pcl::PointXYZ> extract;
	int i = 0, nr_points = (int)cloud_filtered->points.size();//nr_points表示原始点云数据
	// 当还多于30%原始点云数据时
	while (cloud_filtered->points.size() > 0.3 * nr_points)
	{
		// 从余下的点云中分割最大平面组成部分
		seg.setInputCloud(cloud_filtered);//设置输入点云
		seg.segment(*inliers, *coefficients);//分割点云
		if (inliers->indices.size() == 0)
		{
			std::cerr << "Could not estimate a planar model for the given dataset.(无法估计给定数据集的平面模型。)" << std::endl;
			break;
		}
		// 分离内层
		extract.setInputCloud(cloud_filtered);//设置输入点云
		extract.setIndices(inliers);//设置保留内点
		extract.setNegative(false);//判断保留内点还是反向选取,false是保留内点,true是反选
		extract.filter(*cloud_p);//执行滤波并将结果保存在cloud_p中
		std::cerr << "cloud_filtered: " << cloud_filtered->size() << std::endl;//输出提取之后剩余的

		std::cerr << "--------------------------------------------------" << std::endl;//设置屏幕分界线
		//保存
		std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl;//输出cloud_p的点数
		std::stringstream ss;//将PointCloud representing the planar component这个字符串赋值给ss
		ss << "table_scene_lms400_plane_" << i << ".pcd"; //对每一次的提取都进行了文件保存
		writer.write<pcl::PointXYZ>(ss.str(), *cloud_p, false);
		// 创建滤波器对象
		extract.setNegative(true);//提取外层
		extract.filter(*cloud_f);//将外层的提取结果保存到cloud_f
		cloud_filtered.swap(cloud_f);//经cloud_filtered与cloud_f交换


		i++;
	}

	std::cerr << "cloud_filtered: " << cloud_filtered->size() << std::endl;//输出cloud_filterd的总点数

	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_seg1(new pcl::PointCloud<pcl::PointXYZ>);//创建cloud_seg1指针
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_seg2(new pcl::PointCloud<pcl::PointXYZ>);//创建cloud_seg2指针
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_voxel(new pcl::PointCloud<pcl::PointXYZ>);//创建cloud_voxel指针

	pcl::io::loadPCDFile("table_scene_lms400_plane_0.pcd", *cloud_seg1);
	pcl::io::loadPCDFile("table_scene_lms400_plane_1.pcd", *cloud_seg2);
	pcl::io::loadPCDFile("table_scene_lms400_downsampled.pcd", *cloud_voxel);
	
	//将提取结果进行统计学滤波
	pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor1;//创建统计滤波指针
	sor1.setInputCloud(cloud_seg2);//设置输入点云cloud_seg2
	sor1.setMeanK(50);//设置考虑查询点临近个数为50
	sor1.setStddevMulThresh(1);//设置判断是否为离群点的阈值为1
	sor1.filter(*cloud_f);//执行滤波,并将结果储存在cloud_f中
	std::cerr<<cloud_f->size()<<std::endl;//输出cloud_f的总点数
  

	pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer);//创建可视化指针
	viewer->initCameraParameters();//初始化相机参数
    //设置第一个可视化窗口
	int v1(0);
	viewer->createViewPort(0, 0, 0.25, 1, v1);
	viewer->setBackgroundColor(0, 255, 255, v1);//设置背景颜色
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color1(cloud_voxel, 244, 89, 233);//设置点云颜色
	viewer->addPointCloud(cloud_voxel, color1, "cloud_voxel", v1);

	int v2(0);
	viewer->createViewPort(0.25, 0, 0.5, 1, v2);
	viewer->setBackgroundColor(125, 255, 47, v2);
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color2(cloud_seg1, 255, 20, 0);
	viewer->addPointCloud(cloud_seg1, color2, "cloud_seg1", v2); //注意id不能一样

	int v3(0);
	viewer->createViewPort(0.5, 0, 0.75, 1, v3);
	viewer->setBackgroundColor(34, 128, 0, v3);
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color3(cloud_seg2, 255, 20, 150);
	viewer->addPointCloud(cloud_seg2, color3, "cloud_seg2", v3);

	int v4(0);
	viewer->createViewPort(0.75, 0, 1, 1, v4);
	viewer->setBackgroundColor(255, 255, 255, v4);
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color4(cloud_filtered, 244, 89, 0);
	viewer->addPointCloud(cloud_filtered, color4, "cloud_statical", v4);
	viewer->addCoordinateSystem();//添加坐标系
	viewer->spin();
	return (0);
}
//PointCloud before filtering : 460400 data points.
//41049
//PointCloud after filtering : 41049 data points.
//cloud_filtered : 41049
//	--------------------------------------------------
//	PointCloud representing the planar component : 20161 data points.
//	cloud_filtered : 20888
//	--------------------------------------------------
//	PointCloud representing the planar component : 12114 data points.
//	cloud_filtered : 8774
//	11836

 

CMakeLists文件如下:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project(planar_segmentation2)

find_package(PCL 1.2 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})

link_directories(${PCL_LIBRARY_DIRS})

add_definitions(${PCL_DEFINITIONS})

add_executable (planar_segmentation planar_segmentation.cpp)

target_link_libraries (planar_segmentation ${PCL_LIBRARIES})

执行效果如下所示:

去除坐标系:viewer->addCoordinateSystem();//添加坐标系

把这行代码注释掉就可以了

 

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL)//vtk必要头文件
#include <pcl/io/pcd_io.h>//pcd文件读写输入输出
#include <pcl/point_types.h>//支持点类型头文件
#include <pcl/filters/statistical_outlier_removal.h>//统计离群点
#include <pcl/segmentation/extract_clusters.h>//欧几里得分割
#include <pcl/visualization/pcl_visualizer.h>//pcl可视化支持头文件
#include <pcl/segmentation/sac_segmentation.h>//基于采样一致性分割
#include <pcl/ModelCoefficients.h>//采样一致性模型
#include <pcl/filters/extract_indices.h>//索引提取
#include<ctime>
#include<cstdlib>//随机产生随机数
//<1>  字符串转换atof: 字符串转浮点型;atoi:字符串转整型;atol:字符串转长整型
//<2> 伪随机序列生成 rand: 产生随机数 srand:初始化随机因子,防止随机数总是固定不变
//<3> 动态内存管理calloc, malloc,realloc, free
#include <windows.h>

using namespace pcl;
using namespace std;
typedef PointXYZ PoinT;

int *rand_rgb() {//随机产生颜色
	int *rgb = new int[3];
	rgb[0] = rand() % 255;
	rgb[1] = rand() % 255;
	rgb[2] = rand() % 255;
	return rgb;
}
int main() {
	//点云文件的读取
	PointCloud<PoinT>::Ptr cloud(new PointCloud<PoinT>);//创建cloud指针
	if (io::loadPCDFile("D:\\pclcode\\pcl_segmentation\\planar_segmentation2\\source\\table_scene_lms400.pcd", *cloud) == -1)
	{
		PCL_ERROR("read false");
		return 0;
	}
	//去除噪声点
	StatisticalOutlierRemoval<PoinT>sor;//创建滤波器对象
	PointCloud<PoinT>::Ptr sor_cloud(new PointCloud<PoinT>);//创建sor_cloud指针
	sor.setMeanK(10);//设置考虑查询点临近个数为10
	sor.setInputCloud(cloud);//设置输入点云
	sor.setStddevMulThresh(0.1);//设置判读是否为离群点的阈值
	sor.filter(*sor_cloud);//执行滤波并将结果保存在sor_cloud中
	cout << sor_cloud->size() << endl;//输出sor_cloud的点数
	//平面分割(RANSAC)
	SACSegmentation<PoinT> sac;//创建一个分割器
	PointIndices::Ptr inliner(new PointIndices);//inliner表示误差能容忍的点,记录的是点云的序号
	ModelCoefficients::Ptr coefficients(new ModelCoefficients);//创建一个模型参数对象,用于记录结果
	PointCloud<PoinT>::Ptr sac_cloud(new PointCloud<PoinT>);//创建sac_cloud指针
	sac.setInputCloud(sor_cloud);//设置输入点云
	sac.setMethodType(SAC_RANSAC);//分割方法,随机采样法
	sac.setModelType(SACMODEL_PLANE);//Mondatory设置目标几何形状
	sac.setMaxIterations(100);//设置最大迭代次数
	sac.setDistanceThreshold(0.01);//设置误差容忍范围
	//提取平面(展示并输出)
	PointCloud<PoinT>::Ptr ext_cloud(new PointCloud<PoinT>);//创建ext_cloud指针
	PointCloud<PoinT>::Ptr ext_cloud_rest(new PointCloud<PoinT>);//创建ext_cloud_rest指针
	visualization::PCLVisualizer::Ptr viewer(new visualization::PCLVisualizer("平面分割"));//屏幕可视化

	int i = sor_cloud->size(), j = 0;//将sor_cloud的点数赋值给i
	ExtractIndices<PoinT>ext;//创建提取对象ext
	srand((unsigned)time(NULL));//刷新时间的种子节点需要放在循环体外面
	while (sor_cloud->size() > i*0.0)//当提取的点数小于总数的3/10时,跳出循环
	{
		ext.setInputCloud(sor_cloud);
		sac.segment(*inliner, *coefficients);//分割点云,得到参数
		if (inliner->indices.size() == 0)
		{
			break;
		}
		//按照索引提取点云
		ext.setIndices(inliner);//设置保留内点
		ext.setNegative(false);//判断保留内点还是反向选取,false是保留内点,true是反选
		ext.filter(*ext_cloud);//执行滤波,并将结果保存在ext_cloud中
		ext.setNegative(true);//true是反选,反向选取
		ext.filter(*ext_cloud_rest);//执行滤波并将结果保存在ext_cloud_rest中
		
		*sor_cloud = *ext_cloud_rest;//将ext_cloud_rest赋值给sor_cloud
		stringstream ss;//将字符串赋值给ss
		ss << "D:\\pclcode\\pcl_segmentation\\planar_segmentation2\\source\\" << "ext_plane_clouds" << j << ".pcd";//路径加文件名和后缀
		io::savePCDFileASCII(ss.str(), *ext_cloud);//提取的平面点云写出
		int *rgb = rand_rgb();//随机生成0-255的颜色值
		visualization::PointCloudColorHandlerCustom<PoinT>rgb1(ext_cloud, rgb[0], rgb[1], rgb[2]);//提取的平面不同彩色展示
		delete[]rgb;//删除色彩信息
		viewer->addPointCloud(ext_cloud, rgb1, ss.str());//添加坐标系
		j++;
	}
	viewer->spin();
	return 0;

 CMakeLists文件按照上面的格式来修改一下就可以了!!!

执行效果如下所示:

 

 

 

#include <pcl/ModelCoefficients.h>//采样一致性模型头文件
#include <pcl/io/pcd_io.h>//pcd文件输入输出头文件
#include <pcl/point_types.h>//支持点类型头文件
#include <pcl/filters/extract_indices.h>//索引提取
#include <pcl/filters/passthrough.h>//直通滤波器
#include <pcl/features/normal_3d.h>//法线特征估计
#include <pcl/sample_consensus/method_types.h>//随即参数估计方法
#include <pcl/sample_consensus/model_types.h>//模型定义
#include <pcl/segmentation/sac_segmentation.h>//基于采样一致性分割的类头文件
#include <pcl/visualization/pcl_visualizer.h>//可视化相关头文件
typedef pcl::PointXYZ PointT;
int
main(int argc, char** argv)
{
	pcl::PCDReader reader;//点云读入对象
	pcl::PassThrough<PointT> pass;//直通滤波器对象
	pcl::NormalEstimation<PointT, pcl::Normal> ne;//法线估计对象
	pcl::SACSegmentationFromNormals<PointT, pcl::Normal> seg; //分割对象
	pcl::PCDWriter writer;//写对象
	pcl::ExtractIndices<PointT> extract;//点提取对象
	pcl::ExtractIndices<pcl::Normal> extract_normals;//法线提取对象
	pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>());//搜索方式对象
	// 指针创建
	pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);//创建cloud指针
	pcl::PointCloud<PointT>::Ptr cloud_filtered(new pcl::PointCloud<PointT>);//创建cloud_filtered指针
	pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);//创建cloud_normals指针
	pcl::PointCloud<PointT>::Ptr cloud_filtered2(new pcl::PointCloud<PointT>);//cloud_filtered2指针
	pcl::PointCloud<pcl::Normal>::Ptr cloud_normals2(new pcl::PointCloud<pcl::Normal>);//创建cloud_normals指针
	pcl::ModelCoefficients::Ptr coefficients_plane(new pcl::ModelCoefficients), coefficients_cylinder(new pcl::ModelCoefficients);//创建分离平面和分离圆柱面的指针
	pcl::PointIndices::Ptr inliers_plane(new pcl::PointIndices), inliers_cylinder(new pcl::PointIndices);//一个指向索引的指针
	// 
	reader.read("D:\\pclcode\\pcl_segmentation\\cylinder_segmentation\\source\\table_scene_mug_stereo_textured.pcd", *cloud);
	std::cerr << "PointCloud has: " << cloud->points.size() << " data points." << std::endl;//输出点云共有多少点
	// 创建直通滤波器对点云机型滤波
	//对cloud的z fields进行滤波,剔除0~1.5之外的点
	pass.setInputCloud(cloud);//设置输入点云
	pass.setFilterFieldName("z");//设置滤波的field
	pass.setFilterLimits(0, 1.5);//滤波范围(0,1.5)
	pass.filter(*cloud_filtered);//执行滤波,并将滤波结果保存在cloud_filtered中
	std::cerr << "PointCloud after filtering has: " << cloud_filtered->points.size() << " data points." << std::endl;//输出直通滤波后点云的总点数
	//点云法线估计
	ne.setSearchMethod(tree);//搜索方式
	ne.setInputCloud(cloud_filtered);//输入点云为直通滤波器的结果
	ne.setKSearch(50);//选择最近邻的50个点进行法线估计
	ne.compute(*cloud_normals);//法线的计算结果存放至cloud_normals
	// 创建平面模型分割对象以及选择参数
	seg.setOptimizeCoefficients(true);//选择是否优化系数
	seg.setModelType(pcl::SACMODEL_NORMAL_PLANE);//Mondatory设置目标几何形状 使用附加约束确定平面模型
	seg.setNormalDistanceWeight(0.1);//设置表面法线权重系数为0.1
	seg.setMethodType(pcl::SAC_RANSAC);//设置分割方法为随采样法
	seg.setMaxIterations(100);//设置最大迭代次数为100
	seg.setDistanceThreshold(0.03);//设置内点到模型的距离允许最大值
	seg.setInputCloud(cloud_filtered);//输入的点云
	seg.setInputNormals(cloud_normals);//输入的法线
	// Obtain the plane inliers and coefficients
	seg.segment(*inliers_plane, *coefficients_plane);//得到平面内点和平面的4个系数
	std::cerr << "Plane coefficients: " << *coefficients_plane << std::endl;//输出平面
	//从输入点云中分离内点
	//提取出平面内点
	extract.setInputCloud(cloud_filtered);//设置输入点云
	extract.setIndices(inliers_plane);//分离平面内点
	extract.setNegative(false);//false代表保留内点
	// 将平面内点写入磁盘
	pcl::PointCloud<PointT>::Ptr cloud_plane(new pcl::PointCloud<PointT>());//创建cloud_plane指针
	extract.filter(*cloud_plane);//将平面点提取至clodu_plane
	std::cerr << "PointCloud representing the planar component: " << cloud_plane->points.size() << " data points." << std::endl;//输出提取平面的总点数
	writer.write("table_scene_mug_stereo_textured_plane.pcd", *cloud_plane, false);//写入点云文件
	// 移除内点平面,分离剩余点云
	extract.setNegative(true);//提取平面点之外的点,继续处理
	extract.filter(*cloud_filtered2);//平面点
	extract_normals.setNegative(true);
	extract_normals.setInputCloud(cloud_normals);//设置输入点云
	extract_normals.setIndices(inliers_plane);
	extract_normals.filter(*cloud_normals2);
	//创建圆柱面分割对象,并选择参数
	seg.setOptimizeCoefficients(true);选择是否优化系数
	seg.setModelType(pcl::SACMODEL_CYLINDER);//Mondatory设置目标几何形状 用于确定气缸模型,圆柱体的七个系数由其轴上的点、轴方向和半径给出
	seg.setMethodType(pcl::SAC_RANSAC);//设置分割方法为随机采样
	seg.setNormalDistanceWeight(0.1);//设置表面法线权重系数为0.1
	seg.setMaxIterations(10000);//设置最大迭代次数为10000
	seg.setDistanceThreshold(0.05);//设置内点到距离模型的最大值为0.05
	seg.setRadiusLimits(0, 0.1);//设置估计出的圆柱模型的半径范围
	seg.setInputCloud(cloud_filtered2);//提取平面之后剩余的点云
	seg.setInputNormals(cloud_normals2);//剩余点云的法向量
	// 获得圆柱内点和系数
	seg.segment(*inliers_cylinder, *coefficients_cylinder);//得到点的索引和圆柱体系数
	std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;//圆柱体系数
	//将圆柱写入磁盘
	extract.setInputCloud(cloud_filtered2);
	extract.setIndices(inliers_cylinder);//将圆柱面进行分离
	extract.setNegative(false);//false代表保留内点
	pcl::PointCloud<PointT>::Ptr cloud_cylinder(new pcl::PointCloud<PointT>());//创建cloud_cylinder指针
	extract.filter(*cloud_cylinder);//按照圆柱体的索引将圆柱体的点提取至cloud_cylinder
	if (cloud_cylinder->points.empty())
		std::cerr << "Can't find the cylindrical component." << std::endl;
	else
	{
		std::cerr << "PointCloud representing the cylindrical component: " << cloud_cylinder->points.size() << " data points." << std::endl;
		writer.write("table_scene_mug_stereo_textured_cylinder.pcd", *cloud_cylinder, false);
	}
	//将原点云、平面cloud_plane、圆柱体cloud_cylinder可视化
	pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("圆柱面平面分割"));
	//第一个窗口显示输入点云
	int v1(0);
	viewer->createViewPort(0, 0, 0.33, 1, v1);
	viewer->setBackgroundColor(255, 255, 255, v1);//设置背景颜色
	pcl::visualization::PointCloudColorHandlerCustom<PointT> color1(cloud, 244, 89, 233);//设置点云显示的颜色
	viewer->addPointCloud(cloud, color1, "cloud", v1);//在窗口显示原始点云
	//第二个窗口显示分割的平面
	int v2(0);
	viewer->createViewPort(0.33, 0, 0.66, 1, v2);
	viewer->setBackgroundColor(135, 206, 235, v2);
	pcl::visualization::PointCloudColorHandlerCustom<PointT> color2(cloud, 0, 240, 0);
	viewer->addPointCloud(cloud_plane, color2, "cloud_plane", v2);//在中间窗口显示分离平面
	//第三个窗口显示分割的圆柱
	int v3(0);
	viewer->createViewPort(0.66, 0, 1, 1, v3);
	viewer->setBackgroundColor(255, 255, 255, v3);
	pcl::visualization::PointCloudColorHandlerCustom<PointT> color3(cloud, 244, 89, 0);
	viewer->addPointCloud(cloud_cylinder, color3, "cloud_cylinder", v3);//在右边窗口显示分离圆柱面
	//viewer->addCoordinateSystem();//显示坐标系
	while (!viewer->wasStopped())
	{
		viewer->spinOnce();//刷新
	}
	return (0);
}
//PointCloud has : 307200 data points.
//PointCloud after filtering has : 139897 data points.
//Plane coefficients : header:
//seq: 0 stamp : 0 frame_id :
//	values[]
//	values[0] : 0.0161902
//	values[1] : -0.837667
//	values[2] : -0.545941
//	values[3] : 0.528862
//
//	PointCloud representing the planar component : 116300 data points.
//	Cylinder coefficients : header:
// seq: 0 stamp : 0 frame_id :
//	 values[]
//	 values[0] : 0.0543319
//	 values[1] : 0.100139
//	 values[2] : 0.787577
//	 values[3] : -0.0135876
//	 values[4] : 0.834831
//	 values[5] : 0.550338
//	 values[6] : 0.0387446
//
//	 PointCloud representing the cylindrical component : 11462 data points.

 

CMakeLists文件:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project(cylinder_segmentation)

find_package(PCL 1.2 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})

link_directories(${PCL_LIBRARY_DIRS})

add_definitions(${PCL_DEFINITIONS})

add_executable (cylinder_segmentation cylinder_segmentation.cpp)

target_link_libraries (cylinder_segmentation ${PCL_LIBRARIES})

执行效果如下所示:

 

 

 

 

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
基于PCL(点云库)的RANSAC随机采样一致性)算法能够用于分割和提取球体。RANSAC是一个用于拟合基本几何模型的技术,通过随机采样数据点来找到与模型最一致的数据子集。 对于球体的分割和提取,可以按照以下步骤进行: 1. 加载点云数据:首先,将点云数据加载到PCL中,这些数据包含了球体和其他可能的点。 2. 随机采样点:从加载的点云数据中随机选择一小部分点,作为当前迭代的候选数据集。 3. 模型拟合:在选择的候选数据集中,使用球体模型对点进行拟合。这可以通过选择三个点构建一个球体,并计算其他点到该球体的距离来实现。 4. 判断一致性:通过设置一个阈值,判断点到球体模型的距离是否小于该阈值,从而确定是否将该点视为与球体一致的点。 5. 计算一致性得分:对于与球体一致的点,在当前迭代中得到一个一致性得分。一致性得分可以通过计算候选数据集中与模型一致点的数量来得到。 6. 更新最优模型:如果当前的一致性得分高于之前的最优得分,则更新最优模型,并保存该模型的参数。 7. 重复迭代:重复上述步骤,直到达到指定的迭代次数。 8. 输出结果:最终,根据最优模型的参数,可以提取出与球体一致的点,作为分割和提取出的球体数据。 总结来说,基于PCL的RANSAC算法可以通过对点云数据进行随机采样和模型拟合来分割和提取球体。这种方法是一种快速且有效的方法,可以应用于点云处理和三维重建等领域。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙有肥鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值