【PCL-13】圆柱型分割

背景:

有一料仓点云数据,需祛除料仓壁,提取料仓面。

【PCL-13】圆柱型分割_第1张图片

思路:

1、点云法线估计

typedef pcl::PointXYZ PointT;
pcl::NormalEstimation ne;    // 法线估算对象
pcl::search::KdTree::Ptr tree(new pcl::search::KdTree());
pcl::PointCloud::Ptr cloud_normals(new pcl::PointCloud);

ne.setSearchMethod(tree);			//设置法线估计的方式为kdtree
ne.setInputCloud(cloud_filtered_vg);	//输入点云用于法线估计
ne.setKSearch(50);	  //设置k近邻点的个数为5
ne.compute(*cloud_normals);

2、构建圆柱形分割模型

#include 

pcl::SACSegmentationFromNormals seg;    // 分割器
pcl::ModelCoefficients::Ptr coefficients_cylinder(new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers_cylinder(new pcl::PointIndices);

//创建用于圆柱体分割的分割对象,并设置所有参数
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_CYLINDER);   // 设置分割模型为圆柱体
seg.setMethodType(pcl::SAC_RANSAC);         // 设置采用 RANSAC 算法进行参数估计
seg.setNormalDistanceWeight(0.1);           // 设置表面法线权重系数
seg.setMaxIterations(1000);                // 设置最大迭代次数 10000
seg.setDistanceThreshold(0.03);             // 设置内点到模型的最大距离 0.05m
seg.setRadiusLimits(0, 8.0);                // 设置圆柱体的半径范围 0 ~ 0.1m
seg.setInputCloud(cloud_filtered_vg);      //输入点云数据
seg.setInputNormals(cloud_normals);
seg.segment(*inliers_cylinder, *coefficients_cylinder);
std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;

3、提取数据

pcl::ExtractIndices extract;        // 点提取对象
pcl::PCDWriter writer; 

// 将圆柱体外点写入磁盘
extract.setInputCloud(cloud_filtered_vg);
extract.setIndices(inliers_cylinder);
extract.setNegative(true);  //ture:提取圆柱体外数据,false:提取圆柱体内数据
pcl::PointCloud::Ptr cloud_cylinder(new pcl::PointCloud());
extract.filter(*cloud_cylinder);
writer.write("..\\testdata\\result\\data\\output_cloud.pcd", *cloud_cylinder, false);

完整示例代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

typedef pcl::PointXYZ PointT;

int main(int argc, char *argv[]) {
	pcl::PCDReader reader;    // PCD 文件读取对象
	pcl::NormalEstimation ne;    // 法线估算对象
	pcl::SACSegmentationFromNormals seg;    // 分割器
	pcl::PCDWriter writer;                                       // PCD 文件写入对象
	pcl::ExtractIndices extract;                         // 点提取对象
	pcl::search::KdTree::Ptr tree(new pcl::search::KdTree());

	pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
	pcl::PointCloud::Ptr cloud_normals(new pcl::PointCloud);
	pcl::ModelCoefficients::Ptr coefficients_cylinder(new pcl::ModelCoefficients);
	pcl::PointIndices::Ptr inliers_cylinder(new pcl::PointIndices);

	// 读取点云数据
	reader.read("..\\testdata\\result\\data\\tong.pcd", *cloud);
	std::cerr << "PointCloud has: " << cloud->points.size() << " data points." << std::endl;

	//---------------------------------------体素滤波-------------------------------
	pcl::PointCloud::Ptr cloud_filtered_vg(new pcl::PointCloud);

	//pcl::ApproximateVoxelGrid sor;
	pcl::VoxelGrid vg;
	vg.setInputCloud(cloud);
	vg.setLeafSize(0.2f, 0.2f, 0.2f);//单位为m
	vg.filter(*cloud_filtered_vg);
	pcl::io::savePCDFileASCII("..\\testdata\\result\\data\\vg.pcd", *cloud_filtered_vg);

	
	ne.setSearchMethod(tree);			//设置法线估计的方式为kdtree
	ne.setInputCloud(cloud_filtered_vg);	//输入过滤后的点云用于法线估计
	ne.setKSearch(50);	  //设置k近邻点的个数为50
	ne.compute(*cloud_normals);

	//创建用于圆柱体分割的分割对象,并设置所有参数
	seg.setOptimizeCoefficients(true);
	seg.setModelType(pcl::SACMODEL_CYLINDER);   // 设置分割模型为圆柱体
	seg.setMethodType(pcl::SAC_RANSAC);         // 设置采用 RANSAC 算法进行参数估计
	seg.setNormalDistanceWeight(0.1);           // 设置表面法线权重系数
	seg.setMaxIterations(1000);                // 设置最大迭代次数 10000
	seg.setDistanceThreshold(0.03);             // 设置内点到模型的最大距离 0.05m
	seg.setRadiusLimits(0, 8.0);                // 设置圆柱体的半径范围 0 ~ 0.1m
	seg.setInputCloud(cloud_filtered_vg);
	seg.setInputNormals(cloud_normals);
	seg.segment(*inliers_cylinder, *coefficients_cylinder);
	std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;

	// 将圆柱体外点写入磁盘
	extract.setInputCloud(cloud_filtered_vg);
	extract.setIndices(inliers_cylinder);
	extract.setNegative(true);
	pcl::PointCloud::Ptr cloud_cylinder(new pcl::PointCloud());
	extract.filter(*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("..\\testdata\\result\\data\\output_cloud.pcd", *cloud_cylinder, false);
	}

	return 0;
}

运行结果:

【PCL-13】圆柱型分割_第2张图片

你可能感兴趣的:(PCL)