基于合力的点云边缘提取

一、原理 

基于合力的三维点云边缘提取,其根据点的近邻点分布规律来识别边缘点。对于边缘点,其近邻点分布在其一侧,使用近邻点构成的向量合成理论上不为零(图a);对于非边缘点,近邻点均匀分布在其周边,向量合成理论上为零(图b)。

基于合力的点云边缘提取_第1张图片  基于合力的点云边缘提取_第2张图片

基于合力的点云边缘提取_第3张图片基于合力的点云边缘提取_第4张图片

二、算法步骤

依据合理的边缘点提取,其过程如下:

(1)对于每个点,使用kdtree搜索其近邻点

(2)使用近邻点构成向量,并对向量进行单位化

p_{0}p_{1}=(x_{i}-x_{0},y_{i}-y_{0},z_{i}-z_{0})

p_{0}p_{i0}=\frac{p_{0}p_{i}}{|p_{0}p_{i}|}

(3)对向量进行叠加,得到合力指标F(P0):

F(P_{0})=\frac{1}{K}|\sum_{i=1}^{k}p_{0}p_{i0}|

 依据合力指标判断该点是否为边缘点。其中合理指标靠近0的,为非边缘点;合力指标越大的则为边缘点。

三、源代码及实验结果

完整源代码下载链接:https://download.csdn.net/download/qq_32867925/87398181

基于PCL1.8环境编写的程序,部分代码展示如下:

void main()
{
	//char *inputpath = "D:\\矩形.txt";
	//char *outpath = "D:\\矩形_边缘.txt";
	char *inputpath = "D:\\三维点.txt";
	char *outpath = "D:\\三维点_边缘.txt";

	ifstream infile(inputpath, ios::in);
	char line[128];
	vector points;
	pcl::PointXYZ pt;
	while (infile.getline(line, sizeof(line)))
	{
		std::stringstream word(line);
		word >> pt.x;
		word >> pt.y;
		word >> pt.z;

		points.push_back(pt);
	}
	vector bounpoint, nonbounpoint;
	double thres_sumvector = 0.25;

	//point                待提取的原始点数据
	//thres_sumvector      向量合成阈值大小
	//bounpoint            边缘点
	//nonbounpoint         非边缘点
	BoundaryExtract(points, thres_sumvector, bounpoint, nonbounpoint);

	//边缘点
	pcl::PointCloud::Ptr Cloud_bound(new pcl::PointCloud);
	Cloud_bound->width = bounpoint.size();
	Cloud_bound->height = 1;
	Cloud_bound->is_dense = false;
	Cloud_bound->resize(Cloud_bound->width*Cloud_bound->height);

	for (int i = 0; i < bounpoint.size(); i++)
	{
		Cloud_bound->points[i].x = bounpoint[i].x;
		Cloud_bound->points[i].y = bounpoint[i].y;
		Cloud_bound->points[i].z = bounpoint[i].z;
	}

	//非边缘点
	pcl::PointCloud::Ptr Cloud_nonbound(new pcl::PointCloud);
	Cloud_nonbound->width = nonbounpoint.size();
	Cloud_nonbound->height = 1;
	Cloud_nonbound->is_dense = false;
	Cloud_nonbound->resize(Cloud_nonbound->width*Cloud_nonbound->height);

	for (int i = 0; i < nonbounpoint.size(); i++)
	{
		Cloud_nonbound->points[i].x = nonbounpoint[i].x;
		Cloud_nonbound->points[i].y = nonbounpoint[i].y;
		Cloud_nonbound->points[i].z = nonbounpoint[i].z;
	}

	pcl::visualization::PCLVisualizer viewer("点云边缘提取");
	viewer.setBackgroundColor(0, 0, 0);

	//边缘点设置成红色
	pcl::visualization::PointCloudColorHandlerCustom singleColor_bound(Cloud_bound, 255, 0, 0);
	viewer.addPointCloud(Cloud_bound, singleColor_bound, "bound");//显示点云,其中fildColor为颜色显示
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "bound");//设置点云大小

	//非边缘点设置成白色
	pcl::visualization::PointCloudColorHandlerCustom singleColor_nonbound(Cloud_nonbound, 255, 255, 255);
	viewer.addPointCloud(Cloud_nonbound, singleColor_nonbound, "nonbound");//显示点云,其中fildColor为颜色显示
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "nonbound");//设置点云大小

	//结果保存
	ofstream outfile(outpath, ios::out);
	for (int i = 0; i < bounpoint.size(); i++)
	{
		outfile << fixed << setprecision(3) << bounpoint[i].x << " " << bounpoint[i].y << " " << bounpoint[i].z << " " <<
			fixed << setprecision(0) << 255 << " " << 0 << " " << 0 << endl;
	}

	for (int i = 0; i < nonbounpoint.size(); i++)
	{
		outfile << fixed << setprecision(3) << nonbounpoint[i].x << " " << nonbounpoint[i].y << " " << nonbounpoint[i].z << " " <<
			fixed << setprecision(0) << 255 << " " << 255 << " " << 255 << endl;
	}
	outfile.close();

	while (!viewer.wasStopped())
	{
		viewer.spinOnce();
	}
}

平面点云提取的边缘结果:

基于合力的点云边缘提取_第5张图片

非平面点云提取的结果:

基于合力的点云边缘提取_第6张图片

基于合力的点云边缘提取_第7张图片

你可能感兴趣的:(PCL点云数据处理(C++),人工智能,python)