PCL-LCCP 点云分割

LCCP是Locally Convex Connected Patches的缩写

一、算法大致可以分成两个部分:

1.基于超体聚类的过分割。
2.在超体聚类的基础上再聚类。
超体聚类作为一种过分割方法,在理想情况下是不会引入错误信息的,也就是说适合在此基础上再进行处理。LCCP方法并不依赖于点云颜色,所以只使用空间信息和法线信息。

二、算法思路:

1.主要核心在CC(Extended Convexity Criterion) 和 SC (Sanity criterion)判据来进行判凹凸性
CC判据就是判别两个超体素的向量A和B与各自法向量之间的夹角,根据两个夹角对比进行判别
SC判据就是判别阈值与俩体素的夹角(这个夹角是通过求俩体素法向量的叉乘与中心连线d的夹角计算得来的)

2.在标记完各个小区域的凹凸关系后,则采用区域增长算法将小区域聚类成较大的物体。

3.至此,分割完成,在滤除多余噪声后即获得点云分割结果。

三、代码结构:

lccp_segmentation.cpp、lccp_segmentation.h、lccp_segmentation.hpp是PCL中LCCP的实现代码
mainwindow.cpp和mainwindow.h是QT窗口

在这里插入图片描述

mainwindow.cpp中默认参数:
粒子距离 = 0.0075f、晶核距离 = 0.3f 以及颜色容差 = 0.0f

    if(lineVoxel->text()!=NULL && 
        lineSeed->text()!=NULL){
        voxel_resolution = this->lineVoxel->text().toFloat();
        seed_resolution = this->lineSeed->text().toFloat();
	    color_importance = this->lineColor->text().toFloat();
    }
    else{
        voxel_resolution = 0.0075f;
		seed_resolution = 0.3f;
		color_importance = 0.0f;
    }

主要调用函数代码:void lccpSeg()

void mainwindow::lccpSeg()
{   
    clock_t startTime,endTime;
    startTime = clock();
    if(lineVoxel->text()!=NULL && 
        lineSeed->text()!=NULL){
        voxel_resolution = this->lineVoxel->text().toFloat();
        seed_resolution = this->lineSeed->text().toFloat();
	    color_importance = this->lineColor->text().toFloat();
    }
    else{
        voxel_resolution = 0.0075f;
	    seed_resolution = 0.3f;
	    color_importance = 0.0f;
    }
    //输入点云
	pcl::PointCloud<PointT>::Ptr input_cloud_ptr(new pcl::PointCloud<PointT>);
	pcl::PCLPointCloud2 input_pointcloud2;
	if (pcl::io::loadPCDFile("milk_cartoon_all_small_clorox.pcd", input_pointcloud2))
	{
		PCL_ERROR("ERROR: Could not read input point cloud ");
		return ;
	}
	pcl::fromPCLPointCloud2(input_pointcloud2, *input_cloud_ptr);
	PCL_INFO("Done making cloud\n");
	    float spatial_importance = 1.0f;
	float normal_importance = 4.0f;
	bool use_single_cam_transform = false;
	bool use_supervoxel_refinement = false;

	unsigned int k_factor = 0;
 
	//voxel_resolution is the resolution (in meters) of voxels used、seed_resolution is the average size (in meters) of resulting supervoxels  
	pcl::SupervoxelClustering<PointT> super(voxel_resolution, seed_resolution);
	super.setUseSingleCameraTransform(use_single_cam_transform);
	super.setInputCloud(input_cloud_ptr);
	//Set the importance of color for supervoxels. 
	super.setColorImportance(color_importance);
	//Set the importance of spatial distance for supervoxels.
	super.setSpatialImportance(spatial_importance);
	//Set the importance of scalar normal product for supervoxels. 
	super.setNormalImportance(normal_importance);
	std::map<uint32_t, pcl::Supervoxel<PointT>::Ptr> supervoxel_clusters;
 
	PCL_INFO("Extracting supervoxels\n");
	super.extract(supervoxel_clusters);
 
	PCL_INFO("Getting supervoxel adjacency\n");
	std::multimap<uint32_t, uint32_t> supervoxel_adjacency;
	super.getSupervoxelAdjacency(supervoxel_adjacency);
	pcl::PointCloud<pcl::PointNormal>::Ptr sv_centroid_normal_cloud = pcl::SupervoxelClustering<PointT>::makeSupervoxelNormalCloud(supervoxel_clusters);
	//LCCP分割
	float concavity_tolerance_threshold = 20;
	float smoothness_threshold = 0.1;
	uint32_t min_segment_size = 0;
	bool use_extended_convexity = false;
	bool use_sanity_criterion = false;
	PCL_INFO("Starting Segmentation\n");
	pcl::LCCPSegmentation<PointT> lccp;
	lccp.setConcavityToleranceThreshold(concavity_tolerance_threshold);
	lccp.setSmoothnessCheck(true, voxel_resolution, seed_resolution, smoothness_threshold);
	lccp.setKFactor(k_factor);
	lccp.setInputSupervoxels(supervoxel_clusters, supervoxel_adjacency);
	lccp.setMinSegmentSize(min_segment_size);
	lccp.segment();
	
	PCL_INFO("Interpolation voxel cloud -> input cloud and relabeling\n");
 
	pcl::PointCloud<pcl::PointXYZL>::Ptr sv_labeled_cloud = super.getLabeledCloud();
	pcl::PointCloud<pcl::PointXYZL>::Ptr lccp_labeled_cloud = sv_labeled_cloud->makeShared();
	lccp.relabelCloud(*lccp_labeled_cloud);
	SuperVoxelAdjacencyList sv_adjacency_list;
	lccp.getSVAdjacencyList(sv_adjacency_list);
	 // Configure Visualizer
    pcl::visualization::PCLVisualizer viewer = pcl::visualization::PCLVisualizer ("3D Viewer",false);
    viewer.addPointCloud (lccp_labeled_cloud, "Segmented point cloud");

	renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow = viewer.getRenderWindow();
    qvtk->SetRenderWindow(renderWindow);
    viewer.setupInteractor(qvtk->GetInteractor(),qvtk->GetRenderWindow());

    qvtk->update();
    qvtk->GetRenderWindow()->Render();
    endTime = clock();
    cout<<"The run time is :" << (double)(endTime-startTime)/CLOCKS_PER_SEC <<"s"<<endl;
}

显示效果:

在这里插入图片描述
代码地址:
https://github.com/excitin9/LCCPSeg

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HiramChen9

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

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

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

打赏作者

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

抵扣说明:

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

余额充值