1、半径滤波RadiusOutlierRemoval
1.1 所需头文件
#include <pcl/filters/radius_outlier_removal.h>
1.2 代码实现
/**
*某个点半径范围内搜索邻域的点集个数能否满足设置点个数,不满足就是离群点。
*/
void pcdROR(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
cout << "<-半径滤波->" << endl;
pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror; //创建统计滤波器对象
ror.setInputCloud(inputCloud); //设置待滤波点云
ror.setRadiusSearch(0.8); // 设置查询点的半径范围
ror.setMinNeighborsInRadius(30);// 设置判断是否为离群点的阈值,即半径内至少包括的点数
ror.setNegative(true);//默认false,保存内点;true,保存滤掉的离群点
ror.filter(*cloud_filtered); //执行滤波,保存滤波结果在cloud_filtered
cout << "\t\t<滤波后的点云信息>\n" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
}
1.3 输出结果
2、条件滤波
2.1 所需头文件
#include <pcl/filters/conditional_removal.h>
2.2 代码实现
/*
ConditionAnd: 所有条件都要满足
ConditionOr: 满足一个条件即可
GT:大于 GE:大于等于
LT:小于 LE:小于等于
EQ:等于
*/
void pcdCondRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
//创建条件限定下的滤波器
pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());//创建条件定义对象range_cond
//为条件定义对象添加比较算子
range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
pcl::FieldComparison<pcl::PointXYZ>("y", pcl::ComparisonOps::GT, -3.0)));//添加在x字段上大于 -.1 的比较算子
range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
pcl::FieldComparison<pcl::PointXYZ>("y", pcl::ComparisonOps::LT, 1.0)));//添加在x字段上小于 1.0 的比较算子
pcl::ConditionalRemoval<pcl::PointXYZ> cr; //创建滤波器对象
cr.setCondition(range_cond); //用条件定义对象初始化
cr.setInputCloud(inputCloud); //设置待滤波点云
cr.setKeepOrganized(true); //保持点云结构,即有序点云经过滤波后,仍能够保持有序性。(是否保留无效点云数据的位置信息)
cr.setUserFilterValue(5); //将过滤掉的点用(5,5,5)代替
cr.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
cout << "\t\t<滤波后的点云信息>\n" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
}
2.3 输出结果
3、索引提取ExtractIndices
3.1 所需头文件
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/filters/extract_indices.h>
3.2 代码实现
void pcdExtractIndices(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
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(1000); //设置最大迭代次数
seg.setDistanceThreshold(0.01); //设置判断是否为模型内点的距离阈值
seg.setInputCloud(inputCloud);
seg.segment(*inliers, *coefficients);//分割实现:存储分割结果到点集合inliers;存储平面模型系数coefficients
if (inliers->indices.size() == 0)
{
PCL_ERROR("不能从给定的点云数据集中提取出平面模型!\n");
}
pcl::ExtractIndices<pcl::PointXYZ> extract; //创建点云提取对象
extract.setInputCloud(inputCloud); //设置输入点云
extract.setIndices(inliers); //设置分割后的内点inliers为需要提取的点集
extract.setNegative(false); //设置提取内点而非外点,默认false
extract.filter(*cloud_filtered); //提取点集并存储到 cloud_filtered
cout << "平面点集点的个数为:" << cloud_filtered->points.size() << endl;
cout << "\t\t<滤波后的点云信息>\n" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
}
3.3 输出结果
4、ProjectInliers投影滤波
4.1 所需头文件
#include <pcl/filters/project_inliers.h>
4.2 代码实现
/*
* 将点投影到一个参数化模型上,这个参数化模型可以是平面、圆球、圆柱、锥形等进行投影滤波
*/
//定义球的结构体
struct Sphere
{
float center_x;
float center_y;
float center_z;
float radius;
};
void pcdProjectInliers(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients()); //创建分割时所需要的模型系数对象
//创建一个平面 平面方程ax+by+cz+d=0; c!=0
coefficients->values.resize(4); //设置模型系数的大小
coefficients->values[0] = 1.0; //x系数
coefficients->values[1] = 1.0; //y系数
coefficients->values[2] = 1.0; //z系数
coefficients->values[3] = 0.0; //d
//coefficients->values[0] = coefficients->values[1] = 0;
//coefficients->values[2] = 1.0;
//coefficients->values[3] = 0;
//投影滤波
pcl::ProjectInliers<pcl::PointXYZ> proj;//创建投影滤波器对象
proj.setModelType(pcl::SACMODEL_PLANE); //设置对象对应的投影模型
proj.setInputCloud(inputCloud); //设置输入点云
proj.setModelCoefficients(coefficients);//设置模型对应的系数
proj.filter(*cloud_filtered); //执行投影滤波,存储结果于cloud_projected
cout << "\t\t<滤波后的点云信息>\n" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
Sphere sp;
sp.center_x = -0.0267599;
sp.center_y = 0.0952158;
sp.center_z = 0.00894712;
sp.radius = 12;
---------------------------------投影到球面----------------------------------
//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>);
//cloud_projected->width = inputCloud->width;
//cloud_projected->height = inputCloud->height;
//cloud_projected->resize(inputCloud->size());
//cloud_projected->is_dense = false;
//for (size_t i = 0; i < inputCloud->points.size(); i++)
//{
// float d = sqrt(pow(inputCloud->points[i].x, 2) + pow(inputCloud->points[i].y, 2) + pow(inputCloud->points[i].z, 2));
// cloud_projected->points[i].x = inputCloud->points[i].x * sp.radius / d + sp.center_x;
// cloud_projected->points[i].y = inputCloud->points[i].y * sp.radius / d + sp.center_y;
// cloud_projected->points[i].z = inputCloud->points[i].z * sp.radius / d + sp.center_z;
//}
//viewPort2(inputCloud, cloud_projected);
}
4.3 输出结果
投影到平面
投影到球面
5、ModelOutlierRemoval 模型滤波器
5.1 所需头文件
#include <pcl/filters/model_outlier_removal.h>
5.2 代码实现
/*
* ModelOutlierRemoval基于模型和点之间的距离过滤云中的点。
* 迭代整个输入一次,自动过滤非有限点和setSampleConsensusModelPointer()指定的模型之外的点,以及setThreholdFunctionPointer()指定的阈值
*/
void pcdModelOutlierRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{
cout << "<-正在模型滤波->" << endl;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
//设置模型系数
pcl::ModelCoefficients model_coeff;
model_coeff.values.resize(4);
model_coeff.values[0] = 0.0;
model_coeff.values[1] = 0.0;
model_coeff.values[2] = 14.0;
model_coeff.values[3] = 0.0;
///模型滤波
pcl::ModelOutlierRemoval<pcl::PointXYZ> filter; //创建模型滤波器对象
filter.setModelCoefficients(model_coeff); //为模型对象添加模型系数
filter.setThreshold(14); //设置判断是否为模型内点的阈值
filter.setModelType(pcl::SACMODEL_PLANE); //设置模型类别
filter.setInputCloud(inputCloud); //输入待滤波点云
filter.setNegative(false); //默认false,提取模型内点;true,提取模型外点
filter.filter(*cloud_filtered); //执行模型滤波,保存滤波结果于cloud_filtered
cout << "\t\t<滤波后的点云信息>\n" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
}
5.3 输出结果
6、空间裁剪滤波 CropHull滤波器
6.1 所需头文件
#include <pcl/filters/crop_hull.h>
#include <pcl/surface/concave_hull.h>
6.2 代码实现
void pcdCropHull(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{
cout << "<----- CropHull滤波器 ----->" << endl;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //滤波后点云
pcl::PointCloud<pcl::PointXYZ>::Ptr boundingbox(new pcl::PointCloud<pcl::PointXYZ>); //封闭区域顶点
pcl::PointCloud<pcl::PointXYZ>::Ptr surface_hull(new pcl::PointCloud<pcl::PointXYZ>); //描述凸包形状的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr objects(new pcl::PointCloud<pcl::PointXYZ>); //提取的封闭区域内部点云
///设置封闭范围顶点
boundingbox->push_back(pcl::PointXYZ(0.4, 0.4, 0.3));
boundingbox->push_back(pcl::PointXYZ(0.8, -90, 45));
boundingbox->push_back(pcl::PointXYZ(-10, 0.3, 50));
boundingbox->push_back(pcl::PointXYZ(-0.5, 0.1, -1.1));
boundingbox->push_back(pcl::PointXYZ(6, 9, 0));
boundingbox->push_back(pcl::PointXYZ(0.1, -0.1, 0));
boundingbox->push_back(pcl::PointXYZ(-0.1, 0.1, 0));
boundingbox->push_back(pcl::PointXYZ(-9, -34, 67));
boundingbox->push_back(pcl::PointXYZ(15, 0.1, 88));
/*
* hull 和 ch 维度要一致
*/
///构造凸包
pcl::ConvexHull<pcl::PointXYZ> hull;//创建凸包对象
hull.setInputCloud(boundingbox); //设置输入点云:封闭区域顶点点云
hull.setDimension(2); //设置凸包维度
std::vector<pcl::Vertices> polygons;//设置Vertices类型的向量,用于保存凸包顶点
hull.reconstruct(*surface_hull, polygons);//计算凸包结果
///CropHull滤波
pcl::CropHull<pcl::PointXYZ> ch;//创建CropHull滤波对象
ch.setDim(2); //设置维度,与凸包维度一致
ch.setInputCloud(inputCloud); //设置需要滤波的点云
ch.setHullIndices(polygons); //输入封闭区域的顶点
ch.setHullCloud(surface_hull); //输入封闭区域的形状
ch.filter(*objects); //执行CropHull滤波,存储结果于objects
cout << "\t<滤波后的点云信息>\n" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
pcl::PCDWriter writer;
writer.write("polygons.pcd", *boundingbox, true);
cout << "\t<封闭区域顶点点云信息>\n" << *boundingbox << endl;
writer.write("surface_hull.pcd", *surface_hull, true);
cout << "\t<封闭形状点云信息>\n" << *surface_hull << endl;
writer.write("objects.pcd", *objects, true);
cout << "\t<提取的点云信息>\n" << *objects << endl;
viewPort2(inputCloud, objects);
6.3 输出结果