PCL 计算点云凹包(2D及3D)(Surface_ConcaveHull)

PCL专栏目录及须知

凹包计算多用在二维上,三维使用较少。

1.凹包计算

alpha-shape算法:

对任意的点云P,用一个半径为α的圆在点集P外滚动,当α足够大时,这个圆就不会滚到点集内部,其滚动的痕迹就是点集P的边界线。

(1)将点云投影到平面,得到二维点集P。

(2)定义一个圆(即滚球),圆半径为alpha。

(3)从点集P中任取种子点pi,计算pi同点集P内各点间的距离,并将所有与点pi间距离小于滚球直径alpha * 2的点加入点集Q(初始边界点)。

(4)从点集Q内任取种子点qi,生成同时过点pi及qi的,半径为alpha的两个外接圆Cpi,Cqi。

(5)判断两个外接圆Cpi,Cqi,若其中任意一个外接圆内,不存在点集P中的其他点(即pi及qi处在一个滚球内),那么连接pi及qi,作为凹包的其中一条边。

(6)对点集Q中所有点,依次进行(4)(5)步骤,直到所有点被处理。

(7)对点集P中所有点,依次进行(3)-(6)步骤,直到所有点被处理。

(8)得到所有连接的线条,组合成为凹包。

2.使用场景

凹包使用较少。使用多为凸包。

3.关键函数

(1)凹包设置凹包是2d的还是3d的

surface_3d.setDimension(3);

(2)滚球法的半径,值越小,生成的凹包越细分

surface_3d.setAlpha(0.5);

4.完整代码

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/surface/concave_hull.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>

int main()
{
	/****************计算点云凹包********************/
	// 原始点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in_3d(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in_2d(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::io::loadPCDFile("D:/code/csdn/data/rabbit.pcd", *cloud_in_3d);   // 加载原始点云数据
	pcl::io::loadPCDFile("D:/code/csdn/data/plane.pcd", *cloud_in_2d);   // 加载原始点云数据
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out_3d(new pcl::PointCloud<pcl::PointXYZ>);   // 结果点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out_2d(new pcl::PointCloud<pcl::PointXYZ>);   // 结果点云

	// 计算凹包(3d)
	pcl::ConcaveHull<pcl::PointXYZ> surface_3d;						// 3d凹包
	surface_3d.setInputCloud(cloud_in_3d);
	surface_3d.setDimension(3);										// 凹包设置凹包是2d的还是3d的
	surface_3d.setAlpha(0.5);										// 值越小,生成的凹包越细分
	std::vector<pcl::Vertices> polygons_3d;							// 保存凹包顶点
	surface_3d.reconstruct(*cloud_out_3d, polygons_3d);				// 计算凹包

	// 计算凹包(2d)
	pcl::ConcaveHull<pcl::PointXYZ> surface_2d;						// 2d凹包
	surface_2d.setInputCloud(cloud_in_2d);
	surface_2d.setDimension(2);										// 凹包设置凹包是2d的还是3d的
	surface_2d.setAlpha(true);										// 值越小,生成的凹包越细分
	std::vector<pcl::Vertices> polygons_2d;							// 保存凹包顶点
	surface_2d.reconstruct(*cloud_out_2d, polygons_2d);				// 计算凹包

	/****************展示********************/
	// 3d
	// 模型
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer_3d(new pcl::visualization::PCLVisualizer("surface_3d"));
	viewer_3d->setBackgroundColor(0, 0, 0);
	viewer_3d->addPointCloud<pcl::PointXYZ>(cloud_in_3d, "cloud_3d");
	viewer_3d->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud_3d");
	// 3d凹包
	viewer_3d->addPolygonMesh<pcl::PointXYZ>(cloud_out_3d, polygons_3d, "polygons_3d");
	viewer_3d->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "polygons_3d");
	viewer_3d->setRepresentationToWireframeForAllActors();

	// 2d
	// 模型
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer_2d(new pcl::visualization::PCLVisualizer("surface_2d"));
	viewer_2d->setBackgroundColor(0, 0, 0);
	viewer_2d->addPointCloud<pcl::PointXYZ>(cloud_in_2d, "cloud_2d");
	viewer_2d->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud_2d");
	// 2d凹包
	viewer_2d->addPolygonMesh<pcl::PointXYZ>(cloud_out_2d, polygons_2d, "polygons_2d");
	viewer_2d->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "polygons_2d");
	viewer_2d->setRepresentationToWireframeForAllActors();

	while (!viewer_2d->wasStopped() || !viewer_3d->wasStopped())
	{

		viewer_2d->spinOnce(1000);
		viewer_3d->spinOnce(1000);
		boost::this_thread::sleep(boost::posix_time::microseconds(1000));

	}

	return 0;
}

5.结果展示

三维凹包

二维凹包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值