热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

机器人三维视觉PCL点云库linux下使用滤波filters直通滤波器体素格滤波器VoxelGrid

linux下pcl安装1】命令行安装编译好的二进制文件sudoadd-apt-repositoryppa:v-launchpad-jochen-sprickerho

linux下pcl安装

1】命令行安装 编译好的二进制文件

sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pclsudo apt-get updatesudo apt-get install libpcl-all

2】源码安装



安装依赖Boost,Eigen,FlANN,VTK,OpenNI,QHullsudo apt-get install build-essential libboost-all-dev sudo apt-get install libvtk5-dev Vtk,(visualization toolkit 可视化工具包)是一个开源的免费软件系统,教程 http://blog.csdn.net/www_doling_net/article/details/8763686主要用于三维计算机图形学、图像处理和可视化。它在三维函数库OpenGL的基础上采用面向对象的设计方法发展而来,且具有跨平台的特性。 Vtk是在面向对象原理的基础上设计和实现的,它的内核是用C++构建的VTK面向对象,含有大量的对象模型。 源对象是可视化流水线的起点,映射器(Mapper)对象是可视化流水线的终点,是图形模型和可视化模型之间的接口. 回调(或用户方法): 观察者监控一个对象所有被调用的事件,如果正在监控的一个事件被触发,一个与之相应的回调函数就会被调用。图形模型:Renderer 渲染器,vtkRenderWindow 渲染窗口可视化模型:vtkDataObject 可以被看作是一个二进制大块(blob)vtkProcessObject 过程对象一般也称为过滤器,按照某种运算法则对数据对象进行处理FLANN介绍FLANN库全称是Fast Library for Approximate Nearest Neighbors,它是目前最完整的(近似)最近邻开源库。http://www.cs.ubc.ca/research/flann/uploads/FLANN/flann_manual-1.8.4.pdf去下载 http://www.cs.ubc.ca/research/flann/#downloadlinux下安装 eigensudo apt-get install libeigen3-dev定位安装位置locate eigen3sudo updatedb下载源码git clone https://github.com/PointCloudLibrary/pcl pcl-trunkcd pcl-trunk && mkdir build && cd buildcmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..make -j2sudo make -j2 install

点云滤波 /filters

点云滤波,顾名思义,就是滤掉噪声。原始采集的点云数据往往包含大量散列点、孤立点,

其类似于信号处理中的滤波,单实现手段却和信号处理不一样,主要有以下几方面原因:点云不是函数,无法建立横纵坐标之间的关系点云在空间中是离散的,不像图像信号有明显的定义域点云在空间中分布广泛,建立点与点之间的关系较为困难点云滤波依赖于集合信息而非数值信息

点云滤波方法主要有: 直通滤波器  pcl::PassThrough pass、体素格滤波器 pcl::VoxelGrid sor;、统计滤波器 pcl::StatisticalOutlierRemoval sor;、半径滤波器 pcl::RadiusOutlierRemoval outrem;双边滤波 pcl::BilateralFilter bf;空间剪裁:pcl::Clipper3Dpcl::BoxClipper3Dpcl::CropBoxpcl::CropHull 剪裁并形成封闭曲面卷积滤波:实现将两个函数通过数学运算产生第三个函数,可以设定不同的卷积核pcl::filters::Convolutionpcl::filters::ConvolvingKernel随机采样一致滤波等,通常组合使用完成任务。

1】直通滤波器 PassThrough 

github地址

/*
直通滤波器 PassThrough           直接指定保留哪个轴上的范围内的点
#include
如果使用线结构光扫描的方式采集点云,必然物体沿z向分布较广,
但x,y向的分布处于有限范围内。
此时可使用直通滤波器,确定点云在x或y方向上的范围,
可较快剪除离群点,达到第一步粗处理的目的。
// 创建点云对象 指针
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_filtered (new pcl::PointCloud);
// 原点云获取后进行滤波
pcl::PassThrough pass;// 创建滤波器对象
pass.setInputCloud (cloud);//设置输入点云
pass.setFilterFieldName ("z");//滤波字段名被设置为Z轴方向
pass.setFilterLimits (0.0, 1.0);//可接受的范围为(0.0,1.0)
//pass.setFilterLimitsNegative (true);//设置保留范围内 还是 过滤掉范围内
pass.filter (*cloud_filtered); //执行滤波,保存过滤结果在cloud_filtered
*/
#include
#include
#include //直通滤波器 PassThrough 
#include //点云可视化
// 别名
typedef pcl::PointCloud Cloud;intmain (int argc, char** argv)
{// 定义 点云对象 指针Cloud::Ptr cloud_ptr(new Cloud());Cloud::Ptr cloud_filtered_ptr(new Cloud());//pcl::PointCloud::Ptr cloud_ptr (new pcl::PointCloud);//pcl::PointCloud::Ptr cloud_filtered_ptr (new pcl::PointCloud);// 产生点云数据 cloud_ptr->width &#61; 5;cloud_ptr->height &#61; 1;cloud_ptr->points.resize (cloud_ptr->width * cloud_ptr->height);for (size_t i &#61; 0; i points.size (); &#43;&#43;i){cloud_ptr->points[i].x &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);cloud_ptr->points[i].y &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);cloud_ptr->points[i].z &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);}std::cerr <<"Cloud before filtering滤波前: " <points.size (); &#43;&#43;i)std::cerr <<" " <points[i].x <<" " <points[i].y <<" " <points[i].z < pass;pass.setInputCloud (cloud_ptr);//设置输入点云pass.setFilterFieldName ("z");// 定义轴pass.setFilterLimits (0.0, 1.0);// 范围pass.setFilterLimitsNegative (true);//标志为false时保留范围内的点pass.filter (*cloud_filtered_ptr);// 输出滤波后的点云std::cerr <<"Cloud after filtering滤波后: " <points.size (); &#43;&#43;i)std::cerr <<" " <points[i].x <<" " <points[i].y <<" " <points[i].z <}

&#xff12;】体素格滤波器VoxelGrid 

代码地址

/*
下载桌子点云数据
https://raw.github.com/PointCloudLibrary/data/master/tutorials/table_scene_lms400.pcd
体素格滤波器VoxelGrid  在网格内减少点数量保证重心位置不变 PCLPointCloud2()
下采样
#include
注意此点云类型为 pcl::PCLPointCloud2 类型 blob 格子类型
#include // 转换为模板点云 pcl::PointCloudpcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered);
如果使用高分辨率相机等设备对点云进行采集&#xff0c;往往点云会较为密集。
过多的点云数量会对后续分割工作带来困难。
体素格滤波器可以达到向下采样同时不破坏点云本身几何结构的功能。
点云几何结构 不仅是宏观的几何外形&#xff0c;也包括其微观的排列方式&#xff0c;
比如横向相似的尺寸&#xff0c;纵向相同的距离。
随机下采样虽然效率比体素滤波器高&#xff0c;但会破坏点云微观结构.
使用体素化网格方法实现下采样&#xff0c;即减少点的数量 减少点云数据&#xff0c;
并同时保存点云的形状特征&#xff0c;在提高配准&#xff0c;曲面重建&#xff0c;形状识别等算法速度中非常实用&#xff0c;
PCL是实现的VoxelGrid类通过输入的点云数据创建一个三维体素栅格&#xff0c;
容纳后每个体素内用体素中所有点的重心来近似显示体素中其他点&#xff0c;
这样该体素内所有点都用一个重心点最终表示&#xff0c;对于所有体素处理后得到的过滤后的点云&#xff0c;
这种方法比用体素中心&#xff08;注意中心和重心&#xff09;逼近的方法更慢&#xff0c;但是对于采样点对应曲面的表示更为准确。
*/
#include
#include
//#include
#include //体素格滤波器VoxelGrid
#include //点云文件pcd 读写
#include //点云可视化
#include //点云类型转换
/*
CloudViewer是简单显示点云的可视化工具&#xff0c;可以使用比较少的代码查看点云&#xff0c;
但是这个是不能用于多线程应用程序当中的。
下面的代码的工作是关于如何在可视化线程中运行代码的例子&#xff0c;
PCLVisualizer是CloudViewer的后端&#xff0c;但它在自己的线程中运行&#xff0c;
如果要使用PCLVisualizer类必须使用调用函数&#xff0c;这样可以避免可视化的并发问题。
但是在实际调用的时候要注意&#xff0c;以防出现核心已转储这一类很麻烦的问题。
*/
using namespace std;
// 别名
typedef pcl::PointCloud Cloud;intmain (int argc, char** argv)
{// 定义 点云对象 指针pcl::PCLPointCloud2::Ptr cloud2_ptr(new pcl::PCLPointCloud2());pcl::PCLPointCloud2::Ptr cloud2_filtered_ptr(new pcl::PCLPointCloud2());Cloud::Ptr cloud_filtered_ptr(new Cloud);// 读取点云文件 填充点云对象pcl::PCDReader reader;reader.read( "../table_scene_lms400.pcd", *cloud2_ptr);if(cloud2_ptr&#61;&#61;NULL) { cout <<"pcd file read err" <width * cloud2_ptr->height<<" data points ( " < vg;vg.setInputCloud (cloud2_ptr);//设置输入点云vg.setLeafSize(0.01f, 0.01f, 0.01f);// 体素块大小 &#xff11;cmvg.filter (*cloud2_filtered_ptr);// 输出滤波后的点云信息cout <<"PointCLoud before filtering 滤波后数量: " <width * cloud2_filtered_ptr->height<<" data points ( " <pcl::fromPCLPointCloud2 (*cloud2_filtered_ptr, *cloud_filtered_ptr);// 程序可视化pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字viewer.showCloud(cloud_filtered_ptr);while (!viewer.wasStopped()){// Do nothing but wait.}return (0);
}

&#xff13;】条件滤波器 conditional_removal

代码地址

/*
条件滤波器可以一次删除满足对输入的点云设定的一个或多个条件指标的所有的数据点删除点云中不符合用户指定的一个或者多个条件的数据点
不在条件范围内的点 被替换为 nan
#include
*/
#include
#include
//#include
//#include //模型系数头文件
//#include //投影滤波类头文件
#include //点云文件pcd 读写
//#include // 球半径滤波器
#include //条件滤波器//#include #include //点云可视化// 别名
typedef pcl::PointCloud Cloud;
using namespace std;
int main (int argc, char** argv)
{// 定义 点云对象 指针Cloud::Ptr cloud_ptr(new Cloud());Cloud::Ptr cloud_filtered_ptr(new Cloud());// 产生点云数据 cloud_ptr->width &#61; 5;cloud_ptr->height &#61; 1;cloud_ptr->points.resize (cloud_ptr->width * cloud_ptr->height);for (size_t i &#61; 0; i points.size (); &#43;&#43;i){cloud_ptr->points[i].x &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);cloud_ptr->points[i].y &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);cloud_ptr->points[i].z &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);}std::cerr <<"Cloud before filtering半径滤波前: " <points.size (); &#43;&#43;i)std::cerr <<" " <points[i].x <<" " <points[i].y <<" " <points[i].z <::Ptr range_cond_cptr(new pcl::ConditionAnd());//为条件定义对象添加比较算子range_cond_cptr->addComparison (pcl::FieldComparison::ConstPtr (newpcl::FieldComparison ("z", pcl::ComparisonOps::GT, 0.0)));//添加在Z字段上大于&#xff08;pcl::ComparisonOps::GT great Then&#xff09;0的比较算子range_cond_cptr->addComparison (pcl::FieldComparison::ConstPtr (newpcl::FieldComparison ("z", pcl::ComparisonOps::LT, 0.8)));//添加在Z字段上小于&#xff08;pcl::ComparisonOps::LT Lower Then&#xff09;0.8的比较算子// 创建滤波器并用条件定义对象初始化pcl::ConditionalRemoval conditrem;//创建条件滤波器conditrem.setCondition (range_cond_cptr); //并用条件定义对象初始化 conditrem.setInputCloud (cloud_ptr); //输入点云conditrem.setKeepOrganized(true); //设置保持点云的结构// 执行滤波conditrem.filter(*cloud_filtered_ptr); //大于0.0小于0.8这两个条件用于建立滤波器// 不在条件范围内的点 被替换为 nan// 输出滤波后的点云std::cerr <<"Cloud after filtering半径滤波后: " <points.size (); &#43;&#43;i)std::cerr <<" " <points[i].x <<" " <points[i].y <<" " <points[i].z < mapping;pcl::removeNaNFromPointCloud(*cloud_filtered_ptr, *cloud_filtered_ptr, mapping);// 输出去除nan后的点云std::cerr <<"Cloud after delet nan point去除nan点 : " <points.size (); &#43;&#43;i)std::cerr <<" " <points[i].x <<" " <points[i].y <<" " <points[i].z <}



&#xff14;】投影滤波 输出投影后的点的坐标 project_inliers

代码地址

/*投影滤波 输出投影后的点的坐标使用参数化模型投影点云
如何将点投影到一个参数化模型上&#xff08;平面或者球体等&#xff09;&#xff0c;
参数化模型通过一组参数来设定&#xff0c;对于平面来说使用其等式形式。
在PCL中有特定存储常见模型系数的数据结构。
#include //模型系数头文件
#include  //投影滤波类头文件
*/
#include
#include
//#include
#include //模型系数头文件
#include //投影滤波类头文件
#include //点云文件pcd 读写
#include //点云可视化// 别名
typedef pcl::PointCloud Cloud;
using namespace std;
int main (int argc, char** argv)
{// 定义 点云对象 指针Cloud::Ptr cloud_ptr(new Cloud());Cloud::Ptr cloud_filtered_ptr(new Cloud());//pcl::PointCloud::Ptr cloud_ptr (new pcl::PointCloud);//pcl::PointCloud::Ptr cloud_filtered_ptr (new pcl::PointCloud);// 产生点云数据 cloud_ptr->width &#61; 5;cloud_ptr->height &#61; 1;cloud_ptr->points.resize (cloud_ptr->width * cloud_ptr->height);for (size_t i &#61; 0; i points.size (); &#43;&#43;i){cloud_ptr->points[i].x &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);cloud_ptr->points[i].y &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);cloud_ptr->points[i].z &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);}std::cerr <<"Cloud before filtering投影滤波前: " <points.size (); &#43;&#43;i)std::cerr <<" " <points[i].x <<" " <points[i].y <<" " <points[i].z <values.resize (4);coefficients->values[0] &#61; coefficients->values[1] &#61; 0;coefficients->values[2] &#61; 1.0;coefficients->values[3] &#61; 0;// 创建投影滤波模型ProjectInliers对象&#xff0c;使用ModelCoefficients作为投影对象的模型参数pcl::ProjectInliers proj; //创建投影滤波对象proj.setModelType (pcl::SACMODEL_PLANE); //设置对象对应的投影模型  平面模型proj.setInputCloud (cloud_ptr); //设置输入点云proj.setModelCoefficients (coefficients); //设置模型对应的系数proj.filter (*cloud_filtered_ptr); //投影结果存储// 输出滤波后的点云std::cerr <<"Cloud after filtering投影滤波后: " <points.size (); &#43;&#43;i)std::cerr <<" " <points[i].x <<" " <points[i].y <<" " <points[i].z <}



&#xff15;】球半径滤波器 radius_outlier_removal

代码地址

/*
球半径滤波器
#include
球半径滤波器与统计滤波器相比更加简单粗暴。
以某点为中心 画一个球计算落在该球内的点的数量&#xff0c;当数量大于给定值时&#xff0c;
则保留该点&#xff0c;数量小于给定值则剔除该点。
此算法运行速度快&#xff0c;依序迭代留下的点一定是最密集的&#xff0c;
但是球的半径和球内点的数目都需要人工指定。
*/
#include
#include
//#include
//#include //模型系数头文件
//#include //投影滤波类头文件
#include //点云文件pcd 读写
#include // 球半径滤波器
#include //点云可视化// 别名
typedef pcl::PointCloud Cloud;
using namespace std;
int main (int argc, char** argv)
{// 定义 点云对象 指针Cloud::Ptr cloud_ptr(new Cloud());Cloud::Ptr cloud_filtered_ptr(new Cloud());// 产生点云数据 cloud_ptr->width &#61; 5;cloud_ptr->height &#61; 1;cloud_ptr->points.resize (cloud_ptr->width * cloud_ptr->height);for (size_t i &#61; 0; i points.size (); &#43;&#43;i){cloud_ptr->points[i].x &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);cloud_ptr->points[i].y &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);cloud_ptr->points[i].z &#61; 1024 * rand () / (RAND_MAX &#43; 1.0f);}std::cerr <<"Cloud before filtering半径滤波前: " <points.size (); &#43;&#43;i)std::cerr <<" " <points[i].x <<" " <points[i].y <<" " <points[i].z < Radius;// 建立滤波器Radius.setInputCloud(cloud_ptr);Radius.setRadiusSearch(1.2);//半径为 0.8&#xff4d;Radius.setMinNeighborsInRadius (2);//半径内最少需要 &#xff12;个点// 执行滤波Radius.filter (*cloud_filtered_ptr);// 输出滤波后的点云std::cerr <<"Cloud after filtering半径滤波后: " <points.size (); &#43;&#43;i)std::cerr <<" " <points[i].x <<" " <points[i].y <<" " <points[i].z <}



&#xff16;】统计滤波器 StatisticalOutlierRemoval


代码地址

/*
下载桌子点云数据
https://raw.github.com/PointCloudLibrary/data/master/tutorials/table_scene_lms400.pcd
统计滤波器 StatisticalOutlierRemoval
#include
统计滤波器用于去除明显离群点&#xff08;离群点往往由测量噪声引入&#xff09;。
其特征是在空间中分布稀疏&#xff0c;可以理解为&#xff1a;每个点都表达一定信息量&#xff0c;
某个区域点越密集则可能信息量越大。噪声信息属于无用信息&#xff0c;信息量较小。
所以离群点表达的信息可以忽略不计。考虑到离群点的特征&#xff0c;
则可以定义某处点云小于某个密度&#xff0c;既点云无效。计算每个点到其最近的k(设定)个点平均距离
。则点云中所有点的距离应构成高斯分布。给定均值与方差&#xff0c;可剔除&#xff4e;个西格玛之外的点
激光扫描通常会产生密度不均匀的点云数据集&#xff0c;另外测量中的误差也会产生稀疏的离群点&#xff0c;
此时&#xff0c;估计局部点云特征&#xff08;例如采样点处法向量或曲率变化率&#xff09;时运算复杂&#xff0c;
这会导致错误的数值&#xff0c;反过来就会导致点云配准等后期的处理失败。
解决办法&#xff1a;对每个点的邻域进行一个统计分析&#xff0c;并修剪掉一些不符合标准的点。
具体方法为在输入数据中对点到临近点的距离分布的计算&#xff0c;对每一个点&#xff0c;
计算它到所有临近点的平均距离&#xff08;假设得到的结果是一个高斯分布&#xff0c;
其形状是由均值和标准差决定&#xff09;&#xff0c;那么平均距离在标准范围之外的点&#xff0c;
可以被定义为离群点并从数据中去除。
*/
#include
#include
//#include
//#include //体素格滤波器VoxelGrid
#include //统计滤波器
#include //点云文件pcd 读写
#include //点云可视化using namespace std;
// 别名
typedef pcl::PointCloud Cloud;intmain (int argc, char** argv)
{// 定义 点云对象 指针Cloud::Ptr cloud_ptr (new Cloud);Cloud::Ptr cloud_filtered_ptr (new Cloud);//pcl::PointCloud::Ptr cloud_ptr (new pcl::PointCloud);//pcl::PointCloud::Ptr cloud_filtered_ptr (new pcl::PointCloud);// 读取点云文件 填充点云对象pcl::PCDReader reader;reader.read( "../table_scene_lms400.pcd", *cloud_ptr);if(cloud_ptr&#61;&#61;NULL) { cout <<"pcd file read err" <width * cloud_ptr->height<<" data points ( " < sta;//创建滤波器对象sta.setInputCloud (cloud_ptr); //设置待滤波的点云sta.setMeanK (50); //设置在进行统计时考虑查询点临近点数sta.setStddevMulThresh (1.0); //设置判断是否为离群点的阀值sta.filter (*cloud_filtered_ptr); //存储内点// 输出滤波后的点云信息std::cerr <<"Cloud after filtering: " < ("table_scene_lms400_outliers.pcd", *cloud_filtered_ptr, false);// 调用系统可视化命令行显示//system("pcl_viewer table_scene_lms400_inliers.pcd");// 程序可视化pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字viewer.showCloud(cloud_filtered_ptr);while (!viewer.wasStopped()){// Do nothing but wait.}return (0);
}





推荐阅读
author-avatar
小青年
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有