【PCL】——点云凸包检测 ConvexHull 和 CropHull 滤波

参考:

  1. https://blog.csdn.net/rocachilles/article/details/95199316
  2. https://blog.csdn.net/m0_37914211/article/details/102855498
  3. https://blog.csdn.net/zfjBIT/article/details/92795689

1. Convex Hull 凸包顶点求解:

  • 点云凸包检测还是比较常用的,PCL自带的凸包检测 ConvexHull ,这个函数比较简单,设置凸包维度 setDimension即可:
// 生成凸包与计算体积:

// 头文件:
#include 

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile<pcl::PointXYZ>("bun_45.pcd", *cloud);

pcl::ConvexHull<pcl::PointXYZ> hull;                  
hull.setInputCloud(cloud);                   
hull.setDimension(3);  // 设置凸包维度
hull.setComputeAreaVolume(true);

std::vector<pcl::Vertices> polygons;    
// polygons保存的是所有凸包多边形的顶点在surface_hull中的下标
pcl::PointCloud<pcl::PointXYZ>::Ptr surface_hull(new pcl::PointCloud<pcl::PointXYZ>);
// surface_hull是所有凸包多边形的顶点
hull.reconstruct(*surface_hull, polygons);  
//凸包点云存放在surface_hull中,polygons中的Vertices存放一组点的索引,索引是surface_hull中的点对应的索引

double convex_volume = hull.getTotalvolume();

cout << surface_hull->size() << endl;
cout << "凸包体积: " << convex_volume << endl;

// ---------------------- Visualizer -------------------------------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer);
viewer->setBackgroundColor(255,255,255);

pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color_handler(cloud, 255, 255, 0);
viewer->addPointCloud(cloud, color_handler, "sample cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 6, "sample cloud");

pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color_handlerK(surface_hull, 255, 0, 0);
viewer->addPointCloud(surface_hull, color_handlerK, "point");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 6, "point");

//viewer->addPolygon(surface_hull, 0, 0, 255, "polyline");

while (!viewer->wasStopped())
{
	viewer->spinOnce(100);
}

采用斯坦福小兔点云,效果如图:
【PCL】——点云凸包检测 ConvexHull 和 CropHull 滤波_第1张图片
如果进一步将某个确定的凸包中的点云从场景分割出来,可以采用 CropHull 进行滤波。

2. CropHull 滤波器:

  • CropHull滤波器得到2D封闭多边形内部或者外部的点云。
pcl::CropHull< PointT >
void setHullIndices (const std::vector< Vertices > &polygons)
// 输入封闭多边形的顶点;

void setHullCloud (PointCloudPtr points)
// 输入封闭多边形的形状;

void setDim (int dim)
// 设置维度:该维度需要与凸包维度一致;

void setCropOutside (bool crop_outside)
// 设置保留封闭多边形的内点or外点:默认保留内点;

示例:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PCDReader reader;
	reader.read("..\\source\\pig.pcd"/*argv[1]*/,*cloud);
 
	//定义2D平面点云
	pcl::PointCloud<pcl::PointXYZ>::Ptr boundingbox_ptr (new pcl::PointCloud<pcl::PointXYZ>);
	boundingbox_ptr->push_back(pcl::PointXYZ(0.1, 0.1, 0));
	boundingbox_ptr->push_back(pcl::PointXYZ(0.1, -0.1,0 ));
	boundingbox_ptr->push_back(pcl::PointXYZ(-0.1, 0.1,0 ));
	boundingbox_ptr->push_back(pcl::PointXYZ(-0.1, -0.1,0 ));
	boundingbox_ptr->push_back(pcl::PointXYZ(0.15, 0.1,0 ));
 
	pcl::ConvexHull<pcl::PointXYZ> hull;                  //创建凸包对象
	hull.setInputCloud(boundingbox_ptr);                  //设置输入点云
	hull.setDimension(2);                                 //设置凸包维度
	std::vector<pcl::Vertices> polygons;                  //设置向量,用于保存凸包定点
	pcl::PointCloud<pcl::PointXYZ>::Ptr surface_hull (new pcl::PointCloud<pcl::PointXYZ>);//该点运用于描述凸包形状
	hull.reconstruct(*surface_hull, polygons);            //计算2D凸包结果
 
	pcl::PointCloud<pcl::PointXYZ>::Ptr objects (new pcl::PointCloud<pcl::PointXYZ>);
	pcl::CropHull<pcl::PointXYZ> bb_filter;               //创建crophull对象
	bb_filter.setDim(2);                                  //设置维度:该维度需要与凸包维度一致
	bb_filter.setInputCloud(cloud);                       //设置需要滤波的点云
	bb_filter.setHullIndices(polygons);                   //输入封闭多边形的顶点
	bb_filter.setHullCloud(surface_hull);                 //输入封闭多边形的形状
	bb_filter.filter(*objects);                           //执行CropHull滤波,存出结果在objects
	std::cout << objects->size() << std::endl;            //
 
	//visualize
	boost::shared_ptr<pcl::visualization::PCLVisualizer> for_visualizer_v (new pcl::visualization::PCLVisualizer ("crophull display"));
	for_visualizer_v->setBackgroundColor(255,255,255);
 
	int v1(0);//显示原始点云
	for_visualizer_v->createViewPort (0.0, 0.0, 0.33, 1, v1);
	for_visualizer_v->setBackgroundColor (255, 255, 255, v1);
	for_visualizer_v->addPointCloud (cloud,"cloud",v1);
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,255,0,0,"cloud");
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,3,"cloud");
	for_visualizer_v->addPolygon<pcl::PointXYZ>(surface_hull,0,.069*255,0.2*255,"backview_hull_polyline1",v1);
 
	int v2(0);//显示封闭2D多边形凸包
	for_visualizer_v->createViewPort (0.33, 0.0, 0.66, 1, v2);	
	for_visualizer_v->setBackgroundColor (255, 255, 255, v2);
	for_visualizer_v->addPointCloud (surface_hull,"surface_hull",v2);
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,255,0,0,"surface_hull");
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,8,"surface_hull");
	for_visualizer_v->addPolygon<pcl::PointXYZ>(surface_hull,0,.069*255,0.2*255,"backview_hull_polyline",v2);
	// addPolygon函数:添加表示输入点云的多边形(折线、全部连接)
 
	int v3(0);//显示滤波结果
	for_visualizer_v->createViewPort (0.66, 0.0, 1, 1, v3);
	for_visualizer_v->setBackgroundColor (255, 255, 255, v3);
	for_visualizer_v->addPointCloud (objects,"objects",v3);
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,255,0,0,"objects");
	for_visualizer_v->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,3,"objects");
 
	while (!for_visualizer_v->wasStopped())
	{
		for_visualizer_v->spinOnce(1000);
	}
	system("pause");
}

显示如图:
【PCL】——点云凸包检测 ConvexHull 和 CropHull 滤波_第2张图片

你可能感兴趣的:(计算机视觉)