文章目录
0. 引言
本文主要记录PCL
点云库的过滤器模块Filtering
的几个例子。
├── data
│ └── table_scene_lms400.pcd
├── ExtractIndices
│ ├── CMakeLists.txt
│ └── extract_indices.cpp
├── PassThrough
│ ├── CMakeLists.txt
│ └── passthrough.cpp
├── ProjectInliers
│ ├── CMakeLists.txt
│ └── project_inliers.cpp
├── RemoveOutliers
│ ├── CMakeLists.txt
│ └── remove_outliers.cpp
├── StatisticalRemoval
│ ├── CMakeLists.txt
│ └── statistical_removal.cpp
└── VoxelGrid
├── CMakeLists.txt
└── voxel_grid.cpp
1. 使用 PassThrough 过滤器过滤点云
这一小节主要目的是:如何沿指定维度执行简单的过滤,即截断给定用户范围内部或外部的值。
1.1 实现代码
工程文件夹名为PassThrough
passthrough.cpp
代码如下:
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
int main(){
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 (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;
}
// 创建过滤器对象
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName("z");
pass.setFilterLimits(0.0, 1.0);
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);
}
1.2 CMakeLists.txt文件
CMakeLists.txt
如下:
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(PassThrough)
find_package(PCL 1.8.1 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (PassThrough passthrough.cpp)
target_link_libraries (PassThrough ${PCL_LIBRARIES})
1.3 运行结果
编译执行结果如下:
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
2. 使用 VoxelGrid 过滤器对点云进行下采样
2.1 实现代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
int main(){
pcl::PCLPointCloud2::Ptr cloud (new pcl::PCLPointCloud2());
pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2());
pcl::PCDReader reader;
reader.read("../../data/table_scene_lms400.pcd", *cloud);
std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height
<< " data points(" << pcl::getFieldsList(*cloud) << ")." << std::endl;
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud(cloud);
sor.setLeafSize(0.01f, 0.01f, 0.01f);
sor.filter(*cloud_filtered);
std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height
<< " data points (" << pcl::getFieldsList(*cloud_filtered) << ")." << std::endl;
pcl::PCDWriter writer;
writer.write ("../../data/table_scene_lms400_downsampled.pcd", *cloud_filtered,
Eigen::Vector4f::Zero(), Eigen::Quaternionf::Identity(), false);
return (0);
}
2.2 CMakeLists.txt文件
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(VoxelGrid)
find_package(PCL 1.8 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINTIONS})
add_executable(VoxelGrid voxel_grid.cpp)
target_link_libraries(VoxelGrid ${PCL_LIBRARIES})
2.3 运行结果
3. 使用 StatisticalOutlierRemoval 过滤器删除异常值
3.1 实现代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
int main(){
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCDReader reader;
reader.read<pcl::PointXYZ> ("../../data/table_scene_lms400.pcd", *cloud);
std::cerr << "Cloud before filtering: " << std::endl;
std::cerr << *cloud << std::endl;
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
sor.setInputCloud(cloud);
sor.setMeanK(50);
sor.setStddevMulThresh(1.0);
sor.filter(*cloud_filtered);
std::cerr << "Cloud after filtering: " << std::endl;
std::cerr << *cloud_filtered << std::endl;
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("../../data/table_scene_lms400_inliers.pcd", *cloud_filtered, false);
sor.setNegative(true);
sor.filter(*cloud_filtered);
writer.write<pcl::PointXYZ> ("../../data/table_scene_lms400_outliers.pcd", *cloud_filtered, false);
return (0);
}
3.2 CMakeLists.txt文件
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(StatisticalRemoval)
find_package(PCL 1.8 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINTIONS})
add_executable(StatisticalRemoval statistical_removal.cpp)
target_link_libraries(StatisticalRemoval ${PCL_LIBRARIES})
3.3 运行结果
4. 使用参数模型投影点
4.1 实现代码
#include <iostream>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/filters/project_inliers.h>
int main(){
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projectd (new pcl::PointCloud<pcl::PointXYZ>);
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 projection: " << std::endl;
for (const auto& point: *cloud){
std::cerr << " " << point.x << " "
<< point.y << " "
<< point.z << std::endl;
}
pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients());
coefficients->values.resize(4);
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 (cloud);
proj.setModelCoefficients (coefficients);
proj.filter (*cloud_projectd);
std::cerr << "Cloud after projection: " << std::endl;
for (const auto& point: *cloud_projectd){
std::cerr << " " << point.x << " "
<< point.y << " "
<< point.z << std::endl;
}
return (0);
}
4.2 CMakeLists.txt文件
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(ProjectInliers)
find_package(PCL 1.8 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINTIONS})
add_executable(ProjectInliers project_inliers.cpp)
target_link_libraries(ProjectInliers ${PCL_LIBRARIES})
4.3 运行结果
5. 从点云中提取索引
5.1 实现代码
#include <iostream>
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/extract_indices.h>
int main(){
pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filterd_blob (new pcl::PCLPointCloud2);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), cloud_p (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCDReader reader;
reader.read ("../../data/table_scene_lms400.pcd", *cloud_blob);
std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl;
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud (cloud_blob);
sor.setLeafSize (0.01f, 0.01f, 0.01f);
sor.filter (*cloud_filterd_blob);
pcl::fromPCLPointCloud2 (*cloud_filterd_blob, *cloud_filtered);
std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients());
pcl::PointIndices::Ptr inliers (new pcl::PointIndices());
pcl::SACSegmentation<pcl::PointXYZ> seg;
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setMaxIterations (1000);
seg.setDistanceThreshold (0.01);
pcl::ExtractIndices<pcl::PointXYZ> extract;
int i = 0, nr_points = (int) cloud_filtered->size();
while (cloud_filtered->size() == 0){
seg.setInputCloud (cloud_filtered);
seg.segment (*inliers, *coefficients);
if (inliers->indices.size() == 0){
std::cerr << "Could not estimate a planar model for the given dataset. " << std::endl;
break;
}
extract.setInputCloud (cloud_filtered);
extract.setIndices (inliers);
extract.setNegative (false);
extract.filter (*cloud_p);
std::cerr << "PointCloud reqresenting the planar component: " << cloud_p->width * cloud_p->height << " data points. " << std::endl;
std::stringstream ss;
ss << "table_scene_lms400_plane_" << i << ".pcd";
writer.write<pcl::PointXYZ> (ss.str(), *cloud_p, false);
extract.setNegative (true);
extract.filter (*cloud_f);
cloud_filtered.swap (cloud_f);
i++;
}
return (0);
}
5.2 CMakeLists.txt文件
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(ExtractIndices)
find_package(PCL 1.8 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINTIONS})
add_executable(ExtractIndices extract_indices.cpp)
target_link_libraries(ExtractIndices ${PCL_LIBRARIES})
5.3 运行结果
6. 使用条件或半径异常值删除来删除异常值
6.1 实现代码
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h>
int main(){
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->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);
}
if (strcmp(argc[1], "-r") == 0){
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
outrem.setInputCloud(cloud);
outrem.setRadiusSearch(0.8);
outrem.setMinNeighborsInRadius (2);
outrem.setKeepOrganized(true);
outrem.filter (*cloud_filtered);
}
else if (strcmp(argv[1], "-c") == 0){
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)));
pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
condrem.setCondition (range_cond);
codnrem.setInputCloud (cloud);
condrem.setKeepOrganized(true);
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;
}
return (0);
}
6.2 CMakeLists.txt文件
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(RemoveOutliers)
find_package(PCL 1.8 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINITIONS})
add_executable(RemoveOutliers remove_outliers.cpp)
target_link_libraries(RemoveOutliers ${PCL_LIBRARY_DIRS})
6.3 运行结果
Reference:
⭐️👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍🌔