各种滤波方法类对点云滤波的整体流程:
使用对应滤波器方法类设置滤波器对象------将待滤波的点云添加到滤波器对象------根据相应滤波的的特性设置滤波器的各个参数------设置滤波条件------采用滤波方法滤波,将滤波后的点云输出。
例子:直通滤波器对点云滤波
1,创建pass滤波器对象; pcl::PassThrough<pcl::PointXYZ> pass(true/false);
首先创建passthrough滤波器对象,如果后续过程依然要使用被滤除点,我们必须保存被滤除点的索引以供后续使用,那么创建滤波器对象时,必须设置为true,默认构造函数创建滤波器对象时默认参数是false,不保存被滤除点的索引。
2,添加滤波对象两种方式,
一是添加指向点云的指针;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudnew(pcl::PointCloud<pcl::PointXYZ>)
pass.setInputCloud(cloud);
二是添加指向点云索引的指针;
pcl::IndicesConstPtr my_indicies;
pass.setIndicies(my_indicies);
三是设置滤波器的各种参数;
pass.setFilterFieldName(const std::string):设置在那个属性字段上做滤波处理;
pass.setFilterLimits(double a,double b):设置滤波的区间限制;
pass.setFilterLimitsNegative(bool):设置滤除区间内的点还是区间外的点;
pass.filter(*pointcloud_ptr):滤波后的点云的输出;
程序如下:
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include<pcl/visualization/pcl_visualizer.h>
#include<pcl/common/common_headers.h>
int main(int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudIn(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOut1(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOut2(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOut3(new pcl::PointCloud<pcl::PointXYZ>);
//创建一个圆柱类型点云,半径radius=1,z=[-1,1]
pcl::PointXYZ point;
for (float z = -1; z <= 1; z += 0.05)
{
for (double angle = 0; angle <= 360.0; angle += 5.0)
{
point.x = cos(pcl::deg2rad(angle));
point.y = sin(pcl::deg2rad(angle));
point.z = z;
cloudIn->points.push_back(point);
}
}
// 创建直通滤波器对象
pcl::PassThrough<pcl::PointXYZ> pass(true); //设置为true,要保留被滤除点的索引;
pass.setInputCloud(cloudIn);
//首先沿着x字段滤波
pass.setFilterFieldName("x");
pass.setFilterLimits(0.0, 1.0); //滤波区间x[0,1]
pass.setFilterLimitsNegative (false); //false:要滤除[0,1]外部的点
pass.filter(*cloudOut1);
/* cout << pass.getFilterFieldName() << endl;
float a, b;
pass.getFilterLimits(a, b);
cout << "a=" << a << "," << "b=" << b << endl;
cout << pass.getNegative() << endl;*/
pcl::IndicesConstPtr removedIndicies1;
removedIndicies1 = pass.getRemovedIndices();
pass.setIndices(removedIndicies1);
pass.setFilterFieldName("z");
pass.setFilterLimits(0.0, 1.0);
pass.setFilterLimitsNegative(true); //true:要滤除在z[0,1]区间内的点
pass.filter(*cloudOut2);
pcl::IndicesConstPtr removedIndicies2;
removedIndicies2 = pass.getRemovedIndices();
pass.setIndices(removedIndicies2);
pass.setFilterFieldName("y");
pass.setFilterLimits(0.0, 1.0);
pass.setFilterLimitsNegative(true); //true:要滤除在y[0,1]区间内的点
pass.filter(*cloudOut3);
//创建可视窗口
pcl::visualization::PCLVisualizer viewer("3D viewer");
int v1(0);
viewer.createViewPort(0, 0, 0.5, 0.5, v1);
viewer.setBackgroundColor(0, 0, 0, v1);
viewer.addPointCloud(cloudIn, "cloud1", v1);
viewer.addCoordinateSystem(0.5, "coordinatysystem1", v1);
viewer.addText("v1", 10, 10, "text1", v1);
int v2(0);
viewer.createViewPort(0.5, 0, 1, 0.5, v2);
viewer.setBackgroundColor(0, 0, 0, v2);
viewer.addPointCloud(cloudOut1, "cloud2", v2);
viewer.addCoordinateSystem( 0.5,"coordinatysystem2", v2);
viewer.addText("v2", 10, 10, "text2", v2);
int v3(0);
viewer.createViewPort(0, 0.5, 0.5, 1, v3);
viewer.setBackgroundColor(0, 0, 0, v3);
viewer.addPointCloud(cloudOut2, "cloud3", v3);
viewer.addCoordinateSystem(0.5, "coordinatysystem3", v3);
viewer.addText("v3", 10, 10, "text3", v3);
int v4(0);
viewer.createViewPort(0.5, 0.5, 1, 1, v4);
viewer.setBackgroundColor(0, 0, 0, v4);
viewer.addPointCloud(cloudOut3, "cloud4", v4);
viewer.addCoordinateSystem(0.5, "coordinatysystem4", v4);
viewer.addText("v4", 10, 10, "text4", v4);
while (!viewer.wasStopped())
{
viewer.spinOnce(100);
}
return (0);
}
结果如下图所示:可知:
1,pcl库中可视窗口的坐标原点在左下角;
2,v2视口为v1视口原始点云沿着x字段滤波得到的[0,1]区间内的点云;
3,v3视口为v1原始点云经过第一次滤波被滤除点云沿着z方向滤波,得到区间[-1,0]的点云;
4,v4视口为第二次滤波被滤除的点云在y方向的滤波,可知,对于一个滤波器对象pass连续使用发法getRemoveIndices()返回的仅仅是上一次滤波被滤除点云的索引值,上上一次滤波被滤除的点云的索引就被覆盖点不存在了。
来自源码:
passthrough.h头文件
namespace pcl
{
......
1, 默认构造函数,如果要保存被滤除点云的索引,应设置为true,默认是不保存false.
PassThrough (bool extract_removed_indices = false) :
FilterIndices<PointT> (extract_removed_indices),
filter_field_name_ (""),
filter_limit_min_ (FLT_MIN),
filter_limit_max_ (FLT_MAX)
{
filter_name_ = "PassThrough";
}
2,设置滤波字段,获取滤波字段。
inline void
setFilterFieldName (const std::string &field_name)
{
filter_field_name_ = field_name;
}
inline std::string const
getFilterFieldName () const
{
return (filter_field_name_);
}
3,设置滤波区间范围,获取滤波区间范围
inline void
setFilterLimits (const float &limit_min, const float &limit_max)
{
filter_limit_min_ = limit_min;
filter_limit_max_ = limit_max;
}
inline void
getFilterLimits (float &limit_min, float &limit_max) const
{
limit_min = filter_limit_min_;
limit_max = filter_limit_max_;
}
4,设置滤除区间内的点还是区间外的点,true:滤除区间内的点,false:滤除区间外的点。获取该设置参数,该函数可以使用getNegative()函数代替使用。
PCL_DEPRECATED(1, 13, "use inherited FilterIndices::setNegative() instead")
inline void
setFilterLimitsNegative (const bool limit_negative)
{
negative_ = limit_negative;
}
PCL_DEPRECATED(1, 13, "use inherited FilterIndices::getNegative() instead")
inline void
getFilterLimitsNegative (bool &limit_negative) const
{
limit_negative = negative_;
}
......
}
filter.h头文件
namespace pcl
{
class Filter
{
inline void
getRemovedIndices (PointIndices &pi)
{
pi.indices = *removed_indices_;
}
}
}
pcl_base.hpp文件
template <typename PointT> void
pcl::PCLBase<PointT>::setIndices (const IndicesConstPtr &indices)
{
indices_.reset (new Indices (*indices));
fake_indices_ = false;
use_indices_ = true;
}
///
template <typename PointT> void
pcl::PCLBase<PointT>::setIndices (const PointIndicesConstPtr &indices)
{
indices_.reset (new Indices (indices->indices));
fake_indices_ = false;
use_indices_ = true;
}