PCL滤波介绍(3)
(1)从一个点云中提取索引
如何使用一个,基于某一分割算法提取点云中的一个子集。
代码解析
#include <iostream>
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#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> int
main (int argc, char** argv)
{ /**********************************************************************************************************
从输入的.PCD 文件载入数据后,创建一个VOxelGrid滤波器对数据进行下采样,在这里进行下才样是为了加速处理过程,
越少的点意味着分割循环中处理起来越快
**********************************************************************************************************/ pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filtered_blob (new pcl::PCLPointCloud2);//申明滤波前后的点云
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>); // 读取PCD文件
pcl::PCDReader reader;
reader.read ("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); // 设置采样体素大小
sor.filter (*cloud_filtered_blob); //保存 // 转换为模板点云
pcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered); std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl; // 保存下采样后的点云
pcl::PCDWriter writer;
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 ()); pcl::SACSegmentation<pcl::PointXYZ> seg; //创建分割对象 seg.setOptimizeCoefficients (true); //设置对估计模型参数进行优化处理 seg.setModelType (pcl::SACMODEL_PLANE); //设置分割模型类别
seg.setMethodType (pcl::SAC_RANSAC); //设置用哪个随机参数估计方法
seg.setMaxIterations (); //设置最大迭代次数
seg.setDistanceThreshold (0.01); //判断是否为模型内点的距离阀值 // 设置ExtractIndices的实际参数
pcl::ExtractIndices<pcl::PointXYZ> extract; //创建点云提取对象 int i = , nr_points = (int) cloud_filtered->points.size ();
// While 30% of the original cloud is still there
while (cloud_filtered->points.size () > 0.3 * nr_points)
{
// 为了处理点云包含的多个模型,在一个循环中执行该过程并在每次模型被提取后,保存剩余的点进行迭代
seg.setInputCloud (cloud_filtered);
seg.segment (*inliers, *coefficients);
if (inliers->indices.size () == )
{
std::cerr << "Could not estimate a planar model for the given dataset." << std::endl;
break;
} // Extract the inliers
extract.setInputCloud (cloud_filtered);
extract.setIndices (inliers);
extract.setNegative (false);
extract.filter (*cloud_p);
std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl; std::stringstream ss;
ss << "table_scene_lms400_plane_" << i << ".pcd";
writer.write<pcl::PointXYZ> (ss.str (), *cloud_p, false); // Create the filtering object
extract.setNegative (true);
extract.filter (*cloud_f);
cloud_filtered.swap (cloud_f);
i++;
} return ();
}
结果:

显示出来:

图1 原始点云图像 图2 下采样后点云数据

图3 分割得到的其一平面模型 图4 分割得到的其二平面模型
(2)使用ConditionalRemoval 或RadiusOutlinerRemoval移除离群点
如何在滤波模块使用几种不同的方法移除离群点,对于ConditionalRemoval滤波器,可以一次删除满足对输入的点云设定的一个或多个条件指标的所有的数据点,RadiusOutlinerRemoval滤波器,它可以删除在输入点云一定范围内没有至少达到足够多近邻的所有数据点。
关于RadiusOutlinerRemoval的理解,在点云数据中,设定每个点一定范围内周围至少有足够多的近邻,不满足就会被删除
关于ConditionalRemoval 这个滤波器删除点云中不符合用户指定的一个或者多个条件的数据点
新建文件remove_outliers.cpp
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h> int
main (int argc, char** argv)
{
if (argc != ) //确保输入的参数
{
std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
exit();
}
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>); //填充点云
cloud->width = ;
cloud->height = ;
cloud->points.resize (cloud->width * cloud->height); for (size_t i = ; i < cloud->points.size (); ++i)
{
cloud->points[i].x = * rand () / (RAND_MAX + 1.0f);
cloud->points[i].y = * rand () / (RAND_MAX + 1.0f);
cloud->points[i].z = * rand () / (RAND_MAX + 1.0f);
} if (strcmp(argv[], "-r") == ){
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem; //创建滤波器 outrem.setInputCloud(cloud); //设置输入点云
outrem.setRadiusSearch(0.8); //设置半径为0.8的范围内找临近点
outrem.setMinNeighborsInRadius (); //设置查询点的邻域点集数小于2的删除
// apply filter
outrem.filter (*cloud_filtered); //执行条件滤波 在半径为0.8 在此半径内必须要有两个邻居点,此点才会保存
}
else if (strcmp(argv[], "-c") == ){
//创建条件限定的下的滤波器
pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond (new
pcl::ConditionAnd<pcl::PointXYZ> ()); //创建条件定义对象
//为条件定义对象添加比较算子
range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (new
pcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::GT, 0.0))); //添加在Z字段上大于0的比较算子 range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (new
pcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::LT, 0.8))); //添加在Z字段上小于0.8的比较算子
// 创建滤波器并用条件定义对象初始化
pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
condrem.setCondition (range_cond);
condrem.setInputCloud (cloud); //输入点云
condrem.setKeepOrganized(true); //设置保持点云的结构
// 执行滤波
condrem.filter (*cloud_filtered); //大于0.0小于0.8这两个条件用于建立滤波器
}
else{
std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
exit();
}
std::cerr << "Cloud before filtering: " << std::endl;
for (size_t i = ; i < cloud->points.size (); ++i)
std::cerr << " " << cloud->points[i].x << " "
<< cloud->points[i].y << " "
<< cloud->points[i].z << std::endl;
// display pointcloud after filtering
std::cerr << "Cloud after filtering: " << std::endl;
for (size_t i = ; i < cloud_filtered->points.size (); ++i)
std::cerr << " " << cloud_filtered->points[i].x << " "
<< cloud_filtered->points[i].y << " "
<< cloud_filtered->points[i].z << std::endl;
return ();
}
编译运行的结果为

从中可以看出ConditionalRemoval 或RadiusOutlinerRemoval的区别
RadiusOutlinerRemoval比较适合去除单个的离群点 ConditionalRemoval 比较灵活,可以根据用户设置的条件灵活过滤
微信公众号号可扫描二维码一起共同学习交流

PCL滤波介绍(3)的更多相关文章
- PCL滤波介绍(2)
(1)使用statisticalOutlierRemoval滤波器移除离群点 使用统计分析技术,从一个点云数据中集中移除测量噪声点(也就是离群点)比如:激光扫描通常会产生密度不均匀的点云数据集,另外测 ...
- PCL滤波介绍(1)
在获取点云数据时 ,由于设备精度,操作者经验环境因素带来的影响,以及电磁波的衍射特性,被测物体表面性质变化和数据拼接配准操作过程的影响,点云数据中讲不可避免的出现一些噪声.在点云处理流程中滤波处理作为 ...
- 图像处理之均值滤波介绍及C算法实现
1 均值滤波介绍 滤波是滤波是将信号中特定波段频率滤除的操作,是从含有干扰的接收信号中提取有用信号的一种技术. 均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临 ...
- 图像处理之中值滤波介绍及C实现
1 中值滤波概述 中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号平滑处理技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值. 中值滤波的基本原理是把数字图像或数字序 ...
- PCL—低层次视觉—点云滤波(初步处理)
点云滤波的概念 点云滤波是点云处理的基本步骤,也是进行 high level 三维图像处理之前必须要进行的预处理.其作用类似于信号处理中的滤波,但实现手段却和信号处理不一样.我认为原因有以下几个方面: ...
- PCL—点云滤波(初步处理)
博客转载自:http://www.cnblogs.com/ironstark/p/4991232.html 点云滤波的概念 点云滤波是点云处理的基本步骤,也是进行 high level 三维图像处理之 ...
- PCL学习笔记(一)
由于项目需要,开始学习一下HP公司的PCL打印语言,发现这方面的中文资料非常少,我做下记录也为后人提供便利. 关于PCL的介绍可以参考wiki百科 http://zh.wikipedia.org/zh ...
- PCL基础3.2-如何编写新的PCL类
1.文件名为mainBilateralFilter.cpp的文件内容如下 #include <pcl/point_types.h> #include <pcl/io/pcd_io.h ...
- opencv-11-中值滤波及自适应中值滤波
开始之前 在上一篇我们实现了读取噪声图像, 然后 进行三种形式的均值滤波得到结果, 由于我们自己写的均值滤波未作边缘处理, 所以效果有一定的下降, 但是总体来说, 我们得到的结果能够说明我们的算法执行 ...
随机推荐
- 安装CDH5时出错 5.68.168.192.in-addr.arpa domain name pointer bogon.
这个是因为使用的DNS是联通的server,联通会将所有保留的网络地址RFC1918( http://tools.ietf.org/html/rfc1918)都指向"bogon" ...
- 如何使用 Chrome 浏览器调试动态加载的 Javascript 脚本
在IE中,可以在调试程序的文档列表最下方看到一个"动态脚本"的文件夹,里面可以找到动态加载的脚本,但是...数量繁多,也不能自定义名称... 但是在 Chrome 中,貌似根本找不 ...
- Android Service GetSystemService
http://blog.sina.com.cn/s/blog_71d1e4fc0100o8qr.html http://blog.csdn.net/bianhaohui/article/details ...
- cxf、struts、spring中web.xml过滤url问题解决方案
利用struts2自带的正则匹配,应该说这算是最官方的解决方案了 在struts.properties中加正则匹配 struts.action.excludePattern=/webservice/. ...
- 【教程】ubuntu下安装samba服务器
一.准备工作 首先更新 software sources, 找到最快的源 lcw@ubuntu:~$ sudo apt-get update 二.安装samba lcw@ubuntu:~$ sudo ...
- java版本DbhelperMysql
package com.hebut.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.P ...
- 常用查找算法(Java)
常用查找算法(Java) 2018-01-22 1 顺序查找 就是一个一个依次查找 2 二分查找 二分查找(Binary Search)也叫作折半查找. 二分查找有两个要求, 一个是数列有序, 另一个 ...
- iOS高版本备份恢复到低版本系统的方法
一般来说,在更新iOS系统的时候我们都会建议大家先用iTunes对系统进行完整备份.但时不时都会有人偷懒,或者使用手机OTA升级而没有对系统备份,最终导致不满意新系统了,想降级却无备份可以恢复的尴尬局 ...
- Python给我的小伙伴来个微信机器人
[本文出自天外归云的博客园] 安装wxpy 首先你得去图灵机器人官网上注册个账号,登录后在机器人设置里面会有一个api_key,下文会用到! 然后说开发环境,我用的是python3环境,事先需要安装一 ...
- BAT-局域网内在线电脑IP
相关资料:朋友发来的,来源不明. 问题现象:有个朋友问我都在一个内网中,电脑A没有显示器,怎么找到它的IP. 问题处理: 1.登陆路由器查看IP在线情况. 2.用BAT文件显示出在线IP. 显示局域网 ...