PCL 基于颜色的区域生长分割(Segmentation_RegionGrowingRGB)

PCL专栏目录及须知

注意:本方法可按颜色分割点云,适用于具有颜色流通性的点云,看文末结果展示。

1.基于RGB的区域生长分割

将具有颜色或(法线或者曲率【可选】)相似性的点云集合起来构成一簇聚类点。

算法逻辑同区域生长分割相似,只是阈值从法线/曲率变为了颜色。

(1)分割不同颜色点云块。

1)当前种子点P和距离范围在邻域点之间色差小于色差阀值的点簇视为一个聚类。

2)迭代进行步骤1),直到遍历完所有点云。

(2)合并聚类出的点云块,得到结果点云。

1)聚类之间的色差小于色差阀值和并为一个聚类,且当前聚类中点的数量小于聚类点数量的与最近的聚类合并在一起。

源码中所用色差计算公式:

1)点与点的颜色差异值:

diff = (p1.r - p2.r)*(p1.r - p2.r) + (p1.g - p2.g)*(p1.g - p2.g) + (p1.b - p2.b)*(p1.b - p2.b)

2)区域与区域的颜色差异值:

diffArea = 区域中所有点与点的颜色差异值累加和 /  区域中点对个数

2.使用场景

可用于分割具有颜色连通性的点云。如示例中的建筑物等。

3.关键函数

(1)距离阈值,用于聚类相邻点搜索

segmentation.setDistanceThreshold(2.0);	

(2)两点颜色阈值

segmentation.setPointColorThreshold(8);

(3)两类区域颜色阈值

segmentation.setRegionColorThreshold(20);

4.完整代码

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/search/kdtree.h>
#include <pcl/common/angles.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/segmentation/region_growing_rgb.h>
#include <boost/thread/thread.hpp>

#define NorAndCuv

int main()
{
	/****************基于颜色的区域生长分割********************/
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);				// 源点云
	pcl::io::loadPCDFile("D:/code/csdn/data/unit.pcd", *cloud);

	// 区域生长分割
	// 法线和表面曲率估计
	pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>);
	pcl::PointCloud <pcl::Normal>::Ptr normals(new pcl::PointCloud <pcl::Normal>);
	pcl::NormalEstimationOMP<pcl::PointXYZRGB, pcl::Normal> n;
	n.setInputCloud(cloud);
	n.setSearchMethod(tree);
	n.setNumberOfThreads(6);																	// 设置线程数
	n.setKSearch(20);																			// k近邻数目
	n.compute(*normals);

	// 基于颜色的区域生长分割
	pcl::RegionGrowingRGB<pcl::PointXYZRGB> segmentation;
	segmentation.setInputCloud(cloud);
	segmentation.setMinClusterSize(500);								// 一簇聚类最小点数
	segmentation.setMaxClusterSize(1000000);							// 一簇聚类最大点数
	segmentation.setSearchMethod(tree);
	segmentation.setDistanceThreshold(2.0);								// 距离阈值,用于聚类相邻点搜索
	segmentation.setPointColorThreshold(8);								// 两点颜色阈值
	segmentation.setRegionColorThreshold(20);							// 两类区域颜色阈值

#ifdef NorAndCuv
	segmentation.setSmoothModeFlag(true);								// 设置是否使用法向量夹角,设置为true则需提供法线及法线夹角阈值
	segmentation.setCurvatureTestFlag(true);							// 设置是否使用曲率阈值,设置为true则需提供法线及法线夹角阈值
#else
	segmentation.setSmoothModeFlag(false);	
	segmentation.setCurvatureTestFlag(false);
#endif // NorAndCuv
	segmentation.setInputNormals(normals);
	segmentation.setSmoothnessThreshold(pcl::deg2rad(3.0));				// 法向量夹角的阈值,超过这个夹角,即认为不在一个平面上
	segmentation.setCurvatureThreshold(1.0);							// 曲率的阈值,超过这个阈值,即认为不在一个平面上

	std::vector <pcl::PointIndices> clustersIndices;					// 聚类结果
	segmentation.extract(clustersIndices);

	// 提取聚类后点云
	std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> clustreClouds;
	for (size_t i = 0; i < clustersIndices.size(); i++)
	{
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloudTemp(new pcl::PointCloud<pcl::PointXYZ>);
		pcl::copyPointCloud(*cloud, clustersIndices[i], *cloudTemp);
		clustreClouds.push_back(cloudTemp);
	}

	/****************展示********************/
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("EuclideanClusterExtraction"));
	for (size_t i = 0; i < clustreClouds.size(); i++)
	{
		pcl::RGB rgb = pcl::getRandomColor(0, 255);
		viewer->addPointCloud<pcl::PointXYZ>(clustreClouds.at(i), pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(clustreClouds.at(i), rgb.r, rgb.g, rgb.b), "clustreClouds" + i);
	}

	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

	return (0);
}

5.结果展示

(1)原始RGB点云

(2)分割后点云

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值