《PCL点云库学习&VS2010(X64)》Part 14 PCL1.72(VTK6.2.0)点云分割(Point Cloud Segmentation)

Part 14 PCL1.72(VTK6.2.0)点云分割(Point Cloud Segmentation)


1、Plane Model Segmentation

cpp:

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/search/kdtree.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/extract_indices.h>

int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_source (new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_target (new pcl::PointCloud<pcl::PointXYZ>);

	// check arguments
	if(argc != 2) {
		std::cout << "ERROR: the number of arguments is illegal!" << std::endl;
		return -1;
	}

	// load pcd file
	if(pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *cloud_source)==-1) {
		std::cout << "load source failed!" << std::endl;
		return -1;
	}

	std::cout << "source loaded!" << std::endl;


	// pass through filter to get the certain field
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_source_filtered(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PassThrough<pcl::PointXYZ> pt;
	pt.setInputCloud(cloud_source);
	pt.setFilterFieldName("y");
	pt.setFilterLimits(-0.1, 0.6);
	pt.filter(*cloud_source_filtered);
	
	// segmentation
	pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
	pcl::PointIndices::Ptr inliers (new pcl::PointIndices);

	pcl::SACSegmentation<pcl::PointXYZ> sac;
	sac.setInputCloud(cloud_source_filtered);    // cloud_source_filtered 为提取桌子表面 cloud_source 为提取地面
	sac.setMethodType(pcl::SAC_RANSAC);//set sample method SAC_RANSAC
	sac.setModelType(pcl::SACMODEL_PLANE);
	sac.setDistanceThreshold(0.01);
	sac.setMaxIterations(100);
	sac.setProbability(0.95);

	sac.segment(*inliers, *coefficients);
	
	// extract the certain field
	pcl::ExtractIndices<pcl::PointXYZ> ei;
	ei.setIndices(inliers);
	ei.setInputCloud(cloud_source_filtered);    // cloud_source_filtered 为提取桌子表面 cloud_source 为提取地面
	ei.filter(*cloud_target);

	std::cout << *coefficients << std::endl;

	// display
	pcl::visualization::PCLVisualizer p;
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> tgt_h (cloud_target, 255, 0, 0);
	p.setWindowName("cloud_target-目标数据-桌面");
	p.addPointCloud(cloud_target, tgt_h, "target");
	p.spinOnce();
	
	pcl::visualization::PCLVisualizer p2;
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_h (cloud_source, 0, 255, 0);
	p2.setWindowName("cloud_source-原始数据");
	p2.addPointCloud(cloud_source, src_h, "source");
	p2.spinOnce();//no spin()

	pcl::visualization::PCLVisualizer p3;
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_f(cloud_source_filtered, 0, 0, 255);
	p3.setWindowName("cloud_source_filtered-桌子表面");
	p3.addPointCloud(cloud_source_filtered, src_f, "cloud_source_filtered");
	p3.spin();

	return 0;
}

运行

注意点:

  1. inline void setModelType (int model) 所提取目标模型的属性(平面、球、圆柱等等),这个示例中主要是提取平面。
  2. inline voidsetMethodType (int method)采样方法(RANSAC、LMedS)等,具体的方式可以参考教程,此处选随机一致性采样。
  3. SACMODEL_PLANE - 用于确定平面模型。平面的四个系数是Hessian的正常形态:[normal_x normal_y normal_z D]
    * SACMODEL_LINE - 用于确定线模型。该行的6个系数是由一个点上线,并线的方向:[point_on_line.x point_on_line.y point_on_line.z line_direction.x line_direction.y line_direction.z]
    * SACMODEL_CIRCLE2D - 用于确定一个2d圆。其圆心和半径的圆的三个系数:[center.x center.y半径]
    * SACMODEL_CIRCLE3D - 尚未实现
    * SACMODEL_SPHERE - 用于确定球体。球体的四个系数由3D的圆心和半径为:[center.x center.y center.z半径]
    * SACMODEL_CYLINDER - 用于确定圆柱。圆柱模型的七个系数由点上的轴,轴的方向,半径,因为:[point_on_axis.x point_on_axis.y point_on_axis.z axis_direction.x axis_direction.y axis_direction.z半径]
    * SACMODEL_CONE - 尚未实现
    * SACMODEL_TORUS - 尚未实现
    * SACMODEL_PARALLEL_LINE - 确定一个给定轴的平行线的模型,在一个指定的最大角偏差。该生产线的系数类似SACMODEL_LINE。
    * SACMODEL_PERPENDICULAR_PLANE - 为确定用户指定的轴垂直的平面内一个指定的最大角偏差,的模式。平面系数类似SACMODEL_PLANE。
    * SACMODEL_PARALLEL_LINES - 尚未实现
    * SACMODEL_NORMAL_PLANE - 一个使用一个额外的约束来确定平面:在每个内点的表面法线在指定的最大角偏差,表面正常的输出平面平行。平面系数类似SACMODEL_PLANE。
    * SACMODEL_PARALLEL_PLANE - 一个maximim指定的角偏差,到用户指定的轴范围内确定一个平面平行的典范。 SACMODEL_PLANE。
    * SACMODEL_NORMAL_PARALLEL_PLANE 使用额外的一般平面约束来分割3D平面。平面必须平行与用户指定的轴。SACMODEL_NORMAL_PARALLEL_PLANE因此是equivallent SACMODEL_NORMAL_PLANE + SACMODEL_PARALLEL_PLANE。平面系数类似SACMODEL_PLANE。



2、柱体分割Cylinder Segmentation

cpp:
#include <vtkAutoInit.h>         
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);

#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/passthrough.h>
#include <pcl/features/normal_3d.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/search/kdtree.h>  
#include <pcl/visualization/pcl_visualizer.h> 

typedef pcl::PointXYZ PointT;

int
main (int argc, char** argv)
{
  // All the objects needed
  pcl::PCDReader reader;
  pcl::PassThrough<PointT> pass;
  pcl::NormalEstimation<PointT, pcl::Normal> ne;
  pcl::SACSegmentationFromNormals<PointT, pcl::Normal> seg; 
  pcl::PCDWriter writer;
  pcl::ExtractIndices<PointT> extract;
  pcl::ExtractIndices<pcl::Normal> extract_normals;
  pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT> ());

  // Datasets
  pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
  pcl::PointCloud<PointT>::Ptr cloud_filtered (new pcl::PointCloud<PointT>);
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
  pcl::PointCloud<PointT>::Ptr cloud_filtered2 (new pcl::PointCloud<PointT>);
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals2 (new pcl::PointCloud<pcl::Normal>);
  pcl::ModelCoefficients::Ptr coefficients_plane (new pcl::ModelCoefficients), coefficients_cylinder (new pcl::ModelCoefficients);
  pcl::PointIndices::Ptr inliers_plane (new pcl::PointIndices), inliers_cylinder (new pcl::PointIndices);
 
  // Read in the cloud data
  reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);
  std::cerr << "PointCloud has: " << cloud->points.size () << " data points." << std::endl;

  // Build a passthrough filter to remove spurious NaNs
  pass.setInputCloud (cloud);
  pass.setFilterFieldName ("z");
  pass.setFilterLimits (0, 1.5);
  pass.filter (*cloud_filtered);
  std::cerr << "PointCloud after filtering has: " << cloud_filtered->points.size () << " data points." << std::endl;

  // Estimate point normals
  ne.setSearchMethod (tree);
  ne.setInputCloud (cloud_filtered);
  ne.setKSearch (50);
  ne.compute (*cloud_normals);

  // Create the segmentation object for the planar model and set all the parameters
  seg.setOptimizeCoefficients (true);
  seg.setModelType (pcl::SACMODEL_NORMAL_PLANE);
  seg.setNormalDistanceWeight (0.1);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setMaxIterations (100);
  seg.setDistanceThreshold (0.03);
  seg.setInputCloud (cloud_filtered);
  seg.setInputNormals (cloud_normals);
  // Obtain the plane inliers and coefficients
  seg.segment (*inliers_plane, *coefficients_plane);
  std::cerr << "Plane coefficients: " << *coefficients_plane << std::endl;

  // Extract the planar inliers from the input cloud
  extract.setInputCloud (cloud_filtered);
  extract.setIndices (inliers_plane);
  extract.setNegative (false);

  // Write the planar inliers to disk
  pcl::PointCloud<PointT>::Ptr cloud_plane (new pcl::PointCloud<PointT> ());
  extract.filter (*cloud_plane);
  std::cerr << "PointCloud representing the planar component: " << cloud_plane->points.size () << " data points." << std::endl;
  writer.write ("table_scene_mug_stereo_textured_plane.pcd", *cloud_plane, false);

  // Remove the planar inliers, extract the rest
  extract.setNegative (true);
  extract.filter (*cloud_filtered2);
  extract_normals.setNegative (true);
  extract_normals.setInputCloud (cloud_normals);
  extract_normals.setIndices (inliers_plane);
  extract_normals.filter (*cloud_normals2);

  // Create the segmentation object for cylinder segmentation and set all the parameters
  seg.setOptimizeCoefficients (true);
  seg.setModelType (pcl::SACMODEL_CYLINDER);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setNormalDistanceWeight (0.1);
  seg.setMaxIterations (10000);
  seg.setDistanceThreshold (0.05);
  seg.setRadiusLimits (0, 0.1);
  seg.setInputCloud (cloud_filtered2);
  seg.setInputNormals (cloud_normals2);

  // Obtain the cylinder inliers and coefficients
  seg.segment (*inliers_cylinder, *coefficients_cylinder);
  std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;

  // Write the cylinder inliers to disk
  extract.setInputCloud (cloud_filtered2);
  extract.setIndices (inliers_cylinder);
  extract.setNegative (false);
  pcl::PointCloud<PointT>::Ptr cloud_cylinder (new pcl::PointCloud<PointT> ());
  extract.filter (*cloud_cylinder);

  if (cloud_cylinder->points.empty ()) 
    std::cerr << "Can't find the cylindrical component." << std::endl;
  else
  {
	  std::cerr << "PointCloud representing the cylindrical component: " << cloud_cylinder->points.size () << " data points." << std::endl;
	  writer.write ("table_scene_mug_stereo_textured_cylinder.pcd", *cloud_cylinder, false);
  }

  std::cerr << "Start display……" << std::endl;
  // display  
  pcl::visualization::PCLVisualizer p;
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> source(cloud, 255, 0, 0);
  p.setWindowName("源数据");
  p.addPointCloud(cloud, source, "source");
  p.spinOnce();

  pcl::visualization::PCLVisualizer p2;
  pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> ps_filtered(cloud_filtered, 0, 255, 0);
  p2.setWindowName("直通滤波后的数据");
  p2.addPointCloud(cloud_filtered, ps_filtered, "ps_filtered");
  p2.spinOnce();//no spin()  

  //pcl::visualization::PCLVisualizer p3;
  //pcl::visualization::PointCloudColorHandlerCustom<pcl::Normal> normals(cloud_normals, 0, 0, 255);
  //p3.setWindowName("法线数据");
  //p3.addPointCloud(cloud_normals, normals, "normals");
  //p3.spinOnce();

  pcl::visualization::PCLVisualizer p4;
  pcl::visualization::PointCloudColorHandlerCustom<PointT> extra_outlier(cloud_filtered2, 0, 0, 255);
  p4.setWindowName("提取外点数据");
  p4.addPointCloud(cloud_filtered2, extra_outlier, "extra_outlier");
  p4.spinOnce();

  pcl::visualization::PCLVisualizer p5;
  //pcl::visualization::PointCloudColorHandlerCustom<pcl::Normal> normals2(cloud_normals2, 0, 0, 255);
  p5.setWindowName("提取外点法线数据");
  p5.addPointCloudNormals<PointT, pcl::Normal>(cloud_filtered2, cloud_normals2, 10, 0.05, "normals2");//normals corresponded with origin data
  p5.spinOnce();

  pcl::visualization::PCLVisualizer p6;
  pcl::visualization::PointCloudColorHandlerCustom<PointT>  plane(cloud_plane, 0, 0, 255);
  p6.setWindowName("内点平面");
  p6.addPointCloud(cloud_plane, plane, "plane");
  p6.addCylinder(*coefficients_plane, "coefficients_plane");
  p6.spinOnce();

  pcl::visualization::PCLVisualizer p7;
  pcl::visualization::PointCloudColorHandlerCustom<PointT>  cylinder(cloud_cylinder, 0, 0, 255);
  p7.setWindowName("内点柱面");
  p7.addPointCloud(cloud_cylinder, cylinder, "cylinder");
  p7.addCylinder(*coefficients_cylinder, "coefficients_cylinder");
  p7.spin();

  std::cerr << "The end……" << std::endl;

  return (0);
}

运行:


3、cluster extraction——欧式聚类提取(分割)

cpp:
#include <pcl/ModelCoefficients.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/features/normal_3d.h>
#include <pcl/kdtree/kdtree.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/visualization/pcl_visualizer.h>     
#include <pcl/common/time.h> 
#include <time.h>

int 
main (int argc, char** argv)
{
	clock_t start, end;
  // Read in the cloud data读数据
  pcl::PCDReader reader;
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);
  reader.read ("table_scene_lms400.pcd", *cloud);
  std::cout << "PointCloud before filtering has: " << cloud->points.size () << " data points." << std::endl; //*

  // Create the filtering object: downsample the dataset using a leaf size of 1cm体素栅格滤波
  pcl::VoxelGrid<pcl::PointXYZ> vg;
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
  vg.setInputCloud (cloud);
  vg.setLeafSize (0.01f, 0.01f, 0.01f);
  vg.filter (*cloud_filtered);
  std::cout << "PointCloud after filtering has: " << cloud_filtered->points.size ()  << " data points." << std::endl; //*

  // Create the segmentation object for the planar model and set all the parameters随机采样一致性分割
  pcl::SACSegmentation<pcl::PointXYZ> seg;
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZ> ());
  pcl::PCDWriter writer;
  seg.setOptimizeCoefficients (true);
  seg.setModelType (pcl::SACMODEL_PLANE);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setMaxIterations (100);
  seg.setDistanceThreshold (0.02);

  int i=0, nr_points = (int) cloud_filtered->points.size ();
  while (cloud_filtered->points.size () > 0.3 * nr_points)
  {
    // Segment the largest planar component from the remaining cloud从剩余点云中分割出最大平面
    seg.setInputCloud (cloud_filtered);
    seg.segment (*inliers, *coefficients);
    if (inliers->indices.size () == 0)
    {
      std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
      break;
    }

    // Extract the planar inliers from the input cloud从输入点云(滤波后的点云)中提取平面内点
    pcl::ExtractIndices<pcl::PointXYZ> extract;
    extract.setInputCloud (cloud_filtered);
    extract.setIndices (inliers);
    extract.setNegative (false);

    // Write the planar inliers to disk存储平面点云
    extract.filter (*cloud_plane);
    std::cout << "PointCloud representing the planar component: " << cloud_plane->points.size () << " data points." << std::endl;

    // Remove the planar inliers, extract the rest移除内点,提取剩下的点云
    extract.setNegative (true);
    extract.filter (*cloud_f);
    cloud_filtered = cloud_f;
  }

  // 
  // Creating the KdTree object for the search method of the extraction为提取算法创建KdTree
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
  tree->setInputCloud (cloud_filtered);
  // 

  std::vector<pcl::PointIndices> cluster_indices;
  pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;//欧式聚类
  ec.setClusterTolerance (0.02); // 2cm
  ec.setMinClusterSize (100);
  ec.setMaxClusterSize (25000);
  ec.setSearchMethod (tree);
  ec.setInputCloud (cloud_filtered);

  start = clock();
  ec.extract (cluster_indices);
  end = clock();

  // 

  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>);
    for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++)
      cloud_cluster->points.push_back (cloud_filtered->points[*pit]); //*
    cloud_cluster->width = cloud_cluster->points.size ();
    cloud_cluster->height = 1;
    cloud_cluster->is_dense = true;

    std::cout << "PointCloud representing the Cluster: " << cloud_cluster->points.size () << " data points." << std::endl;
    std::stringstream ss;
    ss << "cloud_cluster_" << j << ".pcd";
    writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false); //*
    j++;
  }
  //  
  //得到欧式聚类时间  
  std::cout << "欧式聚类运行时间" << std::endl;
  std::cout << "运行时间:" << (double)(end-start)/*/CLOCKS_PER_SEC*/ << "毫妙" << std::endl;
  
  //  
  pcl::visualization::PCLVisualizer viewer;
  int v1(0);
  viewer.createViewPort(0.0, 0.0, 0.25, 1.0, v1);
  viewer.setBackgroundColor(1.0, 0.5, 1.0, v1);
  viewer.addText("Remove the planar inliers, extract the rest ", 10, 10, "cloud_f", v1);
  viewer.addPointCloud(cloud_f, "cloud_f", v1);

  int v2(0);
  viewer.createViewPort(0.25, 0.0, 0.5, 1.0, v2);
  viewer.setBackgroundColor(1.0, 0.5, 1.0, v2);
  viewer.addText("cloud_plane", 10, 10, "cloud_plane", v2);
  viewer.addPointCloud(cloud_plane, "cloud_plane", v2);

  int v3(0);
  viewer.createViewPort(0.5, 0.0, 0.75, 1.0, v3);
  viewer.setBackgroundColor(1.0, 0.5, 1.0, v3);
  viewer.addText("cloud", 10, 10, "cloud", v3);
  viewer.addPointCloud(cloud, "cloud", v3);

  int v4(0);
  viewer.createViewPort(0.75, 0.0, 1.0, 1.0, v4);
  viewer.setBackgroundColor(1.0, 0.5, 1.0, v4);
  viewer.addText("cloud_filtered", 10, 10, "cloud_filtered", v4);
  viewer.addPointCloud(cloud_filtered, "cloud_filtered", v4);
  //
  viewer.spin();

  //  
  return (0);
}

运行:




4、区域生长分割:

代码:

#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d.h>
#include <pcl/segmentation/region_growing.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
using namespace std;

int
main(int argc, char** argv)
{	
	string filename("region_growing_tutorial.pcd");

	// Object for storing the point cloud.
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	// Object for storing the normals.
	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);

	// Read a PCD file from disk.
	if (pcl::io::loadPCDFile<pcl::PointXYZ>(filename, *cloud) != 0)//argv[1]
	{
		return -1;
	}

	// kd-tree object for searches.
	pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>);
	kdtree->setInputCloud(cloud);

	// Estimate the normals.
	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
	normalEstimation.setInputCloud(cloud);
	normalEstimation.setRadiusSearch(0.03);
	normalEstimation.setSearchMethod(kdtree);
	normalEstimation.compute(*normals);

	// Region growing clustering object.
	pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> clustering;
	clustering.setMinClusterSize(100);
	clustering.setMaxClusterSize(10000);
	clustering.setSearchMethod(kdtree);
	clustering.setNumberOfNeighbours(30);
	clustering.setInputCloud(cloud);
	clustering.setInputNormals(normals);
	// Set the angle in radians that will be the smoothness threshold
	// (the maximum allowable deviation of the normals).
	clustering.setSmoothnessThreshold(7.0 / 180.0 * M_PI); // 7 degrees.
	// Set the curvature threshold. The disparity between curvatures will be
	// tested after the normal deviation check has passed.
	clustering.setCurvatureThreshold(1.0);

	std::vector <pcl::PointIndices> clusters;
	clustering.extract(clusters);

	// For every cluster...
	int currentClusterNum = 1;
	for (std::vector<pcl::PointIndices>::const_iterator i = clusters.begin(); i != clusters.end(); ++i)
	{
		// ...add all its points to a new cloud...
		pcl::PointCloud<pcl::PointXYZ>::Ptr cluster(new pcl::PointCloud<pcl::PointXYZ>);
		for (std::vector<int>::const_iterator point = i->indices.begin(); point != i->indices.end(); point++)
			cluster->points.push_back(cloud->points[*point]);
		cluster->width = cluster->points.size();
		cluster->height = 1;
		cluster->is_dense = true;

		// ...and save it to disk.
		if (cluster->points.size() <= 0)
			break;
		std::cout << "Cluster " << currentClusterNum << " has " << cluster->points.size() << " points." << std::endl;
		std::string fileName = "cluster" + boost::to_string(currentClusterNum) + ".pcd";
		pcl::io::savePCDFileASCII(fileName, *cluster);

		currentClusterNum++;
	}

	//Read cluster cloud points saved above from file
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster1(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster2(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster3(new pcl::PointCloud<pcl::PointXYZ>);

	pcl::io::loadPCDFile("cluster1.pcd",*cloud_cluster1);
	pcl::io::loadPCDFile("cluster2.pcd", *cloud_cluster2);
	pcl::io::loadPCDFile("cluster3.pcd",*cloud_cluster3);

	//Visualization
	pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D viewer"));
	
	//create viewport #1
	int v1(0);
	viewer->createViewPort(0.0, 0.5, 0.5, 1.0, v1);
	viewer->setBackgroundColor(0.5, 0.5, 0.5);
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_handle1(cloud_cluster1, 250, 0, 0);
	viewer->addPointCloud(cloud_cluster1,cloud_handle1,"cluster1",v1);
	viewer->spinOnce();

	//create viewport #2
	int v2(0);
	viewer->createViewPort(0.5, 0.5, 1.0, 1.0, v2);
	viewer->setBackgroundColor(0.5, 0.5, 0.5);
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_handle2(cloud_cluster2, 0, 250, 0);
	viewer->addPointCloud(cloud_cluster2, cloud_handle2, "cluster2", v2);
	viewer->spinOnce();

	//create viewport #3
	int v3(0);
	viewer->createViewPort(0.0, 0.0, 0.5, 0.5, v3);
	viewer->setBackgroundColor(0.5, 0.5, 0.5);
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_handle3(cloud_cluster3, 0, 0, 250);
	viewer->addPointCloud(cloud_cluster3, cloud_handle3, "cluster3", v3);
	viewer->spinOnce();

	//create viewport #4
	int v4(0);
	viewer->createViewPort(0.5, 0.0, 1.0, 0.5, v4);
	viewer->setBackgroundColor(0.5, 0.5, 0.5);
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_handle(cloud, 220, 220, 20);
	viewer->addPointCloud(cloud, cloud_handle, "cloud", v4);
	viewer->spin();

}

运行结果:





5、RANSAC模型分割,基本的代码

 //创建一个模型参数对象,用于记录结果
  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 (cloud);
  //分割点云
  seg.segment (*inliers, *coefficients);


上面的模型系数计算出来后可以直接输出。在有的函数中会用到模型参数进行集合建模,如直线和平面等。


评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值