1 几个主要的类
1.1 StatisticalOutlierRemoval类
基于统计方法移除点云中的离散点的类,对每个点,我们计算它到它的所有临近点的平均距离。假设得到的结果是一个高斯分布,其形状由均值和标准差决定,平均距离在标准范围(由全局距离平均值和方差定义)之外的点,可被定义为离群点并可从数据集中去除掉。
//读取点云
pcl::PCDReaderreader;//定义读取对象
reader.read<pcl::PointXYZ>("table_scene_lms400.pcd",*cloud);//读取点云文件
///点云滤波//
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;// 创建滤波器对象
sor.setInputCloud(cloud); //设置待滤波的点云
sor.setMeanK(50); //设置在进行统计时考虑查询点邻近点数
sor.setStddevMulThresh(1.0); //设置判断是否为离群点的阈值
sor.filter(*cloud_filtered); //执行滤波处理保存内点到cloud_filtered
//如果要提取外点
//sor.setNegative(true);
//sor.filter(*cloud_filtered);
//输出滤波后的点云个数
cout << sor_cloud->size() << endl;
//输出滤波结果
writer.write<pcl::PointXYZ>("table_scene_lms400_outliers.pcd",*cloud_filtered,false);
1.2 SACSegmentation分割类
几个重要的成员函数
函数 | 功能 |
inline void setModelType (int model) | 所提取目标模型的属性(平面、球、圆柱等等)。 enum SacModel |
inline voidsetMethodType (int method) | 采样方法 namespace pcl |
inline void setDistanceThreshold (doublethreshold) | 查询点到目标模型的距离阈值 (如果大于此阈值,则查询点不在目标模型上,默认值为0)。 |
inline void setMaxIterations (intmax_iterations) | 最大迭代次数(默认值为50)。 |
inline void setProbability (double probability) | 至少一个样本不包含离群点的概率(默认值为0.99) |
virtual void segment (PointIndices &inliers,ModelCoefficients &model_coefficients) | 输出提取点的索引和目标模型的参数 |
inline void setInputCloud (const PointCloudConstPtr &cloud) | 设置输入点云 |
一个分割代码片段
SACSegmentation<PoinT> sac;//创建分割对象
PointIndices::Ptr inliner(new PointIndices);
ModelCoefficients::Ptr coefficients(new ModelCoefficients);
PointCloud<PoinT>::Ptr sac_cloud(new PointCloud<PoinT>);
sac.setInputCloud(sor_cloud);//设置输入点云
sac.setMethodType(SAC_RANSAC);//选择随机抽样一致性算法
sac.setModelType(SACMODEL_PLANE);//提取的是平面
sac.setMaxIterations(100);//最大迭代次数为100
sac.setDistanceThreshold(0.01);//距离阈值为0.01
sac.setProbability(0.95);
sac.segment(*inliers, *coefficients);
1.3 ExtractIndices根据点云索引提取点云子集
ExtractIndices<PoinT>ext;//创建提取点云索引对象
ext.setInputCloud(sor_cloud);//设置输入点云数据
ext.setIndices(inliner);//设置点云索引
ext.setNegative(false);//保留内点
ext.filter(*ext_cloud);//滤波
ext.setNegative(true);//保留外点
ext.filter(*ext_cloud_rest);//滤波
//内点的分层可视化
visualization::PointCloudColorHandlerCustom<PoinT> rgb1(ext_cloud, rand() % 255, rand() % 255, rand() % 255);//提取的平面不同随机彩色展示
visualization::PCLVisualizer viewer;
viewer.addPointCloud(ext_cloud, rgb1, ss.str());
2 分离的示例代码及结果
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/extract_indices.h>
#include<ctime>
#include<cstdlib>
#include <windows.h>
#include "deal.h"
using namespace pcl;
using namespace std;
//显示点云
void cloudShow(string cloudFileName)
{
pcl::PointCloud<pcl::PointXYZ> cloud1;
int ret = pcl::io::loadPCDFile(cloudFileName, &cloud1);
pcl::visualization::CloudViewer viewer("Cloud Viewer");
viewer.showCloud(&cloud1);
viewer.runOnVisualizationThreadOnce(viewerOneOff);//设置控制台的背景色
while(!viewer.wasStopped()){
}
}
//设置显示的背景色
void viewerOneOff(pcl::visualization::PCLVisualizer& viewer)
{
viewer.setBackgroundColor(0,0,1);
}
//剔除地面点
void splitGround()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCDReader reader;
// 读入点云PCD文件
reader.read("desk.pcd",*cloud);
std::cerr << "Point cloud data: " << cloud->points.size () << " points" << std::endl;
pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
// Create the segmentation object
pcl::SACSegmentation<pcl::PointXYZ> seg;
// Optional
seg.setOptimizeCoefficients (true);
// Mandatory
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
// 距离阈值 单位m
seg.setDistanceThreshold (0.15);
seg.setInputCloud (cloud);
seg.segment (*inliers, *coefficients);
if (inliers->indices.size () == 0)
{
PCL_ERROR ("Could not estimate a planar model for the given dataset.");
return;
}
// 提取地面
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud (cloud);
extract.setIndices (inliers);
extract.filter (*cloud_filtered);
std::cerr << "Ground cloud after filtering: " << std::endl;
std::cerr << *cloud_filtered << std::endl;
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("3dpoints_ground.pcd", *cloud_filtered, false);
// 提取除地面外的物体
extract.setNegative (true);
extract.filter (*cloud_filtered);
std::cerr << "Object cloud after filtering: " << std::endl;
std::cerr << *cloud_filtered << std::endl;
writer.write<pcl::PointXYZ> ("3dpoints_object.pcd", *cloud_filtered, false);
// 点云可视化
pcl::visualization::CloudViewer viewer("Filtered");
viewer.showCloud(cloud_filtered);
viewer.runOnVisualizationThreadOnce(viewerOneOff);
while(!viewer.wasStopped()){
}
system("pause");
return;
}
int main()
{
splitGround();
return 0;
}
原始点云:
滤波结果(地面点已经被过滤掉):
参考阅读
PCL: Segmentation模块之SACSegmentation点云分割
如果你需要其他测试数据,可查阅该网址