平面点云的有序边缘点提取

****只适用于位于同一平面上的点云数据,进行边缘点检测

一、原理介绍

有序边缘点,就是提取的边缘点具有先后顺序,连接起来能够大体描述点云形状。如下图所示为有序边缘点,其连接成的多边形大体准确刻画了点云外部形状。而下面的一副图,其提取的边缘点为无序边缘点。无序边缘点一般后面需要 进行有序排列,其难度依据点云形状而定。

 

 

下面介绍一种使用alpha shapes算法提取边缘点,并进行排序的方法,其先使用alpha shapes算法提取边缘点,再进行排序。

代码下载链接:https://download.csdn.net/download/qq_32867925/87429769?spm=1001.2014.3001.5503

二、源码测试及实验结果

****再次声明:其只适用于位于同一平面上的点云数据,进行边缘点检测

运行环境:PCL1.8版本及以上,IDE:vs2013

 单独运行cpp文件即可。

(1)边缘点提取实验(部分核心代码展示)

//测试边缘提取结果
void main01()
{
	char *inputpath = "E:\\testdata.xyz";
	char *outpath = "E:\\result.xyz";
	//(1)读入点云数据
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	cloud = XYZ2PCDPtr(inputpath);
	//(2)边缘检测
	double r = 1.2;
	vector<pcl::PointXYZ> bound, non_bound;
	boundExtract(cloud, r, bound, non_bound);
	ofstream outfile(outpath, ios::out);
	for (int i = 0; i < bound.size(); i++)
	{
		outfile << fixed << setprecision(3) << bound[i].x << " " << bound[i].y << " " << bound[i].z << " " << fixed << setprecision(0) <<
			255 << " " << 0 << " " << 0 << endl;
	}

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

}

 其结果如下,整体上来说还是不错的,提取的边缘点比较简洁

 (2)测试边缘点是否有序(部分核心代码展示):


//测试边缘点的有序性
void main()
{
	 char *inputpath = "E:\\testdata.xyz";
	//char *inputpath = "E:\\testdata_01.xyz";
	
	//(1)读入点云数据
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	cloud = XYZ2PCDPtr(inputpath);
	//(2)边缘检测
	double r = 1.2;
	vector<pcl::PointXYZ> bound, non_bound;
	boundExtract(cloud, r, bound, non_bound);
	
	//(3)可视化
	pcl::visualization::PCLVisualizer viewer("outline view");
	viewer.setBackgroundColor(0, 0, 0);
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 0, 255);
	viewer.addPointCloud<pcl::PointXYZ>(cloud, single_color, "sample cloud");
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");//设置点云大小
	
	//(4)增加多边形
	pcl::PlanarPolygon<pcl::PointXYZ> polygon;
	pcl::PointCloud<pcl::PointXYZ> contour;
	contour.width = bound.size();
	contour.height = 1;
	contour.is_dense = false;
	contour.resize(contour.height*contour.width);
	for (int i = 0; i < bound.size(); i++)
	{
		contour.points[i] = bound[i];
	}
	
	polygon.setContour(contour);
	viewer.addPolygon(polygon, 255, 0, 0, "ploygon", 0);
	//(5)增加点
	pcl::PointCloud<pcl::PointXYZ>::Ptr Boun_Cloud(new pcl::PointCloud<pcl::PointXYZ>);
	Boun_Cloud->width = bound.size();
	Boun_Cloud->height = 1;
	Boun_Cloud->is_dense = false;
	Boun_Cloud->resize(Boun_Cloud->width*Boun_Cloud->height);
	for (int i = 0; i < Boun_Cloud->width; i++)
	{
		Boun_Cloud->points[i] = bound[i];
	}

	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> singleColor(Boun_Cloud, 0, 255, 0);//0-255  设置成绿色
	viewer.addPointCloud<pcl::PointXYZ>(Boun_Cloud, singleColor, "sample");//显示点云,其中fildColor为颜色显示
	viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample");//设置点云大小

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

其对于凸包、凹包形状的点云数据均可以提取出,表现出较强的稳健性

 

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是基于合力的平面点云边缘提取的示例代码: ``` #include <iostream> #include <pcl/point_types.h> #include <pcl/features/normal_3d.h> #include <pcl/filters/extract_indices.h> #include <pcl/kdtree/kdtree_flann.h> #include <pcl/features/integral_image_normal.h> int main(int argc, char** argv) { // Load input point cloud pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile("input_cloud.pcd", *cloud); // Compute normals for all points pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; ne.setInputCloud(cloud); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>()); ne.setSearchMethod(tree); pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>); ne.setRadiusSearch(0.03); ne.compute(*cloud_normals); // Compute integral image normal for all points pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> ne_integral; ne_integral.setNormalEstimationMethod(ne_integral.AVERAGE_3D_GRADIENT); ne_integral.setMaxDepthChangeFactor(0.02f); ne_integral.setNormalSmoothingSize(10.0f); ne_integral.setInputCloud(cloud); pcl::PointCloud<pcl::Normal>::Ptr cloud_normals_integral(new pcl::PointCloud<pcl::Normal>); ne_integral.compute(*cloud_normals_integral); // Compute curvature for all points pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloud_curvature(new pcl::PointCloud<pcl::PointXYZINormal>); pcl::concatenateFields(*cloud, *cloud_normals_integral, *cloud_curvature); pcl::search::KdTree<pcl::PointXYZINormal>::Ptr tree_curvature(new pcl::search::KdTree<pcl::PointXYZINormal>); tree_curvature->setInputCloud(cloud_curvature); pcl::CurvatureEstimation<pcl::PointXYZINormal, pcl::PointXYZINormal> ce; ce.setInputCloud(cloud_curvature); ce.setSearchMethod(tree_curvature); ce.setRadiusSearch(0.03); ce.compute(*cloud_curvature); // Compute forces for all points pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_forces(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointXYZ force; for (int i = 0; i < cloud->size(); ++i) { pcl::PointXYZ& p = cloud->points[i]; pcl::Normal& n = cloud_normals_integral->points[i]; pcl::PointXYZINormal& c = cloud_curvature->points[i]; force.x = n.normal_x * c.curvature; force.y = n.normal_y * c.curvature; force.z = n.normal_z * c.curvature; cloud_forces->push_back(force); } // Extract edge points based on forces pcl::ExtractIndices<pcl::PointXYZ> extractor; pcl::IndicesPtr indices(new std::vector<int>); for (int i = 0; i < cloud->size(); ++i) { pcl::PointXYZ& p = cloud->points[i]; pcl::PointXYZ& f = cloud_forces->points[i]; if (f.norm() > 0.1) indices->push_back(i); } pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_edges(new pcl::PointCloud<pcl::PointXYZ>); extractor.setInputCloud(cloud); extractor.setIndices(indices); extractor.filter(*cloud_edges); // Save edge points to file pcl::io::savePCDFile("output_edges.pcd", *cloud_edges); return 0; } ``` 这段代码中,我们首先加载了一个点云输入文件,然后计算了每个的法向量和曲率。接着,我们通过计算每个的合力来判断它是否为边缘。最后,我们提取出所有的边缘,并将它们保存到一个输出文件中。需要注意的是,这段代码中只处理了平面点云,如果要处理曲面点云,还需要进行额外的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

点云实验室lab

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

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

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

打赏作者

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

抵扣说明:

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

余额充值