PCL常用可视化/滤波/分割等函数的封装

本文档详细介绍了PCL库中用于点云处理的各种函数,包括点云的可视化、滤波、分割等操作。通过示例代码展示了如何使用头文件function.h和源文件function.cpp中的函数,如直通滤波、体素滤波、随机采样一致(RANSAC)分割、欧式聚类分割等。此外,还提供了多窗口显示不同类型的点云以及点云显示的视角设置。
摘要由CSDN通过智能技术生成

1. 头文件 function.h

#pragma once
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/common/impl/io.hpp>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/ModelCoefficients.h>             //模型系数头文件
#include <pcl/filters/project_inliers.h>          //投影滤波类头文件
#include <pcl/console/parse.h>
#include <pcl/io/io.h>
#include <pcl/io/ply_io.h>
#include <pcl/common/io.h>
#include <pcl/common/centroid.h>
#include <pcl/common/common.h>
#include <pcl/common/transforms.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h>
#include <pcl/range_image/range_image.h>
#include <pcl/features/normal_3d.h>

#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/filters/extract_indices.h>	//根据索引提取内点
#include <pcl/filters/voxel_grid.h> //体素滤波
#include <pcl/keypoints/uniform_sampling.h> //均匀采样滤波
#include <pcl/compression/octree_pointcloud_compression.h>   //点云压缩类
#include <pcl/filters/model_outlier_removal.h>//模型滤波
#include <pcl/filters/convolution_3d.h>//高斯滤波
#include <pcl/filters/bilateral.h>//双边滤波
#include <pcl/filters/fast_bilateral.h>  
#include <pcl/filters/crop_hull.h>
#include <pcl/surface/concave_hull.h>
#include <pcl/ModelCoefficients.h>//模型系数相关头文件
#include <pcl/sample_consensus/method_types.h>//模型定义头文件
#include <pcl/sample_consensus/model_types.h>//随机参数估计方法头文件
#include <pcl/segmentation/sac_segmentation.h>//基于采样一致性分割的类的头文件
#include <pcl/segmentation/extract_clusters.h>//欧式聚类分割相关头文件
#include <pcl/segmentation/conditional_euclidean_clustering.h>//条件欧式聚类
#include <pcl/segmentation/region_growing.h>//区域生长分割
#include <pcl/segmentation/region_growing_rgb.h>//颜色区域生长分割
#include <pcl/segmentation/min_cut_segmentation.h>//最小图割
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/features/don.h>
#include <pcl/segmentation/impl/extract_clusters.hpp>//法线微分分割
#include <pcl/segmentation/supervoxel_clustering.h>//超体素分割
#include <pcl/features/boundary.h>//边缘提取
#include <pcl/console/time.h>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/opencv.hpp"  //头文件
#include "opencv2/features2d.hpp"
#include "opencv2/imgproc/types_c.h"
//vtk
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include "vtkAutoInit.h" 
#include <vector>
#include <string>
#include <Windows.h>
#include <iostream>
#include <stdio.h>

class PCLfunction
{
public:

	double getMaxValue(pcl::PointXYZ p1, pcl::PointXYZ p2);
	double maxLen;

public:
	//一.点云显示相关函数

	//1.点云可视化及视角设置
	void visualization(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, int mode);
	//1.2显示XYZRGB点云
	void visualization1(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud);
	//2.多窗口显示
	void visualization2wd(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2);
	//2.2多窗口显示XYZI点云
	void visualization2wd1(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud1, pcl::PointCloud<pcl::PointXYZI>::Ptr cloud2);
	//2.3多窗口显示不同类型点云
	void visualization2wd2(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1, pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud2);
	//2.4多窗口显示XYZRGB类型点云
	void visualization2wd3(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud1, pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud2);
	//3.依次显示点云
	void visualizationCon(pcl::PointCloud<pcl::PointXYZ>::Ptr data[]);

	//二.点云滤波常用函数

	//1.直通滤波
	void PassThrough(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, float min, float max, int mode);
	//2.体素滤波 以正方体质心下采样
	void VoxelGrid(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, float a);
	//3.均匀采样滤波 以球内最接近中心的点下采样
	void UniformSampling(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, double r);
	//4.statisticalOutlierRemoval统计滤波 去除离散点
	void StatisticalOutlierRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, int k, double sigma);
	//5.RadiusOutlierRemoval半径滤波
	void RadiusOutlierRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, double r, int n);
	//6.ConditionalRemoval条件滤波
	void ConditionalRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, int mode, double a, double b);
	//7.投影滤波 
	void ProjectInliers(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud);
	//8.模型滤波
	void ModelOutlierRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, float thresh);
	//9.高斯滤波
	void Gaussian(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud);
	//10.双边滤波
	void BilateralFilter(pcl::PointCloud<pcl::PointXYZI>::Ptr incloud, pcl::PointCloud<pcl::PointXYZI>::Ptr outcloud, double sigma_s, double sigma_r);
	//11.索引提取
	void ExtractIndices(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, std::vector<int> index);
	//12.CropHull滤波
	void CropHull(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud);

	//三.点云分割

	//1.随机采样一致(RANSAC)
	void RANSAC(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud);
	//2.欧式聚类分割
	void EuclideanClusterExtraction(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud);
	//3.条件欧式聚类分割
	//void ConditionalEuclideanClustering(pcl::PointCloud<pcl::PointXYZI>::Ptr incloud, pcl::PointCloud<pcl::PointXYZI>::Ptr outcloud, int Method);
	//4.基于区域生长分割
	void RegionGrowing(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::Normal>::Ptr cloud_normals, pcl::PointCloud<pcl::PointXYZRGB>::Ptr outcloud);
	//5.基于颜色的区域生长分割
	void RegionGrowingRGB(pcl::PointCloud<pcl::PointXYZRGB>::Ptr incloud, pcl::PointCloud<pcl::PointXYZRGB>::Ptr outcloud);
	//6.最小图割
	void MinCutSegmentation(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZRGB>::Ptr outcloud);
	//7.基于法线微分分割
	void DifferenceOfNormalsEstimation(pcl::PointCloud<pcl::PointXYZRGB>::Ptr incloud);
	//8.基于超体素分割
	void SupervoxelClustering(pcl::PointCloud<pcl::PointXYZRGBA>::Ptr incloud);

	//其他

	//1.计算点云法线
	void NormalEstimation(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::Normal>::Ptr cloud_normals);
	//2.边缘提取
	void EstimateBoundary(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::Boundary>& boundaries);
	//3.将txt形式的点云格式转换为pcl::PointXYZ格式
	void CreateCloudFromTxt(const std::string& file_path, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud);
	//4.圆柱拟合
	void CircularColumn(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::PointXYZ > ::Ptr outcloud);
	//5.2D圆拟合
	void Circle2D(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud);
	//6.去除NAN点
	void removeNan(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud);
	//7.拟合球

	//8.计算点云平均密度
	float kdTreeSearch(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, int k);


};

2. 源文件 function.cpp

  • 能够实现一些较为基础的可视化/滤波/分割等操作,代码也基本都注释,要用哪个模块的功能直接将函数复制出来即可
  • 由于是之前刚接触时写的也许会存在一些不好的地方还望指出
  • 直接运行switch语句选择操作时先将点云的路径地址更改为自己的,其次注意输入输出参数的点云类型要一致,也就是说弹出窗口让选择点云时应当仔细观察点云的类型是否相同,不是每个选项组合都能出结果
#include "function.h"

//定义颜色数组用于可视化
float colors[] = {
	255, 0,   0,   // red 		1
	0,   255, 0,   // green		2
	0,   0,   255, // blue		3
	255, 255, 0,   // yellow	4
	0,   255, 255, // light blue5
	255, 0,   255, // magenta   6
	255, 255, 255, // white		7
	255, 128, 0,   // orange	8
	255, 153, 255, // pink		9
	51,  153, 255, //			10
	153, 102, 51,  //			11
	128, 51,  153, //			12
	153, 153, 51,  //			13
	163, 38,  51,  //			14
	204, 153, 102, //			15
	204, 224, 255, //			16
	128, 179, 255, //			17
	206, 255, 0,   //			18
	255, 204, 204, //			19
	204, 255, 153, //			20
};
pcl::PointXYZ p_min, p_max;
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
pcl::search::KdTree<pcl::PointXYZI>::Ptr tree1(new pcl::search::KdTree<pcl::PointXYZI>);
pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree2(new pcl::search::KdTree<pcl::PointXYZRGB>);

//条件欧式设置条件函数1 如果此函数返回true,则将添加候选点到种子点的簇类中
bool enforceIntensitySimilarity(const pcl::PointXYZINormal& point_a, const pcl::PointXYZINormal& point_b, float squared_distance)
{
	if (fabs((float)point_a.intensity - (float)point_b.intensity) < 5.0f)
		return (true);
	else
		return (false);
}
//设置条件函数2
bool enforceCurvatureOrIntensitySimilarity(const pcl::PointXYZINormal& point_a, const pcl::PointXYZINormal& point_b, float squared_distance)
{
	//Eigen::Map<const Eigen::Vector3f> point_a_normal = point_a.normal, point_b_normal = point_b.normal;
	Eigen::Map<const Eigen::Vector3f> point_a_normal = point_a.getNormalVector3fMap(), point_b_normal = point_b.getNormalVector3fMap();
	if (fabs((float)point_a.intensity - (float)point_b.intensity) < 5.0f)
		return (true);
	if (fabs(point_a_normal.dot(point_b_normal)) < 0.05)
		return (true);
	return (false);
}
//设置条件函数3
bool customRegionGrowing(const pcl::PointXYZINormal& point_a, const pcl::PointXYZINormal& point_b, float squared_distance)
{
	//Eigen::Map<const Eigen::Vector3f> point_a_normal = point_a.normal, point_b_normal = point_b.normal;
	Eigen::Map<const Eigen::Vector3f> point_a_normal = point_a.getNormalVector3fMap(), point_b_normal = point_b.getNormalVector3fMap();
	if (squared_distance < 10000)
	{
		if (fabs((float)point_a.intensity - (float)point_b.intensity) < 8.0f)
			return (true);
		if (fabs(point_a_normal.dot(point_b_normal)) < 0.06)
			return (true);
	}
	else
	{
		if (fabs((float)point_a.intensity - (float)point_b.intensity) < 3.0f)
			return (true);
	}
	return (false);
}

//一.点云显示

//1.点云可视化及视角设置
void PCLfunction::visualization(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,int mode)
{
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("点云显示"));

	//可以对点云设置一个统一的颜色
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 255, 0);
	//对点云进行渲染
	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud, "x");
	viewer->addPointCloud<pcl::PointXYZ>(cloud, fildColor, "example");
	//最后一个参数为添加的点云的id
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "example");
	//设置相机视角可以依据点云进行调节
	pcl::getMinMax3D(*cloud, p_min, p_max);
	maxLen = getMaxValue(p_max, p_min);
	//根据输入的模式选择初始展示的方位
	switch (mode)
	{
	case 1:
		//俯视图
		viewer->setCameraPosition(0.5*(p_min.x + p_max.x), 0.5*(p_min.y + p_max.y), p_max.z + 2 * maxLen, 0.5*(p_min.x + p_max.x), 0.5*(p_min.y + p_max.y), p_max.z, 0, 1, 0);
		break;
	case 2:
		//底视图
		viewer->setCameraPosition(0.5*(p_min.x + p_max.x), 0.5*(p_min.y + p_max.y), p_min.z - 2 * maxLen, 0.5*(p_min.x + p_max.x), 0.5*(p_min.y + p_max.y), p_min.z, 0, 1, 0);
		break;
	case 3:
		//前视图
		viewer->setCameraPosition(0.5*(p_min.x + p_max.x), p_min.y - 2 * maxLen, 0.5*(p_min.z + p_max.z), 0.5*(p_min.x + p_max.x), p_min.y, 0.5*(p_min.z + p_max.z), 0, 0, 1);
		break;
	case 4:
		//后视图
		viewer->setCameraPosition(0.5*(p_min.x + p_max.x), p_max.y + 2 * maxLen, 0.5*(p_min.z + p_max.z), 0.5*(p_min.x + p_max.x), p_min.y, 0.5*(p_min.z + p_max.z), 0, 0, 1);
		break;
	case 5:
		//左视图
		viewer->setCameraPosition(p_min.x - 2 * maxLen, 0.5*(p_min.y + p_max.y), 0.5*(p_min.z + p_max.z), p_max.x, 0.5*(p_min.y + p_max.y), 0.5*(p_min.z + p_max.z), 0, 0, 1);
		break;
	case 6:
		//右视图
		viewer->setCameraPosition(p_max.x + 2 * maxLen, 0.5*(p_min.y + p_max.y), 0.5*(p_min.z + p_max.z), p_max.x, 0.5*(p_min.y + p_max.y), 0.5*(p_min.z + p_max.z), 0, 0, 1);
		break;
	default:
		viewer->resetCamera();

	}

	//这个控制放大
	viewer->setCameraFieldOfView(0.5);
	viewer->setCameraClipDistances(0.1, 572);
	viewer->setCameraPosition(-1, 0, 0, 0, 0, 0, 0, 0, 1);
	//viewer->spinOnce();
	while (!viewer->wasStopped()) {
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}
}
//计算点云最大最小点组成的长方体中的最长边
double PCLfunction::getMaxValue(pcl::PointXYZ p1, pcl::PointXYZ p2)
{
	double max = 0;

	if (p1.x - p2.x > p1.y - p2.y)
	{
		max = p1.x - p2.x;

	}
	else
	{
		max = p1.y - p2.y;
	}

	if (max < p1.z - p2.z)
	{
		max = p1.z - p2.z;
	}

	return max;
}
//1.2显示XYZRGB点云
void PCLfunction::visualization1(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud)
{
	//创建3D窗口并添加点云    
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
	viewer->setBackgroundColor(0, 0, 0);
	pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud); //使用cloud的rgb 或者 rgba
	viewer->addPointCloud<pcl::PointXYZRGB>(cloud, rgb, "sample cloud");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud"); //变量名,赋值
	viewer->addCoordinateSystem(1.0);
	viewer->resetCamera();
	viewer->initCameraParameters();
	//viewer->spinOnce();
	while (!viewer->wasStopped()) {
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}
}
//2.两个窗口显示
void PCLfunction::visualization2wd(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2)
{
	//可视化
	boost::shared_ptr<pcl::visualization::PCLVisualizer> MView(new pcl::visualization::PCLVisualizer("处理效果"));
	//int v1, v2, v3, v4;
	//viewer->createViewPort(0.0, 0.0, 0.5, 0.5, v1); //(Xmin,Ymin,Xmax,Ymax)设置窗口坐标
	//viewer->createViewPort(0.5, 0.0, 1.0, 0.5, v2);
	//viewer->createViewPort(0.0, 0.5, 0.5, 1.0, v3);
	//viewer->createViewPort(0.5, 0.5, 1.0, 1.0, v4);

	int v1(0);
	MView->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
	MView->setBackgroundColor(0, 0, 0, v1);
	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud1, "x"); // 按照x字段进行渲染
	MView->addText("before", 10, 10, "v1_text", v1);
	int v2(0);
	MView->createViewPort(0.5, 0.0, 1, 1.0, v2);
	MView->setBackgroundColor(0, 0, 0, v2);
	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor2(cloud2, "x"); // 按照x字段进行渲染
	MView->addText("after", 10, 10, "v2_text", v2);
	MView->addPointCloud<pcl::PointXYZ>(cloud1, fildColor, "sample cloud", v1);
	MView->addPointCloud<pcl::PointXYZ>(cloud2, fildColor2, "cloud", v2);
	//MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "sample cloud", v1);
	//MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_boundary", v2);
	MView->addCoordinateSystem(0.1);
	//最后调用通过设置相机参数使用户从默认的角度和方向观察点云
	MView->initCameraParameters();
	MView->resetCamera();
	MView->spin();
	while (!MView->wasStopped())
	{
		MView->spinOnce(1000);
		boost::this_thread::sleep(boost::posix_time::microseconds(1000));
	}
}
//2.2两个窗口显示XYZI类型的点云
void PCLfunction::visualization2wd1(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud1, pcl::PointCloud<pcl::PointXYZI>::Ptr cloud2)
{
	//可视化
	boost::shared_ptr<pcl::visualization::PCLVisualizer> MView(new pcl::visualization::PCLVisualizer("处理效果"));
	//int v1, v2, v3, v4;
	//viewer->createViewPort(0.0, 0.0, 0.5, 0.5, v1); //(Xmin,Ymin,Xmax,Ymax)设置窗口坐标
	//viewer->createViewPort(0.5, 0.0, 1.0, 0.5, v2);
	//viewer->createViewPort(0.0, 0.5, 0.5, 1.0, v3);
	//viewer->createViewPort(0.5, 0.5, 1.0, 1.0, v4);

	int v1(0);
	MView->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
	MView->setBackgroundColor(0, 0, 0, v1);
	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> fildColor(cloud1, "x"); // 按照x字段进行渲染
	MView->addText("before", 10, 10, "v1_text", v1);
	int v2(0);
	MView->createViewPort(0.5, 0.0, 1, 1.0, v2);
	MView->setBackgroundColor(0.2, 0.2, 0.2, v2);
	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> fildColor2(cloud2, "x"); // 按照x字段进行渲染
	MView->addText("after", 10, 10, "v2_text", v2);
	MView->addPointCloud<pcl::PointXYZI>(cloud1, fildColor, "sample cloud", v1);
	MView->addPointCloud<pcl::PointXYZI>(cloud2, fildColor2, "cloud", v2);
	//MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "sample cloud", v1);
	//MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud", v2);
	MView->addCoordinateSystem(0.1);
	//最后调用通过设置相机参数使用户从默认的角度和方向观察点云
	MView->initCameraParameters();
	MView->resetCamera();
	MView->spin();
	while (!MView->wasStopped())
	{
		MView->spinOnce(1000);
		boost::this_thread::sleep(boost::posix_time::microseconds(1000));
	}
}
//2.3多窗口显示不同类型点云
void PCLfunction::visualization2wd2(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1, pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud2)
{
	//可视化
	boost::shared_ptr<pcl::visualization::PCLVisualizer> MView(new pcl::visualization::PCLVisualizer("处理效果"));
	//int v1, v2, v3, v4;
	//viewer->createViewPort(0.0, 0.0, 0.5, 0.5, v1); //(Xmin,Ymin,Xmax,Ymax)设置窗口坐标
	//viewer->createViewPort(0.5, 0.0, 1.0, 0.5, v2);
	//viewer->createViewPort(0.0, 0.5, 0.5, 1.0, v3);
	//viewer->createViewPort(0.5, 0.5, 1.0, 1.0, v4);

	int v1(0);
	MView->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
	MView->setBackgroundColor(0, 0, 0, v1);
	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud1, "x"); // 按照x字段进行渲染
	MView->addText("before", 10, 10, "v1_text", v1);
	int v2(0);
	MView->createViewPort(0.5, 0.0, 1, 1.0, v2);
	MView->setBackgroundColor(0.2, 0.2, 0.2, v2);
	//pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZRGB> fildColor2(cloud2, "x"); // 按照x字段进行渲染
	pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud2);
	MView->addText("after", 10, 10, "v2_text", v2);
	MView->addPointCloud<pcl::PointXYZ>(cloud1, fildColor, "sample cloud", v1);
	MView->addPointCloud<pcl::PointXYZRGB>(cloud2, rgb, "cloud", v2);
	MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud", v1);
	MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud", v2);
	//MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "sample cloud", v1);
	//MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_boundary", v2);
	MView->addCoordinateSystem(0.1);
	//最后调用通过设置相机参数使用户从默认的角度和方向观察点云
	MView->initCameraParameters();
	MView->resetCamera();
	MView->spin();
	while (!MView->wasStopped())
	{
		MView->spinOnce(1000);
		boost::this_thread::sleep(boost::posix_time::microseconds(1000));
	}
}
//2.4多窗口显示XYZRGB类型点云
void PCLfunction::visualization2wd3(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud1, pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud2)
{
	//可视化
	boost::shared_ptr<pcl::visualization::PCLVisualizer> MView(new pcl::visualization::PCLVisualizer("处理效果"));
	//int v1, v2, v3, v4;
	//viewer->createViewPort(0.0, 0.0, 0.5, 0.5, v1); //(Xmin,Ymin,Xmax,Ymax)设置窗口坐标
	//viewer->createViewPort(0.5, 0.0, 1.0, 0.5, v2);
	//viewer->createViewPort(0.0, 0.5, 0.5, 1.0, v3);
	//viewer->createViewPort(0.5, 0.5, 1.0, 1.0, v4);

	int v1(0);
	MView->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
	MView->setBackgroundColor(0, 0, 0, v1);
	pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud2);
	//pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud1, "x"); // 按照x字段进行渲染
	MView->addText("before", 10, 10, "v1_text", v1);
	int v2(0);
	MView->createViewPort(0.5, 0.0, 1, 1.0, v2);
	MView->setBackgroundColor(0.2, 0.2, 0.2, v2);
	//pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZRGB> fildColor2(cloud2, "x"); // 按照x字段进行渲染
	pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb1(cloud2);
	MView->addText("after", 10, 10, "v2_text", v2);
	MView->addPointCloud<pcl::PointXYZRGB>(cloud1, rgb, "sample cloud", v1);
	MView->addPointCloud<pcl::PointXYZRGB>(cloud2, rgb1, "cloud", v2);
	MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud", v1);
	MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud", v2);
	//MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "sample cloud", v1);
	//MView->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_boundary", v2);
	MView->addCoordinateSystem(0.1);
	//最后调用通过设置相机参数使用户从默认的角度和方向观察点云
	MView->initCameraParameters();
	MView->resetCamera();
	MView->spin();
	while (!MView->wasStopped())
	{
		MView->spinOnce(1000);
		boost::this_thread::sleep(boost::posix_time::microseconds(1000));
	}
}
//3.依次显示点云
void PCLfunction::visualizationCon(pcl::PointCloud<pcl::PointXYZ>::Ptr data[])
{
	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>);
	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2(new pcl::PointCloud<pcl::PointXYZ>);
	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud3(new pcl::PointCloud<pcl::PointXYZ>);
	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud4(new pcl::PointCloud<pcl::PointXYZ>);
	//pcl::io::loadPCDFile("rabbit.pcd", *cloud1);
	//pcl::io::loadPCDFile("01.pcd", *cloud2);
	//pcl::io::loadPCDFile("box.pcd", *cloud3);
	//pcl::io::loadPCDFile("box_1.pcd", *cloud4);
	//pcl::PointCloud<pcl::PointXYZ>::Ptr data[] = { cloud1,cloud2,cloud3,cloud4 };

	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
	viewer->setBackgroundColor(0, 0, 0);
	viewer->addPointCloud<pcl::PointXYZ>(data[0], "sample cloud");
	//viewer->addPointCloud<pcl::PointXYZ>(cloud2, "sample cloud1");
	//viewer->addPointCloud<pcl::PointXYZ>(cloud2, "sample cloud2");
	//viewer->addPointCloud<pcl::PointXYZ>(cloud2, "sample cloud3");
	//viewer->removePointCloud("sample cloud1");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");
	viewer->addCoordinateSystem(1.0);
	viewer->resetCamera();
	viewer->initCameraParameters();

	int i = 0;
	while (!viewer->wasStopped()) {
		pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(data[i], "x"); // 按照x字段进行渲染
		viewer->updatePointCloud(data[i], fildColor, "sample cloud");
		i++;
		if (i == sizeof(data) / sizeof(data[0])) i = 0;
		viewer->spinOnce(5000);
	}

}


//二.点云滤波

//1.直通滤波 可用于消除背景
void PCLfunction::PassThrough(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, float min, float max, int mode)
{
	//设置滤波器对象
	pcl::PassThrough<pcl::PointXYZ> pass;
	//设置输入点云
	pass.setInputCloud(incloud);
	//设置过滤是所需要的点云类型的y字段
	switch (mode)
	{
	case 1:
		pass.setFilterFieldName("x");
		break;
	case 2:
		pass.setFilterFieldName("y");
		break;
	case 3:
		pass.setFilterFieldName("z");
		break;
	}
	//设置在过滤字段上的范围 默认保留范围内的点云
	pass.setFilterLimits(min, max);
	//不设置默认为false即保留范围内点云,true则保留范围外的点云
	//pass.setFilterLimitsNegative (true); 
	//执行滤波,保存过滤结果
	pass.filter(*outcloud);
};
//2.体素滤波 下采样加速处理过程
void PCLfunction::VoxelGrid(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, float a)
{
	pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2);
	pcl::PCLPointCloud2::Ptr cloud_blob2(new pcl::PCLPointCloud2);
	//PointCloud< pcl::PointXYZ >—>PCLPointCloud2
	pcl::toPCLPointCloud2(*incloud, *cloud_blob);
	//创建滤波对象
	//pcl::VoxelGrid<pcl::PointXYZ> vox;
	pcl::VoxelGrid<pcl::PCLPointCloud2> vox;
	//设置需要过滤的点云给滤波对象
	vox.setInputCloud(cloud_blob);
	//设置滤波时创建的体素体积为am的立方体
	vox.setLeafSize(a, a, a);
	//执行滤波处理,存储输出
	vox.filter(*cloud_blob2);
	pcl::fromPCLPointCloud2(*cloud_blob2, *outcloud);
}
//3.均匀采样 不改变点位置准确度好于体素滤波
void PCLfunction::UniformSampling(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, double r)
{
	// Uniform sampling object.
	pcl::UniformSampling<pcl::PointXYZ> filter;
	filter.setInputCloud(incloud);
	filter.setRadiusSearch(r);
	//老版本存储索引再存处理后的点云
	// We need an additional object to store the indices of surviving points.
	//pcl::PointCloud<int> keypointIndices;
	//filter.compute(keypointIndices);
	//pcl::copyPointCloud(*incloud, keypointIndices.points, *outcloud);
	filter.filter(*outcloud); 
}
//4.statisticalOutlierRemoval统计滤波 去除离散点
void PCLfunction::StatisticalOutlierRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, int k, double sigma)
{
	//创建滤波器对象
	pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
	//设置待滤波的点云
	sor.setInputCloud(incloud);
	//设置用于平均距离估计的 KD-tree最近邻搜索点的个数
	sor.setMeanK(k);
	//设置判断是否为离群点的阀值;高斯分布标准差的倍数, 也就是 u+1*sigma,u+2*sigma,u+3*sigma 中的倍数1、2、3 
	sor.setStddevMulThresh(sigma);
	//存储滤波后的点云
	sor.filter(*outcloud);
	//下面这个参数不设置默认为false,true为取被过滤的点
	sor.setNegative(true);
}
//5.半径滤波 指定半径范围r内点数少于n的点滤除
void PCLfunction::RadiusOutlierRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, double r, int n)
{
	//创建滤波器
	pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
	//输入点云
	outrem.setInputCloud(incloud);
	//设置半径查找范围为2
	outrem.setRadiusSearch(r);
	//在半径范围内点数小于12的点滤除.
	outrem.setMinNeighborsInRadius(n);
	//保留存储半径范围内点数大于12的点
	outrem.filter(*outcloud);
}
//6.条件滤波 可以一次对多个轴的范围进行划定
void PCLfunction::ConditionalRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud,int mode, double a, double b)
{
	//创建条件定义对象
	pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());
	//为条件定义对象添加比较算子
	switch (mode)
	{
	case 1:
		//添加在X字段上大于a的比较算子
		range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::GT, a)));
		//添加在X字段上小于b的比较算子
		range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::LT, b)));
	case 2:
		//添加在Y字段上大于a的比较算子
		range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("y", pcl::ComparisonOps::GT, a)));
		//添加在Y字段上小于b的比较算子
		range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("y", pcl::ComparisonOps::LT, b)));
	case 3:
		//添加在Z字段上大于a的比较算子
		range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, a)));
		//添加在Z字段上小于b的比较算子
		range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, b)));
	}	
	//创建滤波器并用条件定义对象初始化
	pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
	condrem.setCondition(range_cond);
	condrem.setInputCloud(incloud);
	//设置保持点云的结构
	condrem.setKeepOrganized(true);
	// 执行滤波 大于a小于b这两个条件用于建立滤波器
	condrem.filter(*outcloud);
}
//7.投影滤波 将三维点投影至二维平面
void PCLfunction::ProjectInliers(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud)
{
	//填充ModelCoefficients的值,使用ax+by+cz+d=0平面模型,其中 a=b=d=0,c=1 也就是X0Y平面
    //定义模型系数对象,并填充对应的数据
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
	coefficients->values.resize(4);
	coefficients->values[0] = coefficients->values[1] = 0;
	coefficients->values[2] = 1.0;
	//创建ProjectInliers对象,使用ModelCoefficients作为投影对象的模型参数
	coefficients->values[3] = 0;
	//创建投影滤波对象
	pcl::ProjectInliers<pcl::PointXYZ> proj;
	//设置对象对应的投影模型
	proj.setModelType(pcl::SACMODEL_PLANE);
	proj.setInputCloud(incloud);
	//设置模型对应的系数
	proj.setModelCoefficients(coefficients);
	//保存投影结果 
	proj.filter(*outcloud);
}
//8.模型滤波 根据点到模型的距离滤除阈值外的点
void PCLfunction::ModelOutlierRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, float thresh)
{
	//x^2 + y^2 + z^2 = 1
    //position.x: 0, position.y: 0, position.z:0, radius: 1
	pcl::ModelCoefficients sphere_coeff;
	sphere_coeff.values.resize(4);
	sphere_coeff.values[0] = 0;
	sphere_coeff.values[1] = 0;
	sphere_coeff.values[2] = 0;
	sphere_coeff.values[3] = 1;
	pcl::ModelOutlierRemoval<pcl::PointXYZ> sphere_filter;
	sphere_filter.setModelCoefficients(sphere_coeff);
	sphere_filter.setThreshold(thresh);
	//设置滤波模型类型
	sphere_filter.setModelType(pcl::SACMODEL_SPHERE);
	sphere_filter.setInputCloud(incloud);
	sphere_filter.filter(*outcloud);
}
//9.高斯滤波 基于高斯核卷积 低通平滑滤波
void PCLfunction::Gaussian(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud)
{
	//创建高斯核
	pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ> kernel;
	//高斯函数的标准差,决定函数的宽度
	kernel.setSigma(5);
	//设置相对于Sigma参数的距离阈值
	kernel.setThresholdRelativeToSigma(5);
	//设置距离阈值,若点间距离大于阈值则不予考虑
	kernel.setThreshold(5);
	//创建搜索树
	//pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
	//创建3d卷积滤波器
	pcl::filters::Convolution3D<pcl::PointXYZ, pcl::PointXYZ, pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ> > convolution;
	//设置滤波器参数
	convolution.setKernel(kernel);
	convolution.setInputCloud(incloud);
	convolution.setNumberOfThreads(8);
	convolution.setSearchMethod(tree);
	convolution.setRadiusSearch(0.1);
	convolution.convolve(*outcloud);
}
//10.双边滤波 保持边缘,降噪平滑
void PCLfunction::BilateralFilter(pcl::PointCloud<pcl::PointXYZI>::Ptr incloud, pcl::PointCloud<pcl::PointXYZI>::Ptr outcloud, double sigma_s, double sigma_r)
{
	//设置搜索树KDTree
	//pcl::search::KdTree<pcl::PointXYZI>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZI>);
    //利用强度数据进行双边滤波算法的实现
	//通过取临近采样点和加权平均来修正当前采样点的位置,从而达到滤波效果,
	//同时也会有选择剔除与当前采样点“差异”太大的相邻采样点,从而保持原特征
	pcl::BilateralFilter<pcl::PointXYZI> nf;
	nf.setInputCloud(incloud);
	nf.setSearchMethod(tree1);
	//高斯滤波器的一半窗口值
	nf.setHalfSize(sigma_s);
	//标准差
	nf.setStdDev(sigma_r);
	nf.filter(*outcloud);
}
//11.索引提取
void PCLfunction::ExtractIndices(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud, std::vector<int> index)
{
	//提取1,3,4位置处点云
	//std::vector<int> index = { 1,3,4 };
	boost::shared_ptr<std::vector<int>> index_ptr = boost::make_shared<std::vector<int>>(index);
	//Create the filtering object
	pcl::ExtractIndices<pcl::PointXYZ> extract;
	//Extract the inliers
	extract.setInputCloud(incloud);
	extract.setIndices(index_ptr);
	extract.setNegative(false);//如果设为true,可以提取指定index之外的点云
	extract.filter(*outcloud);

	//提取子集构成一个新的点云
	//std::vector<int> indexs = { 1, 2, 5 };//声明索引值
	//pcl::copyPointCloud(*incloud, indexs, *outcloud);//将对应索引的点存储
}
//12.CropHull滤波
void PCLfunction::CropHull(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud)
{
	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); 
	//polygons保存的是所有凸包多边形的顶点在surface_hull中的下标,用于保存凸包顶点
	std::vector<pcl::Vertices> polygons; 
	pcl::PointCloud<pcl::PointXYZ>::Ptr
	surface_hull(new pcl::PointCloud<pcl::PointXYZ>); 
	//凸包点云存放在surface_hull中,polygons中的Vertices存放一组点的索引,索引是surface_hull中的点对应的索引
	hull.reconstruct(*surface_hull, polygons);

	pcl::PointCloud<pcl::PointXYZ>::Ptr objects(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::CropHull<pcl::PointXYZ> bb_filter;
	bb_filter.setDim(2); 
	bb_filter.setInputCloud(incloud);
	bb_filter.setHullIndices(polygons); 
	bb_filter.setHullCloud(surface_hull);
	bb_filter.filter(*outcloud); 
	//std::cout << objects->size() << std::endl;
}

//三.点云分割

//1.随机采样一致(RANSAC)取在RANSAC模型阈值范围内的点
void PCLfunction::RANSAC(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud)
{
	//创建一个模型参数对象,用于记录结果
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
	//inliers表示误差能容忍的点 记录的是点云的序号
	pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
	// 创建一个分割器
	pcl::SACSegmentation<pcl::PointXYZ> seg;
	// Optional设置对估计的模型做优化处理
	seg.setOptimizeCoefficients(true);
	// Mandatory-设置目标几何形状
	seg.setModelType(pcl::SACMODEL_PLANE);
	//分割方法:随机采样法
	seg.setMethodType(pcl::SAC_RANSAC);
	//设置误差容忍范围
	seg.setDistanceThreshold(0.01);
	//输入点云
	seg.setInputCloud(incloud);
	//分割点云,得到参数
	seg.segment(*inliers, *coefficients);
	pcl::copyPointCloud<pcl::PointXYZ>(*incloud, *inliers, *outcloud);
}
//2.欧式聚类分割
void PCLfunction::EuclideanClusterExtraction(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud)
{
	pcl::PCDWriter writer;
	//Creating the KdTree object for the search method of the extraction
	//pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
	//tree->setInputCloud(incloud);//将无法提取平面的点云作为cloud_filtered
	std::vector<pcl::PointIndices> cluster_indices;//保存每一种聚类,每一种聚类下还有具体的聚类的点
	pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;//实例化一个欧式聚类提取对象
	ec.setClusterTolerance(0.5); // 近邻搜索的搜索半径为2cm,重要参数
	ec.setMinClusterSize(999);//设置一个聚类需要的最少点数目为100
	ec.setMaxClusterSize(999999);//一个聚类最大点数目为25000
	ec.setSearchMethod(tree);//设置点云的搜索机制
	ec.setInputCloud(incloud);//设置输入点云
	ec.extract(cluster_indices);//将聚类结果保存至cluster_indices中
	
	//可视化写在这里是为了给每个聚类设置不同的颜色
	pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D viewer"));
	int v1(0);
	viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
	viewer->setBackgroundColor(0.1, 0.1, 0.1, v1);
	viewer->addText("before", 10, 10, "v1 text", v1);
	viewer->addPointCloud<pcl::PointXYZ>(incloud, "cloud_in", v1);
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud_in", v1);
	int v2(0);
	viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2);
	viewer->setBackgroundColor(0.3, 0.3, 0.3, v2);
	viewer->addText("after", 10, 10, "v2 text", v2);

	//迭代访问点云索引cluster_indices,直到分割出所有聚类,一个循环提取出一类点云
	int j = 0;
	for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it)
	{
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>);
		//创建新的点云数据集cloud_cluster,直到分割出所有聚类
		for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); pit++)
		{
			cloud_cluster->points.push_back(incloud->points[*pit]); 
		}
		cloud_cluster->width = cloud_cluster->points.size();
		cloud_cluster->height = 1;
		cloud_cluster->is_dense = true;
		std::stringstream ss;
		ss << "cloud_cluster_" << j << ".pcd";	
		writer.write<pcl::PointXYZ>(ss.str(), *cloud_cluster, false);
		cout << "-----" << ss.str() << "详情-----" << endl;
		cout << *cloud_cluster << endl;

		viewer->addPointCloud<pcl::PointXYZ>(cloud_cluster, ss.str(), v2);
		//设置点云大小
		viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, ss.str(), v2);
		//pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud_cluster, j*50, j*30, j);//这种不行都是同一个颜色
		//设置点云颜色 其中colors取值范围为0-1
		viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, colors[j * 3]/255 , colors[j * 3 + 1]/255, colors[j * 3 + 2]/255 , ss.str(), v2);
		j++;
	}
	viewer->resetCamera();
	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}
}
#if 0
//3.条件欧式聚类分割
void PCLfunction::ConditionalEuclideanClustering(pcl::PointCloud<pcl::PointXYZI>::Ptr incloud, pcl::PointCloud<pcl::PointXYZI>::Ptr outcloud,int Method)
{	
	pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZI>);
	pcl::PointCloud<pcl::PointXYZINormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointXYZINormal>);
	pcl::IndicesClustersPtr clusters(new pcl::IndicesClusters), small_clusters(new pcl::IndicesClusters), large_clusters(new pcl::IndicesClusters);
	pcl::console::TicToc tt;
	float Leaf = 80.0;
	double Radius = 300.0;

	std::cerr << "Downsampling...\n", tt.tic();
	pcl::VoxelGrid<pcl::PointXYZI> vg;//设置滤波对象
	vg.setInputCloud(incloud);//设置需要过滤的点云给滤波对象
	vg.setLeafSize(Leaf, Leaf, Leaf);//设置滤波时创建的栅格边长
	vg.setDownsampleAllData(true);//设置所有的数值域需要被下采样
	vg.filter(*cloud_out);//执行滤波处理,存储输出cloud_out
	std::cerr << ">> Done: " << tt.toc() << " ms, " << cloud_out->points.size() << " points\n";

	// Set up a Normal Estimation class and merge data in cloud_with_normals
	std::cerr << "Computing normals...\n", tt.tic();
	pcl::copyPointCloud(*cloud_out, *cloud_with_normals);//复制点云
	pcl::NormalEstimation<pcl::PointXYZI, pcl::PointXYZINormal> ne;//创建法线估计对象
	ne.setInputCloud(cloud_out);//设置法线估计对象输入点集
	ne.setSearchMethod(tree1);//设置搜索方法
	ne.setRadiusSearch(Radius);// 设置搜索半径
	ne.compute(*cloud_with_normals);//计算并输出法向量
	std::cerr << ">> Done: " << tt.toc() << " ms\n";

	std::cerr << "Segmenting to clusters...\n", tt.tic();
	pcl::ConditionalEuclideanClustering<pcl::PointXYZINormal> cec(true);//创建条件聚类分割对象,并进行初始化。
	cec.setInputCloud(cloud_with_normals);
		//用于选择不同条件函数
	switch (Method)
	{
	case 1:
		cec.setConditionFunction(&enforceIntensitySimilarity);
		break;
	case 2:
		cec.setConditionFunction(&enforceCurvatureOrIntensitySimilarity);
		break;
	case 3:
		cec.setConditionFunction(&customRegionGrowing);
		break;
	default:
		cec.setConditionFunction(&customRegionGrowing);
		break;
	}
	//设置聚类参考点的搜索距离
	cec.setClusterTolerance(500.0);
	//设置过小聚类的标准
	cec.setMinClusterSize(cloud_with_normals->points.size() / 1000);
	//设置过大聚类的标准
	cec.setMaxClusterSize(cloud_with_normals->points.size() / 5);
	//获取聚类的结果,分割结果保存在点云索引的向量中
	cec.segment(*clusters);
	//获取无效尺寸的聚类
	cec.getRemovedClusters(small_clusters, large_clusters);
	//pcl::copyPointCloud<pcl::PointXYZ>(*incloud, *inliers, *outcloud);

	//bool customCondition(const pcl::PointXYZ& seedPoint, const pcl::PointXYZ& candidatePoint, float squaredDistance)
	//{
	//	//自定义条件
	//	return false;
	//	return true;
	//}
	  // Using the intensity channel for lazy visualization of the output
	for (const auto& small_cluster : (*small_clusters))
		for (const auto& j : small_cluster.indices)
			(*cloud_out)[j].intensity = -2.0;
	for (const auto& large_cluster : (*large_clusters))
		for (const auto& j : large_cluster.indices)
			(*cloud_out)[j].intensity = +10.0;
	for (const auto& cluster : (*clusters))
	{
		int label = rand() % 8;
		for (const auto& j : cluster.indices)
			(*cloud_out)[j].intensity = label;
	}

	// Save the output point cloud
	std::cerr << "Saving...\n", tt.tic();
	pcl::io::savePCDFile("output.pcd", *cloud_out);
	std::cerr << ">> Done: " << tt.toc() << " ms\n";
	outcloud = cloud_out;
}
#endif 
//4.基于区域生长分割
void PCLfunction::RegionGrowing(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::Normal>::Ptr cloud_normals, pcl::PointCloud<pcl::PointXYZRGB>::Ptr outcloud)
{
	//区域增长聚类分割对象 <点,法线>
	pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
	//最小的聚类的点数
	reg.setMinClusterSize(50);
	//最大的聚类的点数
	reg.setMaxClusterSize(100000);
	reg.setSearchMethod(tree);
	//设置搜索的邻域点的个数
	reg.setNumberOfNeighbours(500);
	reg.setInputCloud(incloud);
	//reg.setIndices (indices);
	//输入的法线
	reg.setInputNormals(cloud_normals);
	//设置平滑度 法线差值阈值
	//reg.setSmoothnessThreshold(3.0 / 180.0 * M_PI);
	reg.setSmoothnessThreshold(30);
	//设置曲率的阀值
	reg.setCurvatureThreshold(0.05);
	std::vector <pcl::PointIndices> clusters;
	reg.extract(clusters);//获取聚类的结果,分割结果保存在点云索引的向量中
	outcloud = reg.getColoredCloud();
	pcl::PCDWriter writer;//将点云写入磁盘
	writer.write("resultFloor.pcd", *outcloud, false);//改成想要输出的点云名称
}
//5.基于颜色的区域生长分割
void PCLfunction::RegionGrowingRGB(pcl::PointCloud<pcl::PointXYZRGB>::Ptr incloud, pcl::PointCloud<pcl::PointXYZRGB>::Ptr outcloud)
{
	//基于颜色的区域生成的对象
	pcl::RegionGrowingRGB<pcl::PointXYZRGB> reg;
	reg.setInputCloud(incloud);
	//点云的索引,可处理存储直通滤波后的点云
	//reg.setIndices(indices);
	reg.setSearchMethod(tree2);
	//距离的阀值
	reg.setDistanceThreshold(10);
	//点与点之间颜色容差
	reg.setPointColorThreshold(6);
	//区域之间容差
	reg.setRegionColorThreshold(5);
	//设置聚类的大小
	reg.setMinClusterSize(600);
	std::vector <pcl::PointIndices> clusters;
	reg.extract(clusters);
	outcloud = reg.getColoredCloud();
	pcl::PCDWriter writer;//将点云写入磁盘
	writer.write("1.pcd", *outcloud, false);//改成想要输出的点云名称
}
//6.最小图割
void PCLfunction::MinCutSegmentation(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZRGB>::Ptr outcloud)
{
	// 申明一个Min-cut的聚类对象
	pcl::MinCutSegmentation<pcl::PointXYZ> clustering;
	clustering.setInputCloud(incloud); //设置输入
	clustering.setSearchMethod(tree);
	//创建一个点云,列出所知道的所有属于对象的点
	//(前景点)在这里设置聚类对象的中心点
	pcl::PointCloud<pcl::PointXYZ>::Ptr foregroundPoints(new pcl::PointCloud<pcl::PointXYZ>());
	pcl::PointXYZ point;
	point.x = 0.5;
	point.y = 0.5;
	point.z = 0.5;
	foregroundPoints->points.push_back(point);
	clustering.setForegroundPoints(foregroundPoints);//设置聚类对象的前景点
	//设置sigma,它影响计算平滑度的成本。它的设置取决于点云之间的间隔(分辨率)
	clustering.setSigma(0.5);// cet cost = exp(-(dist/cet)^2)
	// 设置聚类对象的半径.
	clustering.setRadius(0.5);// dist2Center / radius
	//设置需要搜索的临近点的个数,增加这个也就是要增加边界处图的个数
	clustering.setNumberOfNeighbours(200);
	//设置前景点的权重(也就是排除在聚类对象中的点,它是点云之间线的权重,)
	clustering.setSourceWeight(0.6);
	std::vector <pcl::PointIndices> clusters;
	clustering.extract(clusters);
	outcloud = clustering.getColoredCloud();
	pcl::PCDWriter writer;//将点云写入磁盘
	writer.write("2.pcd", *outcloud, false);//改成想要输出的点云名称
}
//7.基于法线微分分割
void PCLfunction::DifferenceOfNormalsEstimation(pcl::PointCloud<pcl::PointXYZRGB>::Ptr incloud)
{
	//Create output cloud for DoN results
    pcl::PointCloud<pcl::PointNormal>::Ptr doncloud(new pcl::PointCloud<pcl::PointNormal>);
	pcl::PointCloud<pcl::PointNormal>::Ptr normals_small_scale(new pcl::PointCloud<pcl::PointNormal>);
	pcl::PointCloud<pcl::PointNormal>::Ptr normals_large_scale(new pcl::PointCloud<pcl::PointNormal>);
	pcl::copyPointCloud<pcl::PointXYZRGB, pcl::PointNormal>(*incloud, *doncloud);
	pcl::DifferenceOfNormalsEstimation<pcl::PointXYZRGB, pcl::PointNormal, pcl::PointNormal> don;
	don.setInputCloud(incloud);
	don.setNormalScaleLarge(normals_large_scale);
	don.setNormalScaleSmall(normals_small_scale);
	don.initCompute();
	//Compute DoN
	don.computeFeature(*doncloud);
}
//8.基于超体素分割
void PCLfunction::SupervoxelClustering(pcl::PointCloud<pcl::PointXYZRGBA>::Ptr incloud)
{
	bool disable_transform = true;
	//体素大小,空间八叉树的分辨率,类kinect或xtion获取的数据0.008左右合适
	float voxel_resolution = 0.008f;
	//种子的分辨率,一般可设置为体素分辨率的50倍以上
	float seed_resolution = 0.1f;
	//针对分割场景,如果分割场景中各个物体之间的颜色特征差异明显,可以设置较大
	float color_importance = 0.2f;
	//设置较大且其他影响较小时,基本按照空间分辨率来决定体素分割
	float spatial_importance = 0.4f;
	//针对分割场景,如果分割场景中各个物体连通处的法线特征差异明显,可以设置较大,但在实际使用中,需要针对数据的结构适当考虑,发现估计的准确性等因素
	float normal_importance = 1.0f;
	pcl::SupervoxelClustering<pcl::PointXYZRGBA> super(voxel_resolution, seed_resolution);
	if (disable_transform)
		super.setUseSingleCameraTransform(false);
	super.setInputCloud(incloud);
	super.setColorImportance(color_importance);
	super.setSpatialImportance(spatial_importance);
	super.setNormalImportance(normal_importance);
	//输出结晶分割结果:结果是一个映射表
	std::map <uint32_t, pcl::Supervoxel<pcl::PointXYZRGBA>::Ptr> supervoxel_clusters;
	//获得晶体中心
	super.extract(supervoxel_clusters);
	//获得晶体
	pcl::PointCloud<pcl::PointXYZRGBA>::Ptr voxel_centroid_cloud = super.getVoxelCentroidCloud();
	pcl::PointCloud<pcl::PointXYZL>::Ptr labeled_voxel_cloud = super.getLabeledVoxelCloud();
	pcl::PCDWriter writer;//将点云写入磁盘
	writer.write("3.pcd", *voxel_centroid_cloud, false);
	writer.write("4.pcd", *labeled_voxel_cloud, false);
}


//其他

//1.计算点云法线
void PCLfunction::NormalEstimation(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::Normal>::Ptr cloud_normals)
{
	// 把点云数据传递给法线估计对象
	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
	ne.setInputCloud(incloud);
	// 把空的kd-tree传给法线估计对象
	ne.setSearchMethod(tree);
	// 新建Normal型点云,储存估计法线的输出结果
	//pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);
	// 使用半径在查询点周围3厘米范围内的所有邻元素
	//ne.setRadiusSearch(0.03);
	ne.setKSearch(50);
	// 计算法线值,放到Normal型点云中
	ne.compute(*cloud_normals);
}
//2.边缘提取
void PCLfunction::EstimateBoundary(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::Boundary>& boundaries)
{
	pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundary_est;
	boundary_est.setInputCloud(cloud);
	boundary_est.setInputNormals(normals); // 边界估计依赖于法线
	boundary_est.setKSearch(10); // 一般这里的数值越高,最终边界识别的精度越好
	// boundary_est.setRadiusSearch(0.1); // 设置为分辨率的10倍时效果较好,太小则内部的很多点就都当成边界点了
	boundary_est.setAngleThreshold(M_PI / 2); // 边界估计时的角度阈值,默认值为PI/2,可根据需要进行更改。
	pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>);
	boundary_est.setSearchMethod(kdtree);
	boundary_est.compute(boundaries);
}
//3.txt->point xyz
void PCLfunction::CreateCloudFromTxt(const std::string& file_path, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
	std::ifstream fin(file_path.c_str());
	std::string line;
	pcl::PointXYZ point;
	while (getline(fin, line))
	{
		std::stringstream ss(line);
		ss >> point.x;
		ss >> point.y;
		ss >> point.z;
		cloud->push_back(point);
	}
	fin.close();
}
//4.圆柱拟合 提取出点云中的圆柱体
void PCLfunction::CircularColumn(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals, pcl::PointCloud<pcl::PointXYZ > ::Ptr outcloud)
{
	pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> seg;// 创建圆柱体分割对象
	seg.setInputCloud(cloud);										// 设置输入点云:待分割点云
	seg.setOptimizeCoefficients(true);								// 设置对估计的模型系数需要进行优化
	seg.setModelType(pcl::SACMODEL_CYLINDER);						// 设置分割模型为圆柱体模型
	seg.setMethodType(pcl::SAC_RANSAC);								// 设置采用RANSAC算法进行参数估计
	seg.setNormalDistanceWeight(0.1);								// 设置表面法线权重系数
	seg.setMaxIterations(1000);									    // 设置迭代的最大次数
	seg.setDistanceThreshold(0.05);									// 设置内点到模型距离的最大值
	seg.setRadiusLimits(3.0, 4.0);									// 设置圆柱模型半径的范围
	seg.setInputNormals(normals);								// 设置输入法向量
	pcl::PointIndices::Ptr inliers_cylinder(new pcl::PointIndices);	// 保存分割结果
	pcl::ModelCoefficients::Ptr coefficients_cylinder(new pcl::ModelCoefficients);	// 保存圆柱体模型系数
	seg.segment(*inliers_cylinder, *coefficients_cylinder);			// 执行分割,将分割结果的索引保存到inliers_cylinder中,同时存储模型系数coefficients_cylinder

	pcl::ExtractIndices<pcl::PointXYZ> extract;	// 创建索引提取点对象
	extract.setInputCloud(cloud);			// 设置输入点云:待分割点云
	extract.setIndices(inliers_cylinder);	// 设置内点索引
	extract.setNegative(false);				// 默认false,提取圆柱体内点;true,提取圆柱体外点
	//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cylinder(new pcl::PointCloud<pcl::PointXYZ>());
	extract.filter(*outcloud);		        // 执行滤波,并将结果点云保存到cloud_cylinder中

}
//5.圆形2D拟合
void PCLfunction::Circle2D(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud)
{
	/*pcl::PointCloud<pcl::PointXYZ>::Ptr incloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::io::loadPCDFile<pcl::PointXYZ>("circle2D.pcd", *incloud);*/
	pcl::SampleConsensusModelCircle2D<pcl::PointXYZ>::Ptr model_circle2D(new pcl::SampleConsensusModelCircle2D<pcl::PointXYZ>(cloud));	//选择拟合点云与几何模型
	pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_circle2D);	//创建随机采样一致性对象
	ransac.setDistanceThreshold(0.01);	//设置距离阈值,与模型距离小于0.01的点作为内点
	ransac.setMaxIterations(10000);		//设置最大迭代次数
	ransac.computeModel();				//执行模型估计
	vector<int> inliers;				//存储内点索引的向量
	ransac.getInliers(inliers);			//提取内点对应的索引
	// 根据索引提取内点
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_circle(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::copyPointCloud<pcl::PointXYZ>(*cloud, inliers, *outcloud);
	//输出模型参数
	Eigen::VectorXf coefficient;
	ransac.getModelCoefficients(coefficient);

}
//6.去除NAN点
void PCLfunction::removeNan(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud)
{
	std::vector<int> indices;
	pcl::removeNaNFromPointCloud(*incloud, *outcloud, indices);
}
/*//7.拟合球
void ball()
{

	pcl::SampleConsensusModelSphere<pcl::PointXYZ>::Ptr model_sphere(new pcl::SampleConsensusModelSphere<pcl::PointXYZ>(cloud));	//选择拟合点云与几何模型
	pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_sphere);	//创建随机采样一致性对象
	ransac.setDistanceThreshold(0.01);	//设置距离阈值,与球面距离小于0.01的点作为内点
	ransac.computeModel();				//执行模型估计

	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_sphere(new pcl::PointCloud<pcl::PointXYZ>);

	//---------- 根据索引提取内点 ----------
	//方法1
	vector<int> inliers;				//存储内点索引的向量
	ransac.getInliers(inliers);			//提取内点对应的索引
	pcl::copyPointCloud<pcl::PointXYZ>(*cloud, inliers, *cloud_sphere);

}*/

//8.点云拼接
//同一类型点云直接相加形成一个新的点云,不同类型点云如拼接点和法向量可用pcl::concatenateFields(clouda, n_cloudb, p_n_cloudc)

//9.计算点云平均密度
float PCLfunction::kdTreeSearch(pcl::PointCloud<pcl::PointXYZ>::Ptr incloud, int k)
{
	pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;  //创建一个快速k近邻查询,查询的时候若该点在点云中,则第一个近邻点是其本身
	kdtree.setInputCloud(incloud);
	//int k = 100;
	float everagedistance = 0;
	for (int i = 0; i < incloud->size() / 2; i++)
	{
		vector<int> nnh;
		vector<float> squaredistance;
		//  pcl::PointXYZ p;
		//   p = cloud->points[i];
		kdtree.nearestKSearch(incloud->points[i], k, nnh, squaredistance);
		everagedistance += sqrt(squaredistance[1]);
		//   cout<<everagedistance<<endl;
	}
	everagedistance = everagedistance / (incloud->size() / 2);
	//cout << "everage distance is : " << everagedistance << endl;
	return everagedistance;
}


//主函数
int main(int argc, char** argv)
{
	//定义不同点类型点云

	PCLfunction* my;
	pcl::PointCloud<pcl::Boundary> boundaries;
	pcl::PointCloud<pcl::PointXYZ>::Ptr incloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZI>::Ptr incloud1(new pcl::PointCloud<pcl::PointXYZI>);
	pcl::PointCloud<pcl::PointXYZI>::Ptr outcloud1(new pcl::PointCloud<pcl::PointXYZI>);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr incloud2(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr outcloud2(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointCloud<pcl::PointXYZRGBA>::Ptr incloud3(new pcl::PointCloud<pcl::PointXYZRGBA>);
	pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);

	//导入点云文件
	int x = 0;
	float w = 0;
	std::cout << "选择点云" << endl;
	cin >> x;
	switch (x)
	{
	case 1:
		pcl::io::loadPCDFile<pcl::PointXYZ>("table_scene_lms400.pcd", *incloud);
		break;
	case 2:
		pcl::io::loadPCDFile<pcl::PointXYZRGB>("2.pcd", *incloud2);
		break;
	case 3:
		pcl::io::loadPCDFile<pcl::PointXYZRGBA>("pig.pcd", *incloud3);
		break;
	case 4:
		pcl::io::loadPCDFile<pcl::PointXYZI>("Statues_4.pcd", *incloud1);
		break;
	case 5:
		pcl::io::loadPCDFile<pcl::PointXYZ>("test.pcd", *incloud);
		break;
	case 6:
		pcl::io::loadPCDFile<pcl::PointXYZ>("circle2D.pcd", *incloud);
		break;
	case 7:
		pcl::io::loadPCDFile<pcl::PointXYZ>("E:\\DataSet\\PointCloud\\boundary.pcd", *incloud);
		break;
	default:
		pcl::io::loadPCDFile<pcl::PointXYZ>("rabbit.pcd", *incloud);
	}
	pcl::getMinMax3D(*incloud, p_min, p_max);
	w = my->kdTreeSearch(incloud, 50);
	std::cout <<"点云点数"<< incloud->size() << endl;
	std::cout << "最小点" << p_min.x <<"," << p_min.y<<","<< p_min.z<<endl;
	std::cout << "最大点" << p_max.x << "," << p_max.y << "," << p_max.z << endl;
	std::cout << "点云密度" << w << endl;
	cout << endl;

	//进行点云处理操作
	int y = 0;
	std::cout << "选择点云处理方式" << endl;
	cin >> y;
	switch (y)
	{
	case 1:
		my->NormalEstimation(incloud, cloud_normals);
		break;
	case 2:
		my->NormalEstimation(incloud, cloud_normals);
		my->RegionGrowing(incloud, cloud_normals, outcloud2);
		pcl::io::loadPCDFile<pcl::PointXYZRGB>("resultFloor.pcd", *outcloud2);
		break;
	case 3:
		my->RegionGrowingRGB(incloud2, outcloud2);
		break;
	case 4:
		my->MinCutSegmentation(incloud, outcloud2);
		break;
	case 5:
		//边缘提取
		my->NormalEstimation(incloud, cloud_normals);
		my->EstimateBoundary(incloud, cloud_normals, boundaries);
		for (size_t i = 0; i < incloud->points.size(); ++i) {
			if (boundaries[i].boundary_point > 0) {
				outcloud->push_back(incloud->points[i]);
			}
		}
		break;
	case 6:
		my->ModelOutlierRemoval(incloud, outcloud, 2.0);
		break;
	case 7:
		my->PassThrough(incloud, outcloud, 0.05, 3, 1);
		break;
	case 8:
		my->VoxelGrid(incloud, outcloud, 0.01);
		break;
	case 9:
		my->UniformSampling(incloud, outcloud, 0.01);
		break;
	case 10:
		my->StatisticalOutlierRemoval(incloud, outcloud, 50, 1.0);
		break;
	case 11:
		my->RANSAC(incloud, outcloud);
		break;
	case 12:
		my->EuclideanClusterExtraction(incloud);
		break;
	case 13:
		my->SupervoxelClustering(incloud3);
		break;
	case 14:
		my->CropHull(incloud,outcloud);
		break;
	case 15:
		my->NormalEstimation(incloud, cloud_normals);
		my->CircularColumn(incloud, cloud_normals, outcloud);
		break;
	case 16:
		//my->Circle2D(incloud, outcloud);
		break;
	default:
		my->PassThrough(incloud, outcloud, 0.05, 3, 1);
	}


	//点云可视化
	int z = 0;
	std::cout << "选择可视化方式" << endl;
	cin >> z;
	switch (z)
	{
	case 1:
		my->visualization2wd1(incloud1, outcloud1);
		break;
	case 2:
		my->visualization1(outcloud2);
		break;
	case 3:
		my->visualization2wd(incloud, outcloud);
		break;
	case 4:
		my->visualization2wd2(incloud, outcloud2);
		break;
	case 5:
		my->visualization2wd3(incloud2, outcloud2);
	default:
		my->visualization2wd2(incloud, outcloud2);
	}
	
}

3. 一个示例

  • 例如选择7,11,3可以得到对XYZ类型的点云进行RANSAC平面拟合的处理效果,并且以双窗口的形式对处理结果进行展示。
  • 并且可以显示点云点数,最大最小点以及点云密度等信息
    在这里插入图片描述
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值