RANSAC分割点云地面部分+可视化
win10操作系统PCL1.8.1+vs2015
程序主要用分割算法将地面点云和目标点云分割成两个部分然后输出目标点云,然后再可视化彩色点云的过程。可自行修改迭代次数和阙值,就是那个500和0.05,代码我自己跑过了,能用,那个阙值0.05自行修改。
以下是源码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/visualization/pcl_visualizer.h>
using namespace std;
void detectObjectsOnCloud(pcl::PointCloud<pcl::PointXYZRGB>::Ptr &cloud, pcl::PointCloud<pcl::PointXYZRGB>::Ptr &cloud_filtered)
{
if (cloud->size() > 0)
{
//------------------------------------------PCL分割框架--------------------------------------------------------
//创建分割时所需要的模型系数对象,coefficients及存储内点的点索引集合对象inliers
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
// 创建分割对象
pcl::SACSegmentation<pcl::PointXYZRGB> seg;
// 可选择配置,设置模型系数需要优化
seg.setOptimizeCoefficients(true);
// 必要的配置,设置分割的模型类型,所用的随机参数估计方法,距离阀值,输入点云
seg.setModelType(pcl::SACMODEL_PLANE);//设置模型类型
seg.setMethodType(pcl::SAC_RANSAC);//设置随机采样一致性方法类型
seg.setMaxIterations(500);//最大迭代次数
seg.setDistanceThreshold(0.005);//设定距离阀值,距离阀值决定了点被认为是局内点是必须满足的条件
seg.setInputCloud(cloud);//输入所需要分割的点云对象
//引发分割实现,存储分割结果到点几何inliers及存储平面模型的系数coefficients
seg.segment(*inliers, *coefficients);
//---------------------------------------------------------------------------------------------------------------
if (inliers->indices.size() == 0)
{
cout << "error! Could not found any inliers!" << endl;
}
// extract ground
// 从点云中抽取分割的处在平面上的点集
pcl::ExtractIndices<pcl::PointXYZRGB> extractor;//点提取对象
extractor.setInputCloud(cloud);
extractor.setIndices(inliers);
extractor.setNegative(true);
extractor.filter(*cloud_filtered);
// vise-versa, remove the ground not just extract the ground
// just setNegative to be true
cout << "filter done." << endl;
}
else
{
cout << "no data!" << endl;
}
}
int main(int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZRGB>);
// Fill in the cloud data
pcl::PCDReader reader;//PCD文件读取对象
// Replace the path below with the path where you saved your file
reader.read<pcl::PointXYZRGB>("5.21.pcd", *cloud);//“”内内容修改成你想分割的点云的文件名
detectObjectsOnCloud(cloud, cloud_filtered);//执行上面定义的分割函数
/*pcl::PCDWriter writer;
writer.write<pcl::PointXYZ>("pointcloud_files/000000_filtered.pcd", *cloud_filtered, false);*///和下面一行一样都是保存分割后点云的
pcl::io::savePCDFile("1cloud.pcd", *cloud_filtered);
cout << "Point cloud saved." << endl;
//---------------------------------------------------------PCL可视化-----------------------------------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("cloud show"));
int v1 = 0;
int v2 = 1;
viewer->createViewPort(0, 0, 0.5, 1, v1);
viewer->createViewPort(0.5, 0, 1, 1, v2);
viewer->setBackgroundColor(0, 0, 0, v1);
viewer->setBackgroundColor(0, 0, 0, v2);
pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
viewer->addPointCloud(cloud, "cloud", v1);
viewer->addPointCloud(cloud_filtered, "want cloud", v2);
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(10000));
}
return (0);
}