一、简介
RadiusOutlierRemoval滤波处理会滤除那些一定范围内没有足够多近邻的点;
ConditionalRemoval滤波器用于删除不符合用户要求的一个或多个数据点。
二、代码分析
1)首先,程序会确保用户输入正确的命令行参数,并随机生成一个点云数据:
if (argc != 2)
{
std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
exit(0);
}
// 填入点云数据
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 = 5;
cloud->height = 1;
cloud->points.resize(cloud->width*cloud->height);
//for (size_t i = 0; i < cloud->points.size(); ++i)
//{
// cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
// cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
// cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
//}
for (size_t i = 0; i < cloud->points.size(); ++i)
{
cloud->points[i].x = 2 * rand() / (RAND_MAX + 1.0f) - 0.5;
cloud->points[i].y = 2 * rand() / (RAND_MAX + 1.0f) - 0.5;
cloud->points[i].z = 1 * rand() / (RAND_MAX + 1.0f) - 0.5;
}
2)创建RadiusOutlierRemoval滤波器对象,设置其参数并将其应用到我们输入的点云数据,将搜索半径设为0.8,在此半径内的点必须要有一个近邻,才会保留这个点:
if (strcmp(argv[1], "-r") == 0){
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;// 创建滤波器
outrem.setInputCloud(cloud); //设置输入点云
//搜索半径设为0.8,在此半径内点必须要有至少1个邻居时,此点才会被保留
outrem.setRadiusSearch(0.8); //设置在0.8半径的范围内找邻近点
outrem.setMinNeighborsInRadius(1); //设置查询点的邻近点集数小于1的删除
outrem.filter(*cloud_filtered); //执行条件滤波,存储结果到cloud_filtered
}
3)创建 ConditionalRemoval滤波器,在z字段上大于0小于0.8的点云将被保留,其他点云数据将被删去:
else if (strcmp(argv[1], "-c") == 0){
//创建条件限定下的滤波器
pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>()); //创建条件定义对象
//为条件定义对象添加比较算子: 使用大于0.0和小于0.8这两个条件用于建立滤波器。
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); //设置保持点云的结构:为true时被剔除的点为NAN
condrem.filter(*cloud_filtered); //执行条件滤波,存储结果到cloud_filtered
}
4)显示滤波后的点云:
std::cerr << "Cloud before filtering: " << std::endl;
for (size_t i = 0; i < cloud->points.size (); ++i)
std::cerr << " " << cloud->points[i].x << " "
<< cloud->points[i].y << " "
<< cloud->points[i].z << std::endl;
// 显示滤波后的点云
std::cerr << "Cloud after filtering: " << std::endl;
for (size_t i = 0; 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;
5)整体代码:
#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 != 2)
{
std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
exit(0);
}
// 填入点云数据
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 = 5;
cloud->height = 1;
cloud->points.resize(cloud->width*cloud->height);
//for (size_t i = 0; i < cloud->points.size(); ++i)
//{
// cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
// cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
// cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
//}
for (size_t i = 0; i < cloud->points.size(); ++i)
{
cloud->points[i].x = 2 * rand() / (RAND_MAX + 1.0f) - 0.5;
cloud->points[i].y = 2 * rand() / (RAND_MAX + 1.0f) - 0.5;
cloud->points[i].z = 1 * rand() / (RAND_MAX + 1.0f) - 0.5;
}
if (strcmp(argv[1], "-r") == 0){
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;// 创建滤波器
outrem.setInputCloud(cloud); //设置输入点云
//搜索半径设为0.8,在此半径内点必须要有至少1个邻居时,此点才会被保留
outrem.setRadiusSearch(0.8); //设置在0.8半径的范围内找邻近点
outrem.setMinNeighborsInRadius(1); //设置查询点的邻近点集数小于1的删除
outrem.filter(*cloud_filtered); //执行条件滤波,存储结果到cloud_filtered
}
else if (strcmp(argv[1], "-c") == 0){
//创建条件限定下的滤波器
pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>()); //创建条件定义对象
//为条件定义对象添加比较算子: 使用大于0.0和小于0.8这两个条件用于建立滤波器。
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); //设置保持点云的结构:为true时被剔除的点为NAN
condrem.filter(*cloud_filtered); //执行条件滤波,存储结果到cloud_filtered
}
else{
std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
exit(0);
}
std::cerr << "Cloud before filtering: " << std::endl;
for (size_t i = 0; i < cloud->points.size (); ++i)
std::cerr << " " << cloud->points[i].x << " "
<< cloud->points[i].y << " "
<< cloud->points[i].z << std::endl;
// 显示滤波后的点云
std::cerr << "Cloud after filtering: " << std::endl;
for (size_t i = 0; 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 (0);
}
6)容易遇到的问题:
pcl::ConditionalRemoval<pcl::PointXYZ> condrem(range_cond);
使用上述代码时容易报错:找不到匹配的构造函数!改成以下代码即可解决:
pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
condrem.setCondition(range_cond);
三、编译结果