这个文档显示了在滤波模型里面如何使用几个不同的方法来消除点云里面的异常。
第一步我们将使用一个环境消除滤波器来消除不满足环境条件的点云。然后我们将学会如何使用一个RadiusOutlierRemoval滤波器来消除在指定范围内没有达到指定数量邻居的点。
代码
#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->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); } if (strcmp(argv[1], "-r") == 0){ pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem; // build the filter outrem.setInputCloud(cloud); outrem.setRadiusSearch(0.8); outrem.setMinNeighborsInRadius (2); // apply filter outrem.filter (*cloud_filtered); } else if (strcmp(argv[1], "-c") == 0){ // build the condition 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.0))); range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (new pcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::LT, 0.8))); // build the filter pcl::ConditionalRemoval<pcl::PointXYZ> condrem (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 (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; // display pointcloud after filtering 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); }
RadiusOutlierRemoval的背景
下面这个图片帮助我们可视化了RadiusOutlierRemoval滤波器所做的事情。用户指定了半径一定的一个圆圈。如果指定了圆圈中只有一个的,会被去除,那么黄色的点将被去除,如果指定了圆圈中只有2个点的被去除,那么绿色的将会被去除。
ConditionalRemoval背景
不满足环境的点将被除去
代码解释
下面的代码表示了运行该程序得输入2个参数,-r代表了运行RadiusOutlierRemoval这个滤波器,而-c代表了conditionRemoval这个滤波器
if (argc != 2) { std::cerr << "please specify command line arg '-r' or '-c'" << std::endl; exit(0); }
下面的代码,我们首先定义了PointCloud这个结构,然后把它填满
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 (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); }
如果我们选的参数是-r,就会执行下面这段代码
if (strcmp(argv[1], "-r") == 0){ pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem; // build the filter outrem.setInputCloud(cloud); outrem.setRadiusSearch(0.8); outrem.setMinNeighborsInRadius (2); // apply filter outrem.filter (*cloud_filtered); }
首先,我们先创建RadiusOutlierRemoval这个滤波器类,然后把它的参数进行设置,并把它应用到我们的输入点云中。搜索半径被设置为0.8,一个点要想被当做是这个点云里面的点,必须保证在0.8cm这个半径内还存在别的2个点,否则就会被去除。
对于ConditionalRemoval这个类,用户必须指定-c这个命令
else if (strcmp(argv[1], "-c") == 0){ // build the condition 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.0))); range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (new pcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::LT, 0.8))); // build the filter pcl::ConditionalRemoval<pcl::PointXYZ> condrem (range_cond); condrem.setInputCloud (cloud); condrem.setKeepOrganized(true); // apply filter condrem.filter (*cloud_filtered); }
首先,我们创建了一个点在点云里面的环境。在这个例子里面,我们将把2个比较加入到这个环境中,比0:(GT)大的或者比0.8(LT)小的这两个比较。
在两种情况下,上面的代码将会创建我们将要使用和设置相应的参数给滤波器类。
下面的代码输出了滤波前和滤波后的点云
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; // display pointcloud after filtering 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;
我们可以使用这个
./remove_outliers -c
或者这个
./remove_outliers -r
下面是结果
Cloud before filtering: 0.352222 -0.151883 -0.106395 -0.397406 -0.473106 0.292602 -0.731898 0.667105 0.441304 -0.734766 0.854581 -0.0361733 -0.4607 -0.277468 -0.916762 Cloud after filtering: -0.397406 -0.473106 0.292602 -0.731898 0.667105 0.441304