PCL 点云分割 区域生长分割算法及源代码

  1. 区域增长
    区域增长(region growing)是指将成组的像素或区域发展成更大区域的过程。从种子点的集合开始,从这些点的区域增长是通过将与每个种子点有相似属性像强度、灰度级、纹理颜色等的相邻像素合并到此区域。
  2. 曲率
    它根据点的曲率值对点进行排序。需要这样做是因为区域从曲率最小的点开始增长。这样做的原因是曲率最小的点位于平坦区域(从最平坦区域生长可以减少段的总数)。
  3. 法线夹角阈值,搜索当前种子点的邻域点,计算邻域点的法线与当前种子点的法线之间的夹角,小于阈值的邻域点加入到当前区域;
  4. 对于每个种子点,算法都会发现周边的所有近邻点。1)计算每个近邻点与当前种子点的法线角度差(reg.setSmoothnessThreshold),如果差值小于设置的阈值,则该近邻点被重点考虑,进行第二步测试;2)该近邻点通过了法线角度差检验,如果它的曲率小于我们设定的阈值(reg.setCurvatureThreshold),这个点就被添加到种子点集,即属于当前平面。
//****区域增长分割****//

#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/segmentation/region_growing.h>
#include <pcl/visualization/cloud_viewer.h>
#include <vector>
#include <string>
#include <pcl/io/ply_io.h>
#include <atlstr.h>//CString头文件
using namespace std;

int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::io::loadPLYFile<pcl::PointXYZ>("house.ply", *cloud);

	//设置默认输入参数
	int KN_normal = 50;
	//bool Bool_Cuting=false;
	float SmoothnessThreshold = 45, CurvatureThreshold = 20;

	//法线估计
	pcl::search::Search<pcl::PointXYZ>::Ptr tree = shared_ptr<pcl::search::Search<pcl::PointXYZ> >(new pcl::search::KdTree<pcl::PointXYZ>);//创建一个指向kd树搜索对象的共享指针
	pcl::PointCloud <pcl::Normal>::Ptr normals(new pcl::PointCloud <pcl::Normal>);
	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;//创建法线估计对象
	normal_estimator.setSearchMethod(tree);//设置搜索方法
	normal_estimator.setInputCloud(cloud);//设置法线估计对象输入点集
	normal_estimator.setKSearch(KN_normal);// 设置用于法向量估计的k近邻数目
	normal_estimator.compute(*normals);//计算并输出法向量

	// 区域生长算法的5个参数
	pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;//创建区域生长分割对象
	reg.setMinClusterSize(100);//设置一个聚类需要的最小点数
	reg.setMaxClusterSize(1000000);//设置一个聚类需要的最大点数
	reg.setSearchMethod(tree);//设置搜索方法
	reg.setNumberOfNeighbours(15);//设置搜索的临近点数目
	reg.setInputCloud(cloud);//设置输入点云
	//pcl::IndicesPtr indices(new std::vector <int>);//创建一组索引
	//if(Bool_Cuting)reg.setIndices (indices);//通过输入参数设置,确定是否输入点云索引
	reg.setInputNormals(normals);//设置输入点云的法向量
	reg.setSmoothnessThreshold(SmoothnessThreshold / 180.0 * M_PI);//设置平滑阈值
	reg.setCurvatureThreshold(CurvatureThreshold);//设置曲率阈值
	std::vector <pcl::PointIndices> clusters;
	reg.extract(clusters);//获取聚类的结果,分割结果保存在点云索引的向量中。




	pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud();//如果点云分割成功,该函数返回有色点云,相同的分割有相同的颜色,但是该函数不保证不同的分割一定会有不同的颜色,即不同的分割也可能会有相同的颜色
	pcl::io::savePLYFile("aaa.ply", *colored_cloud);  //保存文件








	std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> RegionGrow; //用于储存区域增长分割后的点云
	for (std::vector<pcl::PointIndices>::const_iterator it = clusters.begin(); it != clusters.end(); ++it)
	{
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>);
		for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); pit++)
			cloud_cluster->points.push_back(cloud->points[*pit]);
		cloud_cluster->width = cloud_cluster->points.size();
		cloud_cluster->height = 1;
		cloud_cluster->is_dense = true;
		RegionGrow.push_back(cloud_cluster);
	}



	cout << " 	RegionGrow.size() = " << RegionGrow.size() << endl;

	ofstream fout; //c++输出文件流,支持输出c++的数据类型,如string
	fout.open("RGCentroid.txt");
	for (int i = 0; i < RegionGrow.size(); i++)
	{
		//显示分割得到的各片点云
		
		//显示分割得到的各片点云 
		pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color(RegionGrow[i], 255 * (1 - i) * (2 - i) / 2, 255 * i * (2 - i), 255 * i * (i - 1) / 2);
		
		//保存分割得到的各片点云
		pcl::io::savePLYFile(to_string(i)+"a.ply",*RegionGrow[i]);  //保存文件
	
		//将分割得到的各片点云的质心保存在.txt文件中
		Eigen::Vector4f RGCentroid;
		pcl::compute3DCentroid(*RegionGrow[i], RGCentroid);//计算点云质心
		fout << "Centroid of  = " << i  << RGCentroid[0] << " " << RGCentroid[1] << " " << RGCentroid[2] << " " << endl;
	}
	fout.close(); //关闭文件。


	return (0);
}

在这里插入图片描述
请添加图片描述
请添加图片描述
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

向日葵xyz

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

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

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

打赏作者

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

抵扣说明:

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

余额充值