函数注释很详细

  1 #include <pcl/ModelCoefficients.h>
  2 #include <pcl/io/pcd_io.h>
  3 #include <pcl/point_types.h>
  4 #include <pcl/filters/extract_indices.h>
  5 #include <pcl/filters/passthrough.h>
  6 #include <pcl/features/normal_3d.h>
  7 #include <pcl/sample_consensus/method_types.h>
  8 #include <pcl/sample_consensus/model_types.h>
  9 #include <pcl/segmentation/sac_segmentation.h>//基于采样一致性分割的类的头文件
 10 #include <pcl/visualization/pcl_visualizer.h>
 11 
 12 typedef pcl::PointXYZ PointT;
 13 
 14 int
 15 main(int argc, char** argv)
 16 {
 17     // ************设置所需对象读入点云数据
 18     pcl::PCDReader reader;                    //PCD文件读取对象
 19     pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
 20     reader.read("table_scene_mug_stereo_textured.pcd", *cloud);
 21     std::cerr << "PointCloud has: " << cloud->points.size() << " data points." << std::endl;
 22 
 23     // ***********直通滤波,将Z轴不在(0,1.5)范围的点过滤掉,将剩余的点存储到cloud_filtered对象中
 24     pcl::PassThrough<PointT> pass;             //直通滤波对象
 25     pass.setInputCloud(cloud);
 26     pass.setFilterFieldName("z");
 27     pass.setFilterLimits(0,1.5);
 28     pcl::PointCloud<PointT>::Ptr cloud_filtered(new pcl::PointCloud<PointT>);
 29     pass.filter(*cloud_filtered);
 30     std::cerr << "PointCloud after filtering has: " << cloud_filtered->points.size() << " data points." << std::endl;
 31 
 32     // ************点云进行法线估计,为后续进行基于法线的分割准备数据
 33     pcl::NormalEstimation<PointT, pcl::Normal> ne;  //法线估计对象
 34     pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>());
 35     ne.setSearchMethod(tree);//设置内部算法实现时所用的搜索对象,tree为指向kdtree或者octree对应的指针
 36     ne.setInputCloud(cloud_filtered);
 37     ne.setKSearch(50);// 设置K近邻搜索时所用的K参数
 38     pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);
 39     ne.compute(*cloud_normals);//计算特征值
 40     cout << cloud_normals->points.size();
 41     // ****************为平面模型创建分割对象并设置所有参数
 42     pcl::SACSegmentationFromNormals<PointT, pcl::Normal> seg;    //分割对象
 43     pcl::ModelCoefficients::Ptr coefficients_plane(new pcl::ModelCoefficients);
 44     pcl::PointIndices::Ptr inliers_plane(new pcl::PointIndices), inliers_cylinder(new pcl::PointIndices);
 45     seg.setOptimizeCoefficients(true);
 46     seg.setModelType(pcl::SACMODEL_NORMAL_PLANE);//设置模型类型
 47     seg.setMethodType(pcl::SAC_RANSAC);//设置随机采样一致性方法类型
 48     seg.setNormalDistanceWeight(0.1);  // 法线信息权重
 49     seg.setMethodType(pcl::SAC_RANSAC);//随机采样一致性算法
 50     seg.setMaxIterations(100);         //最大迭代次数
 51     seg.setDistanceThreshold(0.03);    //设置内点到模型的距离允许最大值
 52     seg.setInputCloud(cloud_filtered); //输入点云
 53     seg.setInputNormals(cloud_normals);//设置输人点云的法线,normals为指向法线的指针。
 54     seg.segment(*inliers_plane, *coefficients_plane);//存储分割结果到点几何inliers_plane及存储平面模型的系数coefficients_plane
 55     std::cerr << "Plane coefficients: " << *coefficients_plane << std::endl;
 56 
 57     // *************从点云中抽取分割的处在平面上的点集
 58     pcl::ExtractIndices<PointT> extract;      //// 创建滤波器对象(点提取对象)
 59     pcl::PointCloud<PointT>::Ptr cloud_plane(new pcl::PointCloud<PointT>());
 60     pcl::PointCloud<PointT>::Ptr cloud_filtered2(new pcl::PointCloud<PointT>);
 61     extract.setInputCloud(cloud_filtered);
 62     extract.setIndices(inliers_plane);//设置分割后的点内为需要提取的点集
 63     extract.setNegative(false);//设置提取点内而非点外。
 64     extract.filter(*cloud_plane);// 存储分割得到的平面上的点到点云文件
 65     extract.setNegative(true);//设置提取点外而非点内。
 66     extract.filter(*cloud_filtered2);//提取输出并储存到cloud_filterd2
 67     std::cerr << "PointCloud representing the planar component: " << cloud_plane->points.size() << " data points." << std::endl;
 68     
 69     // ************Remove the planar inliers, extract the rest
 70     pcl::ExtractIndices<pcl::Normal> extract_normals;    //点提取对象
 71     pcl::PointCloud<pcl::Normal>::Ptr cloud_normals2(new pcl::PointCloud<pcl::Normal>);
 72     extract_normals.setInputCloud(cloud_normals);
 73     extract_normals.setIndices(inliers_plane);
 74     extract_normals.setNegative(true);
 75     extract_normals.filter(*cloud_normals2);
 76 
 77     // **************创建圆柱体的分割对象并设置所有参数
 78     seg.setOptimizeCoefficients(true);         //设置对估计模型优化
 79     seg.setModelType(pcl::SACMODEL_CYLINDER);  //设置分割模型为圆柱形
 80     seg.setMethodType(pcl::SAC_RANSAC);        //参数估计方法
 81     seg.setNormalDistanceWeight(0.1);          //设置表面法线权重系数
 82     seg.setMaxIterations(10000);               //设置迭代的最大次数10000
 83     seg.setDistanceThreshold(0.05);            //设置内点到模型的距离允许最大值
 84     seg.setRadiusLimits(0, 0.1);               //设置估计出的圆柱模型的半径的范围
 85     seg.setInputCloud(cloud_filtered2);
 86     seg.setInputNormals(cloud_normals2);//设置输人点云的法线,normals为指向法线的指针。
 87     // Obtain the cylinder inliers and coefficients
 88     pcl::ModelCoefficients::Ptr  coefficients_cylinder(new pcl::ModelCoefficients);
 89     seg.segment(*inliers_cylinder, *coefficients_cylinder);
 90     std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;
 91 
 92     // Write the cylinder inliers to disk
 93     extract.setInputCloud(cloud_filtered2);
 94     extract.setIndices(inliers_cylinder);
 95     extract.setNegative(false);
 96     pcl::PointCloud<PointT>::Ptr cloud_cylinder(new pcl::PointCloud<PointT>());
 97     extract.filter(*cloud_cylinder);
 98     if (cloud_cylinder->points.empty())
 99         std::cerr << "Can't find the cylindrical component." << std::endl;
100     else
101     {
102         std::cerr << "PointCloud representing the cylindrical component: " << cloud_cylinder->points.size() << " data points." << std::endl;
103         //writer.write("table_scene_mug_stereo_textured_cylinder.pcd", *cloud_cylinder, false);
104     }
105 
106 
107 
108     // 可视化部分
109     pcl::visualization::PCLVisualizer v0("segmention");
110     // 我们将要使用的颜色
111     float bckgr_gray_level = 0.0;  // 黑色
112     float txt_gray_lvl = 1.0 - bckgr_gray_level;
113 
114     // 设置初始点云为白色
115     pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_in_color_h(cloud, (int)255 * txt_gray_lvl, (int)255 * txt_gray_lvl,
116         (int)255 * txt_gray_lvl);//赋予显示点云的颜色
117     v0.addPointCloud(cloud, cloud_in_color_h, "cloud");
118 
119 
120     // 可视化部分
121     pcl::visualization::PCLVisualizer viewer("segmention");
122 
123     // 设置cloud_plane点云为红色
124     pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_tr_color_h(cloud_plane, 0, 0, 255);
125     viewer.addPointCloud(cloud_plane, cloud_tr_color_h, "cloud_plane");
126 
127     //  设置cloud_cylinder点云为绿色
128     pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_icp_color_h(cloud_cylinder, 0, 255, 0);
129     viewer.addPointCloud(cloud_cylinder, cloud_icp_color_h, "cloud_cylinder");
130 
131     // 启动可视化,可以取消
132     v0.addCoordinateSystem(0.0);
133     v0.initCameraParameters();
134     viewer.addCoordinateSystem(0.0);
135     viewer.initCameraParameters();
136 
137     //等待直到可视化窗口关闭。
138     while (!viewer.wasStopped())
139     {
140         v0.spinOnce(100);
141         viewer.spinOnce(100);
142         boost::this_thread::sleep(boost::posix_time::microseconds(100000));
143     }
144 
145     return (0);
146 }