pcl点云库的使用05:提取点云数据中的非地面点的方法

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
  {
    SACMODEL_PLANE,
    SACMODEL_LINE,
    SACMODEL_CIRCLE2D,
    SACMODEL_CIRCLE3D,
    SACMODEL_SPHERE,
    SACMODEL_CYLINDER,
    SACMODEL_CONE,
    SACMODEL_TORUS,
    SACMODEL_PARALLEL_LINE,
    SACMODEL_PERPENDICULAR_PLANE,
    SACMODEL_PARALLEL_LINES,
    SACMODEL_NORMAL_PLANE,
    SACMODEL_NORMAL_SPHERE,
    SACMODEL_REGISTRATION,
    SACMODEL_PARALLEL_PLANE,
    SACMODEL_NORMAL_PARALLEL_PLANE,
    SACMODEL_STICK
  };

inline voidsetMethodType (int method)

采样方法

namespace pcl
{
  const static int SAC_RANSAC  = 0;
  const static int SAC_LMEDS   = 1;
  const static int SAC_MSAC    = 2;
  const static int SAC_RRANSAC = 3;
  const static int SAC_RMSAC   = 4;
  const static int SAC_MLESAC  = 5;
  const static int SAC_PROSAC  = 6;
}

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点云分割

如果你需要其他测试数据,可查阅该网址

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛桂琴

喜欢的读者,可以打赏鼓励一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值