PCl point cloud filtering (1) straight-through filtering, voxel filtering, uniform sampling, statistical filtering

A visual function

void viewPort2(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud, pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered)
{<!-- -->
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Comparison before and after filtering"));

/*-----Viewport 1-----*/
int v1(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1); //Set the minimum and maximum values of the first viewport on the X-axis and Y-axis, with values between 0-1
viewer->setBackgroundColor(0, 0, 0, v1); //Set the background color, 0-1, default black (0, 0, 0)
viewer->addText("before_filtered", 10, 10, "v1_text", v1);
viewer->addPointCloud<pcl::PointXYZ>(inputCloud, "before_filtered_cloud", v1);

/*-----Viewport2-----*/
int v2(0);
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2);
viewer->setBackgroundColor(0.3, 0.3, 0.3, v2);
viewer->addText("after_filtered", 10, 10, "v2_text", v2);
viewer->addPointCloud<pcl::PointXYZ>(cloud_filtered, "after_filtered_cloud", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "befor_filtered_cloud", v1);
//Set the color of the point cloud to red
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "befor_filtered_cloud", v1);

viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "after_filtered_cloud", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "after_filtered_cloud", v2);
viewer->resetCamera();
viewer->spin();
while (!viewer->wasStopped())
{<!-- -->
viewer->spinOnce();
}
}

1. pcl::PassThrough filtering

1.1 Required header files

#include <pcl/filters/passthrough.h>

1.2 Code Implementation
Process: Read in point cloud->Create pass-through filter->Set filter field->Execute->Save and visualize

/*
* Connect the point cloud coordinate constraints of the X, Y, and Z axes of the point cloud to perform filtering. You can constrain only the Z axis, or the X, Y, and Z coordinate axes can be constrained together to achieve the point cloud filtering effect.
* Algorithm principle: Filter a specified dimension and remove points within (or outside) the user-specified field range.
*/
void pcdPassthrough(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{<!-- -->
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_z(new pcl::PointCloud<pcl::PointXYZ>); //Filtered point cloud
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_y(new pcl::PointCloud<pcl::PointXYZ>); //Filtered point cloud

cout << "<-Direct pass filtering in progress->" << endl;
pcl::PassThrough<pcl::PointXYZ> pt; // Create a pass filter object
pt.setInputCloud(inputCloud); //Set input point cloud
pt.setFilterFieldName("z"); //Set the field z required for filtering
pt.setFilterLimits(-3, 10); //Set the y field filter range
pt.setFilterLimitsNegative(true); //Default false, retain point clouds within the range; true, save point clouds outside the range
pt.filter(*cloud_filtered_z); //Perform filtering and save the filtered point cloud

pt.setFilterFieldName("y"); //Set the field y required for filtering
pt.setFilterLimits(-3, 10); //Set the y field filter range
pt.setFilterLimitsNegative(true); //Default false, retain point clouds within the range; true, save point clouds outside the range
pt.filter(*cloud_filtered_y); //Perform filtering and save the filtered point cloud

///Save the filtered point cloud
cout << "<-Saving point cloud->\\
";
if (cloud_filtered_z->empty() || cloud_filtered_y->empty())
{<!-- -->
PCL_ERROR("The saved point cloud is empty!\\
");
return ;
}
else
{<!-- -->
pcl::io::savePCDFileBinary("../pcdFile//z_cloud_filtered.pcd", *cloud_filtered_z);
cout << "\t\t<field z filtered point cloud information>\\
" << *cloud_filtered_z << endl;
pcl::io::savePCDFileBinary("../pcdFile//y_cloud_filtered.pcd", *cloud_filtered_y);
cout << "\t\t<field y filtered point cloud information>\\
" << *cloud_filtered_y << endl;
}
//================================ Comparison visualization before and after filtering============ ======================

pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Comparison before and after filtering"));

/*-----Viewport 1-----*/
int v1(0);
viewer->createViewPort(0.0, 0.0, 0.333, 1.0, v1); //Set the minimum and maximum values of the first viewport on the X-axis and Y-axis, with values between 0-1
viewer->setBackgroundColor(0, 0, 0, v1); //Set the background color, 0-1, default black (0, 0, 0)
viewer->addText("before_filtered", 10, 10, "v1_text", v1);
viewer->addPointCloud<pcl::PointXYZ>(inputCloud, "before_filtered_cloud", v1);

/*-----Viewport2-----*/
int v2(0);
viewer->createViewPort(0.3, 0.0, 0.666, 1.0, v2);
viewer->setBackgroundColor(0.3, 0.3, 0.3, v2);
viewer->addText("z_after_filtered", 10, 10, "v2_text", v2);
viewer->addPointCloud<pcl::PointXYZ>(cloud_filtered_z, "z_after_filtered_cloud", v2);


/*-----Viewport 3-----*/
int v3(0);
viewer->createViewPort(0.666, 0.0, 1.0, 1.0, v3);
viewer->setBackgroundColor(0.4, 0.3, 0.5, v3);
viewer->addText("y_after_filtered", 10, 10, "v3_text", v3);
viewer->addPointCloud<pcl::PointXYZ>(cloud_filtered_y, "y_after_filtered_cloud", v3);
/*-----Set related attributes-----*/
//Set the point size of the point cloud to 2 units. This will cause each point in the point cloud to appear as a larger point.
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "befor_filtered_cloud", v1);
//Set the color of the point cloud to red
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "befor_filtered_cloud", v1);

viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "z_after_filtered_cloud", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "z_after_filtered_cloud", v2);


viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "y_after_filtered_cloud", v3);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.21, 0.35, 0.15, "y_after_filtered_cloud", v3);
viewer->resetCamera();
viewer->spin();
while (!viewer->wasStopped())
{<!-- -->
viewer->spinOnce();
}
}

1.3 Output results:

2. Voxel filtering pcl::VoxelGrid

2.1 Required header files

#include <pcl/filters/voxel_grid.h>

2.2 Code Implementation

/*
*Create a three-dimensional voxel grid -> In each voxel (three-dimensional cube), find the center of gravity of all point clouds in the cube to represent the cube, so as to achieve the purpose of downsampling.
*/
void pcdVoxelGrid(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{<!-- -->
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //Filtered point cloud
cout << "<-Voxel downsampling->" << endl;
pcl::VoxelGrid<pcl::PointXYZ> vg; //Create filter object
vg.setInputCloud(inputCloud); //Set the point cloud to be filtered
vg.setLeafSize(0.5f, 0.6f, 0.6f); //Set voxel size
vg.filter(*cloud_filtered); //Perform filtering and save the filtering results in cloud_filtered

cout << "\t\t<Filtered point cloud information>\\
" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
}

2.3 Output results

3. Uniform Sampling

3.1 Required header files

#include <pcl/keypoints/uniform_sampling.h>

3.2 Code Implementation

/*
* Create a filtered sphere for the point cloud data, and then retain a point closest to the center of the voxel at each voxel to replace all points in the voxel.
*/
void pcdUniformSampling(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud)
{<!-- -->
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //Filtered point cloud
cout << "<-Uniform downsampling->" << endl;
pcl::UniformSampling<pcl::PointXYZ> us; //Create a uniform sampling filter object
us.setInputCloud(inputCloud); //Set the point cloud to be filtered
us.setRadiusSearch(3.0f); //Set the filter sphere radius
us.filter(*cloud_filtered); //Perform filtering and save the filtering results in cloud_filtered

cout << "\t\t<Filtered point cloud information>\\
" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;
viewPort2(inputCloud, cloud_filtered);
}

3.3 Output results

4. Statistical filtering

4.1 Required header files

#include <pcl/filters/statistical_outlier_removal.h>

4.2 Code Implementation

/*
Perform statistical analysis on the neighborhood of each point, and filter out some outlier points that do not meet the requirements based on the distance distribution characteristics from the point to all neighboring points.
Disadvantages:
The first is that when outliers are clustered in a small range, the algorithm takes more time to ensure the filtering effect; the second is that while filtering outliers, boundary points will be filtered.
*/
void pcdSOR(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud) {<!-- -->
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //Filtered point cloud
cout << "<-statistical filtering->" << endl;
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; //Create statistical filter object
sor.setInputCloud(inputCloud); //Set the point cloud to be filtered
sor.setMeanK(20); //Set the number of neighboring points of the query point
sor.setNegative(true);//default false, saves interior points; true, saves filtered outliers
sor.setStddevMulThresh(0.1);//Set the standard deviation multiplier to calculate the threshold for outliers
sor.filter(*cloud_filtered); //Perform filtering and save the filtering results in cloud_filtered

cout << "\t\t<Filtered point cloud information>\\
" << *cloud_filtered << endl;
cout << "inputCloud - cloud_filtered = " << inputCloud->width * inputCloud->height - cloud_filtered->width * cloud_filtered->height << endl;

viewPort2(inputCloud, cloud_filtered);
}

4.3 Output results

Main function

int main()
{<!-- -->
//Input point cloud source point cloud
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); //Filtered point cloud

///Read in point cloud
cout << "<-Reading point cloud->" << endl;
string cloudPath = "../pcdFile//001.pcd";
if (pcl::io::loadPCDFile(cloudPath, *cloud) < 0)
{<!-- -->
PCL_ERROR("Point cloud file does not exist!\\
");
system("pause");
return -1;
}
cout << "\t\t<Read point cloud information>\\
" << *cloud << endl;

//pcdVoxelGrid(cloud);
pcdSOR(cloud);
return 0;
}