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;
}
运行:
注意点:
- inline void setModelType (int model) 所提取目标模型的属性(平面、球、圆柱等等),这个示例中主要是提取平面。
- inline voidsetMethodType (int method)采样方法(RANSAC、LMedS)等,具体的方式可以参考教程,此处选随机一致性采样。
- 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);
上面的模型系数计算出来后可以直接输出。在有的函数中会用到模型参数进行集合建模,如直线和平面等。