精华内容
下载资源
问答
  • BoundaryEstimation测试代码,有比较详细的注释。另外是附加了相关算法的一篇文献,对于理解这个函数比较有帮助
  • 平面点云的凸多边形边界提取

    一、算法原理

    1、流程概述

    1. RANSAC拟合最佳平面
    2. 将点云投影至拟合平面,形成平面点云
    3. 根据凸包算法提取二维点云的凸多边形边界

    二、代码实现

    include <pcl/io/pcd_io.h
    展开全文
  • 点云的边界提取

    热门讨论 2012-06-30 17:40:27
    能够将散乱的点云数据边界点及特征点提取出来,并显示。
  • alpha shapes提取点云边界特征(C++版本)基于PCL库写的alpha shapes算法,具体实现原理参考:https://blog.csdn.net/qq_36686437/article/details/115168516... 平面点云边界提取算法研究[D].长沙理工大学,2017.P51-53
  • 点云边界提取方法总结

    千次阅读 2021-05-04 21:05:50
    经纬线扫描法的基本思想是:将经过坐标变换后的二维数据点集按照 x值的大小排序后存储在一个链表中,在二维平面建立点集的最小包围盒并分别计算出 x 和 y 的最大、最小值;令经线从 x 的最小值开始,取步长为dx,在 ...

    经纬线扫描法

    经纬线扫描法的基本思想是:将经过坐标变换后的二维数据点集按照 x值的大小排序后存储在一个链表中,在二维平面建立点集的最小包围盒并分别计算出 x 和 y 的最大、最小值;令经线从 x 的最小值开始,取步长为dx,在 x 的取值范围内分别计算出每根经线的最大和最小 y 值,并将它们的索引值放在一个新建的链表中,扫描完整个 x 区间;同样的方法扫描纬线,最后将重复的索引值删掉。

    #include <iostream>
    #include <algorithm>
    #include <pcl/io/pcd_io.h>
    #include <pcl/point_types.h>
    
    void BoundaryExtraction(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_boundary, int resolution)
    {
    	pcl::PointXYZ px_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.x < pt2.x; });
    	pcl::PointXYZ px_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.x < pt2.x; });
    
    	float delta_x = (px_max.x - px_min.x) / resolution;
    	float min_y = INT_MAX, max_y = -INT_MAX;
    	std::vector<int> indexs_x(2 * resolution);
    	std::vector<std::pair<float, float>> minmax_x(resolution, { INT_MAX,-INT_MAX });
    	for (size_t i = 0; i < cloud->size(); ++i)
    	{
    		int id = (cloud->points[i].x - px_min.x) / delta_x;
    		if (cloud->points[i].y < minmax_x[id].first)
    		{
    			minmax_x[id].first = cloud->points[i].y;
    			indexs_x[id] = i;
    		}
    		else if (cloud->points[i].y > minmax_x[id].second)
    		{
    			minmax_x[id].second = cloud->points[i].y;
    			indexs_x[id + resolution] = i;
    		}
    	}
    
    	pcl::PointXYZ py_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.y < pt2.y; });
    	pcl::PointXYZ py_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.y < pt2.y; });
    
    	float delta_y = (py_max.y - py_min.y) / resolution;
    	float min_x = INT_MAX, max_x = -INT_MAX;
    	std::vector<int> indexs_y(2 * resolution);
    	std::vector<std::pair<float, float>> minmax_y(resolution, { INT_MAX,-INT_MAX });
    	for (size_t i = 0; i < cloud->size(); ++i)
    	{
    		int id = (cloud->points[i].y - py_min.y) / delta_y;
    		if (cloud->points[i].x < minmax_y[id].first)
    		{
    			minmax_y[id].first = cloud->points[i].x;
    			indexs_y[id] = i;
    		}
    		else if (cloud->points[i].x > minmax_y[id].second)
    		{
    			minmax_y[id].second = cloud->points[i].x;
    			indexs_y[id + resolution] = i;
    		}
    	}
    
    	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xboundary(new pcl::PointCloud<pcl::PointXYZ>);
    	pcl::copyPointCloud(*cloud, indexs_x, *cloud_xboundary);
    	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_yboundary(new pcl::PointCloud<pcl::PointXYZ>);
    	pcl::copyPointCloud(*cloud, indexs_y, *cloud_yboundary);
    	*cloud_boundary = *cloud_xboundary + *cloud_yboundary;
    }
    
    int main(int argc, char** argv)
    {
    	clock_t start = clock();
    
    	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>), cloud_boundary(new pcl::PointCloud<pcl::PointXYZ>);
    	pcl::io::loadPCDFile("test.pcd", *cloud);
    	BoundaryExtraction(cloud, cloud_boundary, 200);
    
    	clock_t stop = clock();
    	double endtime = (double)(stop - start) / CLOCKS_PER_SEC;
    	std::cout << "time:" << endtime * 1000 << "ms" << std::endl;
    
    	pcl::io::savePCDFileBinary("boundary.pcd", *cloud_boundary);
    
    	system("pause");
    	return 0;
    }
    

    网格划分法

    网格划分法分为三个步骤:(1)网格划分(2)寻找边界网格(3)提取边界线。首先建立数据点集的最小包围盒,并用给定间隔的矩形网格将其分割;然后找出边界网格,将这些边界网格按顺序连接起来形成一条由边界网格组成的“粗边界”;再对每个边界网格按照某种规则判断其内的点是否为边界点,连接初始边界,并对此边界线进一步处理使其光滑。
    在这里插入图片描述
    在这里插入图片描述

    #include <iostream>
    #include <vector>
    #include <pcl/io/pcd_io.h>
    #include <pcl/point_types.h>
    #include <pcl/common/transforms.h>
    
    typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
    
    void BoundaryExtraction(PointCloud::Ptr cloud, PointCloud::Ptr cloud_boundary, int resolution)
    {
    	pcl::PointXYZ px_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.x < pt2.x; });
    	pcl::PointXYZ px_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.x < pt2.x; });
    	pcl::PointXYZ py_min = *std::min_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.y < pt2.y; });
    	pcl::PointXYZ py_max = *std::max_element(cloud->begin(), cloud->end(), [](pcl::PointXYZ pt1, pcl::PointXYZ pt2) {return pt1.y < pt2.y; });
    	float x_min = px_min.x, x_max = px_max.x, y_min = py_min.y, y_max = py_max.y;
    
    	float L = sqrt((x_max - x_min)*(y_max - y_min) / resolution);
    	int x_num = (x_max - x_min) / L + 1;
    	int y_num = (y_max - y_min) / L + 1;
    	//std::cout << L << " " << x_num << " " << y_num << std::endl;
    
    	std::vector<std::vector<PointCloud::Ptr>> uv(x_num + 1, std::vector<PointCloud::Ptr>(y_num + 1));
    	for (int i = 0; i <= x_num; ++i)
    	{
    		for (int j = 0; j <= y_num; ++j)
    		{
    			PointCloud::Ptr ptcloud(new PointCloud);
    			uv[i][j] = ptcloud;
    		}
    	}
    	for (int i = 0; i < cloud->size(); ++i)
    	{
    		int x_id = (cloud->points[i].x - x_min) / L;
    		int y_id = (cloud->points[i].y - y_min) / L;
    		uv[x_id][y_id]->push_back(cloud->points[i]);
    	}
    
    	std::vector<std::vector<bool>> boundary_index(x_num + 1, std::vector<bool>(y_num + 1, false));
    	for (int i = 0; i <= x_num; ++i)
    	{
    		if (uv[i][0]->size())
    			boundary_index[i][0] = true;
    		if (uv[i][y_num]->size())
    			boundary_index[i][y_num] = true;
    	}		
    	for (int i = 0; i <= y_num; ++i)
    	{
    		if(uv[0][i]->size())
    			boundary_index[0][i] = true;
    		if (uv[x_num][i]->size())
    			boundary_index[x_num][i] = true;
    	}
    	for (int i = 1; i < x_num-1; ++i)
    	{
    		for (int j = 1; j < y_num-1; ++j)
    		{
    			if (uv[i][j]->size())
    			{
    				if (!uv[i - 1][j - 1]->size() || !uv[i][j - 1]->size() || !uv[i + 1][j - 1]->size() || !uv[i][j - 1]->size() ||
    					!uv[i + 1][j - 1]->size() || !uv[i + 1][j]->size() || !uv[i + 1][j + 1]->size() || !uv[i][j + 1]->size())
    					boundary_index[i][j] = true;
    			}
    		}
    	}
    
    	for (int i = 0; i <= x_num; ++i)
    	{
    		for (int j = 0; j <= y_num; ++j)
    		{
    			//std::cout << i << " " << j << " " << uv[i][j]->points.size() << std::endl;
    			if (boundary_index[i][j])
    			{
    				PointCloud::Ptr ptcloud(new PointCloud);
    				ptcloud = uv[i][j];
    				Eigen::Vector4f cloud_centroid;
    				pcl::compute3DCentroid(*ptcloud, cloud_centroid);
    				cloud_boundary->push_back(pcl::PointXYZ(cloud_centroid(0), cloud_centroid(1), cloud_centroid(2)));
    			}
    		}
    	}
    }
    
    int main(int argc, char** argv)
    {
    	clock_t start = clock();
    
    	PointCloud::Ptr cloud(new PointCloud), cloud_boundary(new PointCloud);
    	pcl::io::loadPCDFile("4icp5+6+icp_skeleton.pcd", *cloud);
    	BoundaryExtraction(cloud, cloud_boundary, 200*200);
    
    	clock_t stop = clock();
    	double endtime = (double)(stop - start) / CLOCKS_PER_SEC;
    	std::cout << "time:" << endtime * 1000 << "ms" << std::endl;
    
    	pcl::io::savePCDFile("boundary.pcd", *cloud_boundary);
    
    	system("pause");
    	return 0;
    }
    

    法线估计法

    可参考PCL:点云数据基于法线的边界提取(从最初的法线估计理论推导到最终的边界提取)

    #include <iostream>
    #include <vector>
    #include <ctime>
    #include <boost/thread/thread.hpp>
    #include <pcl/io/pcd_io.h>
    #include <pcl/visualization/pcl_visualizer.h>
    #include <pcl/console/parse.h>
    #include <pcl/features/eigen.h>
    #include <pcl/features/feature.h>
    #include <pcl/features/normal_3d.h>
    #include <pcl/features/normal_3d_omp.h>
    #include <pcl/impl/point_types.hpp>
    #include <pcl/features/boundary.h>
    #include <pcl/visualization/cloud_viewer.h>
    #include <pcl/filters/voxel_grid.h>
    using namespace std;
    
    int main(int argc, char **argv)
    {
    	clock_t start = clock();
    
    	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    	if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *cloud) == -1)
    	{
    		PCL_ERROR("COULD NOT READ FILE. \n");
    		return (-1);
    	}
    	//std::cout << "points size is:" << cloud->size() << std::endl;
    	
    	pcl::VoxelGrid<pcl::PointXYZ> voxel_grid;
    	voxel_grid.setLeafSize(std::stof(argv[2]), std::stof(argv[2]), std::stof(argv[2]));
    	voxel_grid.setInputCloud(cloud);
    	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
    	voxel_grid.filter(*cloud_filtered);
    	//std::cout << "filtered points size is:" << cloud_filtered->size() << std::endl;
    
    	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
    	pcl::PointCloud<pcl::Boundary> boundaries;
    	pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> est;
    	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    
    	//pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normEst;  //其中pcl::PointXYZ表示输入类型数据,pcl::Normal表示输出类型,且pcl::Normal前三项是法向,最后一项是曲率
    	pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> normEst;
    	normEst.setNumberOfThreads(12);  // 手动设置线程数,否则提示错误
    	normEst.setInputCloud(cloud_filtered);
    	normEst.setSearchMethod(tree);
    	normEst.setRadiusSearch(std::stof(argv[3]));  //法向估计的半径
    	 //normEst.setKSearch(9);  //法向估计的点数
    	normEst.compute(*normals);
    	//cout << "normal size is " << normals->size() << endl;
    
    	est.setInputCloud(cloud_filtered);
    	est.setInputNormals(normals);
    	est.setSearchMethod(tree);
    	est.setKSearch(500);  //一般这里的数值越高,最终边界识别的精度越好
    	est.compute(boundaries);
    
    	pcl::PointCloud<pcl::PointXYZ>::Ptr boundPoints(new pcl::PointCloud<pcl::PointXYZ>);
    	pcl::PointCloud<pcl::PointXYZ> noBoundPoints;
    	int countBoundaries = 0;
    	for (int i = 0; i<cloud_filtered->size(); i++) {
    		uint8_t x = (boundaries.points[i].boundary_point);
    		int a = static_cast<int>(x); //该函数的功能是强制类型转换
    		if (a == 1)
    		{
    			(*boundPoints).push_back(cloud_filtered->points[i]);
    			countBoundaries++;
    		}
    		else
    			noBoundPoints.push_back(cloud_filtered->points[i]);
    	}
    
    	clock_t stop = clock();
    	double endtime = (double)(stop - start) / CLOCKS_PER_SEC; 
    	std::cout << "time:" << endtime * 1000 << "ms" << std::endl;
    	std::cout << "boundary size is:" << countBoundaries << std::endl;
    	//pcl::io::savePCDFileASCII("boundary.pcd", *boundPoints);
    	//pcl::io::savePCDFileASCII("NoBoundpoints.pcd", noBoundPoints);
    	pcl::visualization::CloudViewer viewer("boundary");
    	viewer.showCloud(boundPoints);
    	while (!viewer.wasStopped())
    	{
    	}
    	return 0;
    }
    

    参考资料:点云的边界提取及角点检测算法研究

    展开全文
  • PCL_BoundaryEstimation_Point散乱数据点云边界特征自动提取算法
  • 一、提取平面 1、ransac 2、直通滤波 3、基于区域生长的分割算法 4、欧式聚类? 5、形态学滤波的方法分割 6、超聚类? 7、有待学习。...2、BoundaryEstimation边界提取 3、有待学习 ...

    一、提取平面

    1、ransac

    2、直通滤波

    3、基于区域生长的分割算法

    4、欧式聚类?

    5、形态学滤波的方法分割

    6、超聚类?

    7、有待学习。。。

    二、提取轮廓

    1、chull

    2、BoundaryEstimation边界提取

    3、有待学习

    展开全文
  • PCL(35)点云边界提取

    千次阅读 2021-01-05 16:42:45
    #pragma warning(disable:4996) #include <iostream> #include <pcl/console/parse.h> #include <pcl/filters/extract_indices.h> #include <pcl/io/pcd_io.h>...pcl/visualization/pcl_...
    #pragma warning(disable:4996)
    #include <iostream>
    #include <pcl/console/parse.h>
    #include <pcl/filters/extract_indices.h>
    #include <pcl/io/pcd_io.h>
    #include <pcl/point_types.h>
    
    #
    展开全文
  • MATLAB在平面图形边界信息提取中的应用.pdf
  • MATLAB在平面图形边界信息提取中的应用
  • 本文将Alpha Shapes 算法应用于隧道二维投影边界提取,详细介绍了Alpha Shapes 边界提取算法的原理。给出了实现代码,并对边界点提取结果进行展示。最后对不同半径 α 得到的边界提取结果进行分析讨论,并得出结论。
  • 边界提取采用PCL库里边的方法,基于法线估计来实现的边界检测与提取: 首先从原始点云上计算出法线,再由法线结合数据估计出边界。(这样解释还是特别抽像吧) ------------法线求解:(平面的法线是垂直于它的...
  • 边界提取采用PCL库里边的方法,基于法线估计来实现的边界检测与提取: 首先从原始点云上计算出法线,再由法线结合数据估计出边界。(这样解释还是特别抽像吧) ------------法线求解:(平面的法线是垂直于它的...
  • PCL_BoundaryEstimation边界提取

    千次阅读 2020-04-13 18:23:33
    pcl::BoundaryEstimation用于散乱点云的边界提取,但应该只适用于简单的点云,过于复杂的话效果应该不太好。同时,需要pcl::NormalEstimation先计算法线,算起来也挺慢的。 ...
  • 平面点云凸多边形轮廓提起
  • 提出一种散乱点云边界特征的快速提取算法,该算法采用R*-tree建立散乱点云空间索引结构,基于该结构快速准确获取局部型面参考点集,建立该点集的基准平面,计算点集内各点到基准平面的距离并将该距离与目标点到基准...
  • 经过对VRML文本内容的分析,采用一系列三角形平面取代原始的多边形平面和自由曲面的VRML描述模型表面的方法,建立了文本数据与模型边界线之间的对应关系,提出了一种基于VRML的模具边界线三维解析式提取方法,并将该...
  • 平面点云的凹多边形边界提取
  • RANSAC多平面提取RANSAC思想个人理解实验代码实验结果 RANSAC思想 1、从观测数据中随机选择一个子集。 2、估计出适合于这些子集的模型 3、用这个模型测试其他的数据,根据损失函数,得到符合这个模型的点,称为一致...
  • 平面提取论文

    千次阅读 2020-03-07 21:03:03
    4)其实到第三步就够了,但是为了证实提取出来的是平面区域和为了提升方向估计效果,又将每个平面实例区域输入上个“Plane Recognition”部分再次计算(然而实验表明没卵用) 备用方案:因为对于马路之类缺少纹理的...
  • alpha shapes提取边界原理及详细步骤

    千次阅读 2021-01-31 11:08:29
    由Edelsbrunner H提出的alpha shapes算法是一种简单、有效的快速提取边界点算法。其克服了点云边界点形状影响的缺点,可快速准确提取边界点,其原理如下: ... 平面点云边界提取算法研究[D].长沙理工大学,2017. ...
  • 首先,以垂直于任意坐标轴的平面剖切复杂采空区三角网格模型得到边界剖面线的无序点集,提取无序点集的凸包线作为初始轮廓线,然后将包络于初始轮廓线内的点按张角最大的原则全部添加到轮廓线中,获得完整的剖面轮廓...
  • 平面离散点集外轮廓提取

    热门讨论 2010-04-02 16:20:19
    基于凸包,使用凹点挖掘技术,实现平面离散点集外轮廓提取
  • 行业分类-设备装置-一种结合边界积分方程方法和随机法的平面边界面电荷密度提取方法
  • 提出一种散乱数据点云边界特征自动提取算法,该算法采用R*-tree动态空间索引结构组织散乱数据点云的拓扑关系,基于该结构获取采样点的k近邻点作为局部型面参考数据,以最sJ,-乘法拟合该数据的微切平面,并将其向微切...
  • 主流的几类平面提取的方法有: (1)RANSAC-based methods:long computation time; (2)Region-grow-based methods(pixel、voxel、line); (3) turn into normal space, compute the distance between ...
  • 鉴于传统平面流场拓扑特征提取算法的不足 ,本文提出了一种新的拓扑分析方法。该方法首先通过边界矢量镜像处理 ,建立一个带虚拟边界的扩展流场 ;然后针对扩展流场 ,按照临界点理论提取拓扑特征。最后 ,根据流场的实际...
  • Gabor滤波器与特征提取

    万次阅读 多人点赞 2016-03-18 19:21:37
    Gabor滤波器,最主要使用优势体现在对物体纹理特征的提取上。二维Gabor基函数能够很好地描述哺乳动物初级视觉系统中一对简单视觉神经元的感受野特性。随着小波变换和神经生理学的发展,Gabor变换逐渐演变成二维Gabor...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,337
精华内容 4,534
关键字:

平面边界提取