超体素分割——分割块点云单独保存及遗漏点的处理

根据上一篇博客介绍的超体素分割原理,在PCL中该功能以将其实现,并将其进行可视化。但是存在如下问题:(1)其将所有的块同时显示,对于很多其他应用,比如后续处理需要对每一块点单独进行操作,那么就需要将每个块点云单独抽取出来处理;(2)基于超体素分割,分割得到的点云块数据是远少于原始点的数据,其中与初始体素大小密切相关,初始体素体积越小,损失会小一点。这有点类似降采样,但实际一些分类中,是要保证在超体素处理前后,其总的点数是要保持不变的,因此这些没有化成超体素的点也需要单独抽取出,进行后续处理;(3)块与体素之间拓扑关系的构建。在一些若干处理中,如分类中,点之间的上下文信息与点之间的关系距离密切相关,而有些文献,如《An efficient global energy optimization approach for robust 3D plane segmentation of point clouds》中使用体素中心(或体素所有坐标的平均值)来表示体素,中心坐标一般位于体素中心位置,其与相邻体素之间的距离较远,在条件随机场中,根据距离计算而言,实际相邻的2个体素本身属于同一物体,但实际中可能由于距离太远而被错划分成不同地物。因此体素间相邻关系如何有效构建,也是值得研究的。

针对问题(1),即单独将分出的点云簇分开,代码如下:(PCL1.8

#include <pcl/console/parse.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/segmentation/supervoxel_clustering.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include<iostream>
//VTK include needed for drawing graph lines
#include <vtkPolyLine.h>
#include"IO.h"

using namespace pcl;
using namespace std;

typedef PointXYZ PointT;
typedef PointXYZL PointTL;

int main()
{
	IO IOExample;
	//--------------------加载点云--------------------------
	PointCloud<PointT>::Ptr cloud(new PointCloud<PointT>);
	char *inputpath = "..//测试数据//desk.txt";
	vector<pcl::PointXYZ> allpoints;
	allpoints = IOExample.ReadPointXYZIntoVector(inputpath);
	cloud->width = allpoints.size();
	cloud->height = 1;
	cloud->is_dense = false;
	cloud->resize(cloud->width*cloud->height);
	for (int i = 0; i < allpoints.size(); i++)
	{
		cloud->points[i].x = allpoints[i].x;
		cloud->points[i].y = allpoints[i].y;
		cloud->points[i].z = allpoints[i].z;
	}

	//------------------构建超体素--------------------------
	float voxel_resultion = 0.005f;
	float seed_resultion = 0.15f;
	float color_importance = 0.0f;
	float spatial_importance = 0.4f;
	float normal_importance = 5.0f;

	SupervoxelClustering<PointT> super(voxel_resultion, seed_resultion);
	super.setInputCloud(cloud);
	super.setNormalImportance(normal_importance);
	super.setColorImportance(color_importance);
	super.setSpatialImportance(spatial_importance);
	std::map<uint32_t, Supervoxel<PointT>::Ptr >supervoxl_clustering;
	super.extract(supervoxl_clustering);

	cout << "supervoxel number is " << supervoxl_clustering.size() << endl;

	ofstream outfile("..//测试数据//supervoxel_缺点.txt", ios::out);
	srand((int)time(0));
	for (auto label_itr = supervoxl_clustering.cbegin(); label_itr != supervoxl_clustering.cend(); label_itr++)
	{
		double r = rand() % 255;
		double g = rand() % 255;
		double b = rand() % 255;
		int super_label = label_itr->first;

		Supervoxel<PointT>::Ptr super_cloud = supervoxl_clustering.at(super_label);

		for (int j = 0; j < super_cloud->voxels_->points.size(); j++)
		{
			outfile << fixed << setprecision(3) << super_cloud->voxels_->points[j].x << "\t" << super_cloud->voxels_->points[j].y << "\t" << super_cloud->voxels_->points[j].z <<
				"\t" << fixed << setprecision(0) << r << "\t" << g << "\t" << b << endl;
		}
	}

	
	outfile.close();

	return 0;
}

 

 可以发现,其实有相当部分的点没有划分到超体素中

(2)第二个问题,PCL中其实是有将没有划分到体素中的点进行单独保存的情况,只是很少有博主对其仔细进行研究。将所有点进行保存,其代码如下:

#include <pcl/console/parse.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/segmentation/supervoxel_clustering.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include<iostream>
//VTK include needed for drawing graph lines
#include <vtkPolyLine.h>
#include"IO.h"

using namespace pcl;
using namespace std;

typedef PointXYZ PointT;
typedef PointXYZL PointTL;


void main()
{
	IO IOExample;
	//--------------------加载点云--------------------------
	PointCloud<PointT>::Ptr cloud(new PointCloud<PointT>);
	char strpath[] = "..//测试数据//desk.txt";
	char* path = strpath;
	vector<pcl::PointXYZ> allpoints;
	allpoints = IOExample.ReadPointXYZIntoVector(path);
	cloud->width = allpoints.size();
	cloud->height = 1;
	cloud->is_dense = false;
	cloud->resize(cloud->width * cloud->height);
	for (int i = 0; i < allpoints.size(); i++)
	{
		cloud->points[i].x = allpoints[i].x;
		cloud->points[i].y = allpoints[i].y;
		cloud->points[i].z = allpoints[i].z;
	}

	//------------------构建超体素--------------------------
	float voxel_resultion = 0.005f;
	float seed_resultion = 0.15f;
	float color_importance = 0.0f;
	float spatial_importance = 0.4f;
	float normal_importance = 5.0f;

	SupervoxelClustering<PointT> super(voxel_resultion, seed_resultion);
	super.setInputCloud(cloud);
	super.setNormalImportance(normal_importance);
	super.setColorImportance(color_importance);
	super.setSpatialImportance(spatial_importance);
	std::map<uint32_t, Supervoxel<PointT>::Ptr >supervoxl_clustering;
	super.extract(supervoxl_clustering);

	pcl::PointCloud<pcl::PointXYZL>::Ptr supervoxel_cloud = super.getLabeledCloud();

	int begin = 0;

	//遍历体素获取体素内点的索引,根据索引提取分割后的点云

	ofstream outfile("..//测试数据//supervoxel_不缺点.txt", ios::out);
	struct segpoints
	{
		vector<pcl::PointXYZ> points;
	};

	vector<segpoints> allsegs;
	allsegs.resize(supervoxl_clustering.size());

	vector<pcl::PointXYZ> nonsegs;

	for (int i = 0; i < supervoxel_cloud->points.size(); i++)
	{
		double idlabel = supervoxel_cloud->points[i].label;

		pcl::PointXYZ tempoint;
		tempoint.x = supervoxel_cloud->points[i].x;
		tempoint.y = supervoxel_cloud->points[i].y;
		tempoint.z = supervoxel_cloud->points[i].z;
		if (idlabel > 0 && idlabel <= supervoxl_clustering.size())
		{
			allsegs[idlabel - 1].points.push_back(tempoint);
		}
		else
		{
			nonsegs.push_back(tempoint);
		}
	}

	//进行保存

	for (int i = 0; i < nonsegs.size(); i++)
	{
		outfile << fixed << setprecision(3) << nonsegs[i].x << "\t" << nonsegs[i].y << "\t" << nonsegs[i].z << "\t" << fixed << setprecision(0) << 255 << "\t" << 255 << "\t" << 255 << endl;
	}

	for (int i = 0; i < allsegs.size(); i++)
	{
		double r = rand() % 255;
		double g = rand() % 255;
		double b = rand() % 255;
		for (int j = 0; j < allsegs[i].points.size(); j++)
		{
			outfile << fixed << setprecision(3) << allsegs[i].points[j].x << "\t" << allsegs[i].points[j].y << "\t" << allsegs[i].points[j].z <<
				"\t" << fixed << setprecision(0) << r << "\t" << g << "\t" << b << endl;
		}
	}
	outfile.close();
	cout << "结束" << endl;
	system("pause");

}

 

  

 其实可以发现,这样进行超体素划分,体素块之间存在一些将不属于同一面片的点,划分到同一体素当中,这存在明显的。从同一平面上看(左一),相邻面片之间的点全部划分到对应的体素中去了

对于(3)个问题,目前还没有好的解决方案,按照之前博客来说,其包括如下方法,使用近邻点构建体素与体素、体素与单个点之间的关系;或者使用中心点来表示。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

点云实验室lab

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

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

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

打赏作者

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

抵扣说明:

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

余额充值