1. StatisticalOutlierRemoval Filter
对点云中的每个点进行统计分析
//微微修改一下官方文档的code,大体如下
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
int main (int argc, char* argv[])
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
//load pcd file from the path
//需要你在命令行输入文件所在路径,如 ../data/table.pcd
pcl::PCDReader reader;
reader.read<pcl::PointXYZ> (argv[1], *cloud);
std::cout<<"original cloud data: "<<cloud->points.size()<<"points"<<std::endl;
std::cerr << "Cloud before filtering: " << std::endl;
//std::cerr << *cloud << std::endl;
// Create the filtering object
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
// 设置输入
sor.setInputCloud (cloud);
// 设置用于平均距离估计的 KD-tree最近邻搜索点的个数.
sor.setMeanK (50);
// 高斯分布标准差的倍数, 也就是 u+1*sigma,u+2*sigma,u+3*sigma 中的 倍数1、2、3
sor.setStddevMulThresh (1.0);
// 滤波后输出
sor.filter (*cloud_filtered);
std::cerr << "Cloud after filtering: " << std::endl;
std::cerr << *cloud_filtered << std::endl;
//save the inliers into ASCII PCD file
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("lms400_inliers.pcd", *cloud_filtered, false);
//save the filtered result into ASCII pcd file 保存过滤后的结果
sor.setNegative (true);
sor.filter (*cloud_filtered);
writer.write<pcl::PointXYZ> ("lms400_outliers.pcd", *cloud_filtered, false);
return (0);
}
2. RadiusOutlier removal / 3. Conditional removal
半径移除外点算法,就是设定一个搜索半径,判断目标点在设定半径范围内的相邻点数目,如下所示。
如果设定半径后,设定阀值范围为 1,那么只有黄色目标点被删除,如果设定阀值范围是 2,那么黄色和绿色范围点都会被删除
#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>);
// Fill in the cloud data
cloud->width = 5;
cloud->height = 1;
cloud->resize (cloud->width * cloud->height);
for (auto& point: *cloud)
{
point.x = 1024 * rand () / (RAND_MAX + 1.0f);
point.y = 1024 * rand () / (RAND_MAX + 1.0f);
point.z = 1024 * rand () / (RAND_MAX + 1.0f);
}
// RadiusOutlier-Removal
if (strcmp(argv[1], "-r") == 0)
{
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
// build the filter
outrem.setInputCloud(cloud);
outrem.setRadiusSearch(0.8);
outrem.setMinNeighborsInRadius (1);
outrem.setKeepOrganized(true);
// apply filter
outrem.filter (*cloud_filtered);
}
// Conditional-Removal
else if (strcmp(argv[1], "-c") == 0)
{
// build the condition
// 构建一个 ‘与’ 操作的环境,只有当目标点满足所有条件才被认为是 inlier
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.5)));
range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (new
pcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::LT, 1)));
//上面这两个条件规定了 z 坐标的范围,0.5 < z < 1;
// build the filter
pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
condrem.setCondition (range_cond);
condrem.setInputCloud (cloud);
condrem.setKeepOrganized(true);
// apply filter
condrem.filter (*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 (const auto& point: *cloud)
std::cerr << " " << point.x << " "
<< point.y << " "
<< point.z << std::endl;
// display pointcloud after filtering
std::cerr << "Cloud after filtering: " << std::endl;
for (const auto& point: *cloud_filtered)
std::cerr << " " << point.x << " "
<< point.y << " "
<< point.z << std::endl;
return (0);
}
3. Conditional removal
涉及到的几个关键函数和类:
1. void pcl::ConditionBase< PointT >:: addComparison (ComparisonBaseConstPtr comparison) 增加一个新的比较对象
Parameters
comparison: the comparison operator to add
References pcl::ComparisonBase< PointT >::capable_.
2. pcl::FieldComparison< PointT >::FieldComparison ( std::string field_name,ComparisonOps::CompareOp op,double compare_val ) 规定具体条件
Parameters
field_name: the name of the field that contains the data we want to compare
op: the operator to use when making the comparison
compare_val: the constant value to compare the field value too
References pcl::ComparisonBase< PointT >::capable_, pcl::ComparisonBase< PointT >::field_name_, pcl::getFields(), pcl::ComparisonBase< PointT >::op_, and pcl::FieldComparison< PointT >::point_data_.
3. pcl::ComparisonOps::GT/LT {LT, GT, LE, GE, EQ}
Parameters
LT:less than 小于
GT:greater than 大于
LE:less than or equal to 小于等于
GE:greater than or equal to 大于等于
EQ:equal to 等于
4. pcl::ConditionAnd
‘ 与 ’ 比较,必须满足所有条件才被认为是 inliers
pcl::ConditionOr
‘ 或 ’ 比较, 满足所有条件中的一个就可以认为是 inliers
4. passthrough
直通滤波( passthrough filter)操作相对粗暴,针对你定义的点的类型,对 X、Y、Z、R、G、B…等等各纬度进行内外点的界定
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
int
main (int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
// Fill in the cloud data
cloud->width = 5;
cloud->height = 1;
cloud->points.resize (cloud->width * cloud->height);
for (auto& point: *cloud)
{
point.x = 1024 * rand () / (RAND_MAX + 1.0f);
point.y = 1024 * rand () / (RAND_MAX + 1.0f);
point.z = 1024 * rand () / (RAND_MAX + 1.0f);
}
std::cerr << "Cloud before filtering: " << std::endl;
for (const auto& point: *cloud)
std::cerr << " " << point.x << " "
<< point.y << " "
<< point.z << std::endl;
// Create the filtering object
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud (cloud);
//规定了 x 的取值范围
pass.setFilterFieldName ("x");
pass.setFilterLimits (0.0, 1.0);
//规定了 z 的取值范围
pass.setFilterFieldName ("z");
pass.setFilterLimits (0.0, 1.0);
//这里也可以对颜色(RGB)进行滤波
//pass.setFilterLimitsNegative (true);
pass.filter (*cloud_filtered);
std::cerr << "Cloud after filtering: " << std::endl;
for (const auto& point: *cloud_filtered)
std::cerr << " " << point.x << " "
<< point.y << " "
<< point.z << std::endl;
return (0);
}