Filtering#

Principle#

The act of filtering a cloud is to remove points based on certain criteria.
It is useful if you want to keep points in a given range, if you want to remove outliers …

Passthrough filter#

The passthrough filter create boundaries outside which the points are removed :

Passthrough filtering

Green points are the ones retained after filtering on Z axis#

The corresponding method is the following :

 1/**
 2 * @brief Filter points outside given box along said axis
 3 * @tparam PointT Should be a pcl::PointXYZxxx
 4 * @param cloud Input cloud
 5 * @param filt_cloud Output cloud
 6 * @param axis Axis on which it has to be filtered given ba Axis_t::Axis_e::x/y/z
 7 * @param lowlimit Axis min value
 8 * @param uplimit Axis max value
 9 * @param verbose If has to output debug on console
10*/
11template <typename PointT>
12void passthroughFilterCloud(typename pcl::PointCloud<PointT>::Ptr& cloud, typename pcl::PointCloud<PointT>::Ptr& filt_cloud, Axis_t axis, float lowlimit, float uplimit, bool verbose = 0);
We can choose on which axis the sampling is done with axis through Axis_t struct.
The limits are given with lowlimit and uplimit.

To use it, do as follow :

1passthroughFilterCloud<pcl::PointXYZ>(baseCloud, compCloud, Axis_t::Axis_e::z, 2, 4);

Radius outlier removal#

The radius outlier removal check the number of neighbors each point has in a sphere of given radius. If the point has not enough points close to it, it is considered as an outlier.

Statistical outlier

Radius outlier removal, red points have no neighbors in radius, blue have 1 and green has 2#

The corresponding method is the following :

 1/**
 2 * @brief Remove outliers that do not have k neighbors in given sphere radius
 3 * @tparam PointT Should be a pcl::PointXYZxxx
 4 * @param cloud Input cloud
 5 * @param filt_cloud Output cloud
 6 * @param radius Sphere radius to check neighbor in
 7 * @param minPointsInRadius K neighbors required not to be an outlier
 8 * @param verbose If has to output debug on console
 9*/
10template <typename PointT>
11void radiusOutlierRemoval(typename pcl::PointCloud<PointT>::Ptr& cloud, typename pcl::PointCloud<PointT>::Ptr& filt_cloud, float radius, unsigned int minPointsInRadius, bool verbose = 0);
We can set radius giving the radius of the sphere in which to check for neighbors presence.
minPointsInRadius gives minimal number of neighbors the point must have to be kept.

To use it, do as follow :

1radiusOutlierRemoval<pcl::PointXYZ>(mynewcloud, mynewcloud_filtered, 3, 10);

Statistical outlier removal#

If the cloud is noisy, it contains points that may not belong to the part. As it can be difficult to ensure the part is centered and its dimensions well known, a simple passtrhough filter may not be used.
The statistical outlier allow to remove points that are too distant from others based on following algorithm:
  1. For each point, compute mean distance from their k neigbors

  2. Do global mean

  3. Each point having their mean distance outside the interval [mean-stdDev:mean+stdDev] will be removed

The passthrough filter create boundaries outside which the points are removed.

Statistical outlier

Statistical removing of points, https://pcl.readthedocs.io/en/latest/statistical_outlier.html#

The corresponding method is the following :

 1/**
 2 * @brief Removes outliers based on statistics of whole cloud
 3 * @tparam PointT Should be a pcl::PointXYZxxx
 4 * @param cloud Input cloud
 5 * @param filt_cloud Output cloud
 6 * @param meanK Number of near neighbors to analyze
 7 * @param stdDevMultThresh All points who have a distance larger than stdDevMultThresh standard deviation of the mean distance to the query point will be removed
 8 * @param verbose If has to output debug on console
 9*/
10template <typename PointT>
11void statisticalOutlierRemoval(typename pcl::PointCloud<PointT>::Ptr& cloud, typename pcl::PointCloud<PointT>::Ptr& filt_cloud, unsigned int meanK, float stdDevMultThresh, bool verbose = 0);
We can set meanK, telling us on how many neighbors each point distance must be computed.
stdDevMultThresh gives the interval criterion to keep a point or not. It strongly depends on the resolution of the cloud.

To use it, do as follow :

1statisticalOutlierRemoval<pcl::PointXYZ>(mynewcloud, mynewcloud_filtered, 40, 1);

Conditional remover#

It is also possible to specify specific conditions and let a conditional remover run to determine if point has to be kept or not.

Euclidean clustering#

While filters may be used to isolate multiple parts in the same scan, it requires to know the position of the cloud, the approximate size of all parts.
If these variables are not known, an automatic clustering can be executed to isolate subclouds that have points close to each other.
If you have a ground, you may need to remove it first to avoid that the clustering process detects it as part of the different pieces you try to isolate.
The algorithm groups points that are close to each other into the same cluster.
Once clusters are formed, a low and high values tell the clustering process if the cluster is considered valid or not. It can be used to reject clusters with too few points (outliers that have not been removed for example) or too many.
Euclidian clustering

Blue and green parts are two different clusters#

The corresponding method is the following :

 1/**
 2 * @brief Extract clusters from given cloud based on density
 3 * @tparam PointT Should be a pcl::PointXYZxxx
 4 * @param cloud Cloud to extract clusters from
 5 * @param indices New vector to store indices of clusters
 6 * @param tolerance Tolerance in [m] to look points around
 7 * @param minpointsinclust Minimal points for a cluster to be considered
 8 * @param maxpointsinclust Maximal points for a cluster to be considered (if 0 -> no limit)
 9 * @param verbose If has to output debug on console
10*/
11template <typename PointT>
12void euclideanClustering(typename pcl::PointCloud<PointT>::Ptr& cloud, std::vector<pcl::PointIndices>& indices, float tolerance, unsigned int minpointsinclust = 50, unsigned int maxpointsinclust = 0, bool verbose = false);
The tolerance gives the distance from point to each other to group them. A too low value may create multiple clusters for the same part, while a too big value may merge the different parts together.
minpointsinclust and maxpointsinclust give the boundaries to validate a cluster. If a certain cluster contains too few/many points, it is not considered as valid and will points are clustered with other invalid points.

To use it, do as follow :

 1std::vector<pcl::PointIndices> cluster_indices;
 2euclideanClustering<pcl::PointXYZ>(mycloud, cluster_indices, 6, 50, 0);
 3// Different clusters are accessed with cluster_indices[n]
 4
 5// To recreate clouds from them :
 6std::vector<pcl::PointIndices> cluster_indices;
 7std::vector<pcl::PointCloud<pcl::PointXYZ>> clustered_clouds;
 8// Find clusters
 9euclideanClustering<pcl::PointXYZ>(mycloud, cluster_indices, 6, 50, 0);
10// Iterate throug clusters and create point clouds
11for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it)
12{
13    pcl::PointCloud<pcl::PointXYZ> cl;
14    for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); ++pit)
15    {
16        cl.push_back((*mycloud)[*pit]);
17    }
18    cl.width = cl.size();
19    cl.height = 1;
20    cl.is_dense = true;
21    clustered_clouds.push_back(cl);
22}

Plane model removing#

The passthrough filter removes planes from a cloud.

The corresponding method is the following :

/**
 * @brief Remove planes from given cloud based on density
 * @tparam PointT Should be a pcl::PointXYZxxx
 * @param cloud Cloud to segment
 * @param seg_cloud Output segmented cloud
 * @param thresh Distance threshold to segment inliers
 * @param verbose If has to output debug on console
*/
template <typename PointT>
void segmentPlanes(typename pcl::PointCloud<PointT>::Ptr &cloud, typename pcl::PointCloud<PointT>::Ptr &seg_cloud, float thresh, bool verbose = false);
We specify the distance threshold, which determines how close a point must be to the model in order to be considered an inlier.
To use it, do as follows :
1segmentPlanes<pcl::PointXYZ>(in_cloud, out_cloud, 0.01, false);

Conditional euclidean clustering#

It is also possible to have additional condition while clustering (color matching, smoothness …).

Algorithm 3D Algorithm PCL Point Cloud