随机采样一致方法(RANSAC)
采用迭代的方式从一组包含离群的被观测数据中估算出数学模型的参数。RANSAC算法假设数据中包含正确数据和异常数据(或称为噪声)。正确数据记为内点(inliers),异常数据记为外点(outliers)。同时RANSAC也假设,给定一组正确的数据,存在可以计算出符合这些数据的模型参数的方法。该算法核心思想就是随机性和假设性,随机性是根据正确数据出现概率去随机选取抽样数据,根据大数定律,随机性模拟可以近似得到正确结果。假设性是假设选取出的抽样数据都是正确数据,然后用这些正确数据通过问题满足的模型,去计算其他点,然后对这次结果进行一个评分。
算法流程:
1. 要得到一个直线模型,需要两个点唯一确定一个直线方程。所以第一步随机选择两个点。
2. 通过这两个点,可以计算出这两个点所表示的模型方程y=ax+b。
3. 将所有的数据点套到这个模型中计算误差。
4. 找到所有满足误差阈值的点。
5. 然后我们再重复1~4这个过程,直到达到一定迭代次数后,选出那个被支持的最多的模型,作为问题的解。
#include <iostream> //标准C++库中的输入输出
#include <pcl/ModelCoefficients.h> //采样一致性模型头文件
#include <pcl/io/pcd_io.h>//pcd文件输入输出头文件
#include <pcl/point_types.h>//支持点类型头文件
#include <pcl/sample_consensus/method_types.h>//随机参数估计方法
#include <pcl/sample_consensus/model_types.h>//模型定义
#include <pcl/segmentation/sac_segmentation.h>//基于采样一致性分割的类的头文件
#include <pcl/filters/voxel_grid.h>//基于体素网格化的滤波
#include <pcl/filters/extract_indices.h>//索引提取
#include <pcl/visualization/pcl_visualizer.h>//可视化支持头文件
#include <pcl/filters/statistical_outlier_removal.h> //统计离群点
int
main(int argc, char** argv)
{
pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2), cloud_filtered_blob(new pcl::PCLPointCloud2);//创建指针cloud_blob cloud_filtered_blob
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>), cloud_p(new pcl::PointCloud<pcl::PointXYZ>), cloud_f(new pcl::PointCloud<pcl::PointXYZ>);
// 填入点云数据
pcl::PCDReader reader;//pcd读取
reader.read("D:\\pclcode\\pcl_segmentation\\planar_segmentation\\source\\table_scene_lms400.pcd", *cloud_blob);
std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl;
// 创建滤波器对象:使用叶大小为1cm的下采样
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;//创建体素滤波器对象
sor.setInputCloud(cloud_blob);//设置输入点云
sor.setLeafSize(0.01f, 0.01f, 0.01f);//设置叶大小为1cm
sor.filter(*cloud_filtered_blob);//执行滤波,将体素滤波(下采样)后的点云放置到cloud_filtered_blob
std::cerr << cloud_filtered_blob->width*cloud_filtered_blob->height << std::endl;//体素滤波后cloud_filtered_blob的总点数
// 转化为模板点云
pcl::fromPCLPointCloud2(*cloud_filtered_blob, *cloud_filtered);//将下采样后的点云转换为PoinCloud类型
std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;//滤波后的总点数
// 将下采样后的数据存入磁盘
pcl::PCDWriter writer;//pcd写操作
writer.write<pcl::PointXYZ>("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());//创建采样一致性模型指针
pcl::PointIndices::Ptr inliers(new pcl::PointIndices()); //创建一个PointIndices结构体指针
// 创建分割对象
pcl::SACSegmentation<pcl::PointXYZ> seg;//创建分割对象seg
// 可选
seg.setOptimizeCoefficients(true); //设置对估计的模型做优化处理
// 必选
seg.setModelType(pcl::SACMODEL_PLANE);//设置分割模型类别
seg.setMethodType(pcl::SAC_RANSAC);//设置使用那个随机参数估计方法为随机样本共识
seg.setMaxIterations(1000);//迭代次数
seg.setDistanceThreshold(0.01);//设置是否为模型内点的距离阈值
// 创建滤波器对象
pcl::ExtractIndices<pcl::PointXYZ> extract;
int i = 0, nr_points = (int)cloud_filtered->points.size();//nr_points表示原始点云数据
// 当还多于30%原始点云数据时
while (cloud_filtered->points.size() > 0.3 * nr_points)
{
// 从余下的点云中分割最大平面组成部分
seg.setInputCloud(cloud_filtered);//设置输入点云
seg.segment(*inliers, *coefficients);//分割点云
if (inliers->indices.size() == 0)
{
std::cerr << "Could not estimate a planar model for the given dataset.(无法估计给定数据集的平面模型。)" << std::endl;
break;
}
// 分离内层
extract.setInputCloud(cloud_filtered);//设置输入点云
extract.setIndices(inliers);//设置保留内点
extract.setNegative(false);//判断保留内点还是反向选取,false是保留内点,true是反选
extract.filter(*cloud_p);//执行滤波并将结果保存在cloud_p中
std::cerr << "cloud_filtered: " << cloud_filtered->size() << std::endl;//输出提取之后剩余的
std::cerr << "--------------------------------------------------" << std::endl;//设置屏幕分界线
//保存
std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl;//输出cloud_p的点数
std::stringstream ss;//将PointCloud representing the planar component这个字符串赋值给ss
ss << "table_scene_lms400_plane_" << i << ".pcd"; //对每一次的提取都进行了文件保存
writer.write<pcl::PointXYZ>(ss.str(), *cloud_p, false);
// 创建滤波器对象
extract.setNegative(true);//提取外层
extract.filter(*cloud_f);//将外层的提取结果保存到cloud_f
cloud_filtered.swap(cloud_f);//经cloud_filtered与cloud_f交换
i++;
}
std::cerr << "cloud_filtered: " << cloud_filtered->size() << std::endl;//输出cloud_filterd的总点数
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_seg1(new pcl::PointCloud<pcl::PointXYZ>);//创建cloud_seg1指针
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_seg2(new pcl::PointCloud<pcl::PointXYZ>);//创建cloud_seg2指针
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_voxel(new pcl::PointCloud<pcl::PointXYZ>);//创建cloud_voxel指针
pcl::io::loadPCDFile("table_scene_lms400_plane_0.pcd", *cloud_seg1);
pcl::io::loadPCDFile("table_scene_lms400_plane_1.pcd", *cloud_seg2);
pcl::io::loadPCDFile("table_scene_lms400_downsampled.pcd", *cloud_voxel);
//将提取结果进行统计学滤波
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor1;//创建统计滤波指针
sor1.setInputCloud(cloud_seg2);//设置输入点云cloud_seg2
sor1.setMeanK(50);//设置考虑查询点临近个数为50
sor1.setStddevMulThresh(1);//设置判断是否为离群点的阈值为1
sor1.filter(*cloud_f);//执行滤波,并将结果储存在cloud_f中
std::cerr<<cloud_f->size()<<std::endl;//输出cloud_f的总点数
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer);//创建可视化指针
viewer->initCameraParameters();//初始化相机参数
//设置第一个可视化窗口
int v1(0);
viewer->createViewPort(0, 0, 0.25, 1, v1);
viewer->setBackgroundColor(0, 255, 255, v1);//设置背景颜色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color1(cloud_voxel, 244, 89, 233);//设置点云颜色
viewer->addPointCloud(cloud_voxel, color1, "cloud_voxel", v1);
int v2(0);
viewer->createViewPort(0.25, 0, 0.5, 1, v2);
viewer->setBackgroundColor(125, 255, 47, v2);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color2(cloud_seg1, 255, 20, 0);
viewer->addPointCloud(cloud_seg1, color2, "cloud_seg1", v2); //注意id不能一样
int v3(0);
viewer->createViewPort(0.5, 0, 0.75, 1, v3);
viewer->setBackgroundColor(34, 128, 0, v3);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color3(cloud_seg2, 255, 20, 150);
viewer->addPointCloud(cloud_seg2, color3, "cloud_seg2", v3);
int v4(0);
viewer->createViewPort(0.75, 0, 1, 1, v4);
viewer->setBackgroundColor(255, 255, 255, v4);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color4(cloud_filtered, 244, 89, 0);
viewer->addPointCloud(cloud_filtered, color4, "cloud_statical", v4);
viewer->addCoordinateSystem();//添加坐标系
viewer->spin();
return (0);
}
//PointCloud before filtering : 460400 data points.
//41049
//PointCloud after filtering : 41049 data points.
//cloud_filtered : 41049
// --------------------------------------------------
// PointCloud representing the planar component : 20161 data points.
// cloud_filtered : 20888
// --------------------------------------------------
// PointCloud representing the planar component : 12114 data points.
// cloud_filtered : 8774
// 11836
CMakeLists文件如下:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(planar_segmentation2)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (planar_segmentation planar_segmentation.cpp)
target_link_libraries (planar_segmentation ${PCL_LIBRARIES})
执行效果如下所示:
去除坐标系:viewer->addCoordinateSystem();//添加坐标系
把这行代码注释掉就可以了
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL)//vtk必要头文件
#include <pcl/io/pcd_io.h>//pcd文件读写输入输出
#include <pcl/point_types.h>//支持点类型头文件
#include <pcl/filters/statistical_outlier_removal.h>//统计离群点
#include <pcl/segmentation/extract_clusters.h>//欧几里得分割
#include <pcl/visualization/pcl_visualizer.h>//pcl可视化支持头文件
#include <pcl/segmentation/sac_segmentation.h>//基于采样一致性分割
#include <pcl/ModelCoefficients.h>//采样一致性模型
#include <pcl/filters/extract_indices.h>//索引提取
#include<ctime>
#include<cstdlib>//随机产生随机数
//<1> 字符串转换atof: 字符串转浮点型;atoi:字符串转整型;atol:字符串转长整型
//<2> 伪随机序列生成 rand: 产生随机数 srand:初始化随机因子,防止随机数总是固定不变
//<3> 动态内存管理calloc, malloc,realloc, free
#include <windows.h>
using namespace pcl;
using namespace std;
typedef PointXYZ PoinT;
int *rand_rgb() {//随机产生颜色
int *rgb = new int[3];
rgb[0] = rand() % 255;
rgb[1] = rand() % 255;
rgb[2] = rand() % 255;
return rgb;
}
int main() {
//点云文件的读取
PointCloud<PoinT>::Ptr cloud(new PointCloud<PoinT>);//创建cloud指针
if (io::loadPCDFile("D:\\pclcode\\pcl_segmentation\\planar_segmentation2\\source\\table_scene_lms400.pcd", *cloud) == -1)
{
PCL_ERROR("read false");
return 0;
}
//去除噪声点
StatisticalOutlierRemoval<PoinT>sor;//创建滤波器对象
PointCloud<PoinT>::Ptr sor_cloud(new PointCloud<PoinT>);//创建sor_cloud指针
sor.setMeanK(10);//设置考虑查询点临近个数为10
sor.setInputCloud(cloud);//设置输入点云
sor.setStddevMulThresh(0.1);//设置判读是否为离群点的阈值
sor.filter(*sor_cloud);//执行滤波并将结果保存在sor_cloud中
cout << sor_cloud->size() << endl;//输出sor_cloud的点数
//平面分割(RANSAC)
SACSegmentation<PoinT> sac;//创建一个分割器
PointIndices::Ptr inliner(new PointIndices);//inliner表示误差能容忍的点,记录的是点云的序号
ModelCoefficients::Ptr coefficients(new ModelCoefficients);//创建一个模型参数对象,用于记录结果
PointCloud<PoinT>::Ptr sac_cloud(new PointCloud<PoinT>);//创建sac_cloud指针
sac.setInputCloud(sor_cloud);//设置输入点云
sac.setMethodType(SAC_RANSAC);//分割方法,随机采样法
sac.setModelType(SACMODEL_PLANE);//Mondatory设置目标几何形状
sac.setMaxIterations(100);//设置最大迭代次数
sac.setDistanceThreshold(0.01);//设置误差容忍范围
//提取平面(展示并输出)
PointCloud<PoinT>::Ptr ext_cloud(new PointCloud<PoinT>);//创建ext_cloud指针
PointCloud<PoinT>::Ptr ext_cloud_rest(new PointCloud<PoinT>);//创建ext_cloud_rest指针
visualization::PCLVisualizer::Ptr viewer(new visualization::PCLVisualizer("平面分割"));//屏幕可视化
int i = sor_cloud->size(), j = 0;//将sor_cloud的点数赋值给i
ExtractIndices<PoinT>ext;//创建提取对象ext
srand((unsigned)time(NULL));//刷新时间的种子节点需要放在循环体外面
while (sor_cloud->size() > i*0.0)//当提取的点数小于总数的3/10时,跳出循环
{
ext.setInputCloud(sor_cloud);
sac.segment(*inliner, *coefficients);//分割点云,得到参数
if (inliner->indices.size() == 0)
{
break;
}
//按照索引提取点云
ext.setIndices(inliner);//设置保留内点
ext.setNegative(false);//判断保留内点还是反向选取,false是保留内点,true是反选
ext.filter(*ext_cloud);//执行滤波,并将结果保存在ext_cloud中
ext.setNegative(true);//true是反选,反向选取
ext.filter(*ext_cloud_rest);//执行滤波并将结果保存在ext_cloud_rest中
*sor_cloud = *ext_cloud_rest;//将ext_cloud_rest赋值给sor_cloud
stringstream ss;//将字符串赋值给ss
ss << "D:\\pclcode\\pcl_segmentation\\planar_segmentation2\\source\\" << "ext_plane_clouds" << j << ".pcd";//路径加文件名和后缀
io::savePCDFileASCII(ss.str(), *ext_cloud);//提取的平面点云写出
int *rgb = rand_rgb();//随机生成0-255的颜色值
visualization::PointCloudColorHandlerCustom<PoinT>rgb1(ext_cloud, rgb[0], rgb[1], rgb[2]);//提取的平面不同彩色展示
delete[]rgb;//删除色彩信息
viewer->addPointCloud(ext_cloud, rgb1, ss.str());//添加坐标系
j++;
}
viewer->spin();
return 0;
CMakeLists文件按照上面的格式来修改一下就可以了!!!
执行效果如下所示:
#include <pcl/ModelCoefficients.h>//采样一致性模型头文件
#include <pcl/io/pcd_io.h>//pcd文件输入输出头文件
#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/visualization/pcl_visualizer.h>//可视化相关头文件
typedef pcl::PointXYZ PointT;
int
main(int argc, char** argv)
{
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>());//搜索方式对象
// 指针创建
pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);//创建cloud指针
pcl::PointCloud<PointT>::Ptr cloud_filtered(new pcl::PointCloud<PointT>);//创建cloud_filtered指针
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);//创建cloud_normals指针
pcl::PointCloud<PointT>::Ptr cloud_filtered2(new pcl::PointCloud<PointT>);//cloud_filtered2指针
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals2(new pcl::PointCloud<pcl::Normal>);//创建cloud_normals指针
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);//一个指向索引的指针
//
reader.read("D:\\pclcode\\pcl_segmentation\\cylinder_segmentation\\source\\table_scene_mug_stereo_textured.pcd", *cloud);
std::cerr << "PointCloud has: " << cloud->points.size() << " data points." << std::endl;//输出点云共有多少点
// 创建直通滤波器对点云机型滤波
//对cloud的z fields进行滤波,剔除0~1.5之外的点
pass.setInputCloud(cloud);//设置输入点云
pass.setFilterFieldName("z");//设置滤波的field
pass.setFilterLimits(0, 1.5);//滤波范围(0,1.5)
pass.filter(*cloud_filtered);//执行滤波,并将滤波结果保存在cloud_filtered中
std::cerr << "PointCloud after filtering has: " << cloud_filtered->points.size() << " data points." << std::endl;//输出直通滤波后点云的总点数
//点云法线估计
ne.setSearchMethod(tree);//搜索方式
ne.setInputCloud(cloud_filtered);//输入点云为直通滤波器的结果
ne.setKSearch(50);//选择最近邻的50个点进行法线估计
ne.compute(*cloud_normals);//法线的计算结果存放至cloud_normals
// 创建平面模型分割对象以及选择参数
seg.setOptimizeCoefficients(true);//选择是否优化系数
seg.setModelType(pcl::SACMODEL_NORMAL_PLANE);//Mondatory设置目标几何形状 使用附加约束确定平面模型
seg.setNormalDistanceWeight(0.1);//设置表面法线权重系数为0.1
seg.setMethodType(pcl::SAC_RANSAC);//设置分割方法为随采样法
seg.setMaxIterations(100);//设置最大迭代次数为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);//得到平面内点和平面的4个系数
std::cerr << "Plane coefficients: " << *coefficients_plane << std::endl;//输出平面
//从输入点云中分离内点
//提取出平面内点
extract.setInputCloud(cloud_filtered);//设置输入点云
extract.setIndices(inliers_plane);//分离平面内点
extract.setNegative(false);//false代表保留内点
// 将平面内点写入磁盘
pcl::PointCloud<PointT>::Ptr cloud_plane(new pcl::PointCloud<PointT>());//创建cloud_plane指针
extract.filter(*cloud_plane);//将平面点提取至clodu_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);//写入点云文件
// 移除内点平面,分离剩余点云
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);
//创建圆柱面分割对象,并选择参数
seg.setOptimizeCoefficients(true);选择是否优化系数
seg.setModelType(pcl::SACMODEL_CYLINDER);//Mondatory设置目标几何形状 用于确定气缸模型,圆柱体的七个系数由其轴上的点、轴方向和半径给出
seg.setMethodType(pcl::SAC_RANSAC);//设置分割方法为随机采样
seg.setNormalDistanceWeight(0.1);//设置表面法线权重系数为0.1
seg.setMaxIterations(10000);//设置最大迭代次数为10000
seg.setDistanceThreshold(0.05);//设置内点到距离模型的最大值为0.05
seg.setRadiusLimits(0, 0.1);//设置估计出的圆柱模型的半径范围
seg.setInputCloud(cloud_filtered2);//提取平面之后剩余的点云
seg.setInputNormals(cloud_normals2);//剩余点云的法向量
// 获得圆柱内点和系数
seg.segment(*inliers_cylinder, *coefficients_cylinder);//得到点的索引和圆柱体系数
std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;//圆柱体系数
//将圆柱写入磁盘
extract.setInputCloud(cloud_filtered2);
extract.setIndices(inliers_cylinder);//将圆柱面进行分离
extract.setNegative(false);//false代表保留内点
pcl::PointCloud<PointT>::Ptr cloud_cylinder(new pcl::PointCloud<PointT>());//创建cloud_cylinder指针
extract.filter(*cloud_cylinder);//按照圆柱体的索引将圆柱体的点提取至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);
}
//将原点云、平面cloud_plane、圆柱体cloud_cylinder可视化
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("圆柱面平面分割"));
//第一个窗口显示输入点云
int v1(0);
viewer->createViewPort(0, 0, 0.33, 1, v1);
viewer->setBackgroundColor(255, 255, 255, v1);//设置背景颜色
pcl::visualization::PointCloudColorHandlerCustom<PointT> color1(cloud, 244, 89, 233);//设置点云显示的颜色
viewer->addPointCloud(cloud, color1, "cloud", v1);//在窗口显示原始点云
//第二个窗口显示分割的平面
int v2(0);
viewer->createViewPort(0.33, 0, 0.66, 1, v2);
viewer->setBackgroundColor(135, 206, 235, v2);
pcl::visualization::PointCloudColorHandlerCustom<PointT> color2(cloud, 0, 240, 0);
viewer->addPointCloud(cloud_plane, color2, "cloud_plane", v2);//在中间窗口显示分离平面
//第三个窗口显示分割的圆柱
int v3(0);
viewer->createViewPort(0.66, 0, 1, 1, v3);
viewer->setBackgroundColor(255, 255, 255, v3);
pcl::visualization::PointCloudColorHandlerCustom<PointT> color3(cloud, 244, 89, 0);
viewer->addPointCloud(cloud_cylinder, color3, "cloud_cylinder", v3);//在右边窗口显示分离圆柱面
//viewer->addCoordinateSystem();//显示坐标系
while (!viewer->wasStopped())
{
viewer->spinOnce();//刷新
}
return (0);
}
//PointCloud has : 307200 data points.
//PointCloud after filtering has : 139897 data points.
//Plane coefficients : header:
//seq: 0 stamp : 0 frame_id :
// values[]
// values[0] : 0.0161902
// values[1] : -0.837667
// values[2] : -0.545941
// values[3] : 0.528862
//
// PointCloud representing the planar component : 116300 data points.
// Cylinder coefficients : header:
// seq: 0 stamp : 0 frame_id :
// values[]
// values[0] : 0.0543319
// values[1] : 0.100139
// values[2] : 0.787577
// values[3] : -0.0135876
// values[4] : 0.834831
// values[5] : 0.550338
// values[6] : 0.0387446
//
// PointCloud representing the cylindrical component : 11462 data points.
CMakeLists文件:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(cylinder_segmentation)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (cylinder_segmentation cylinder_segmentation.cpp)
target_link_libraries (cylinder_segmentation ${PCL_LIBRARIES})
执行效果如下所示: