Applying Data Point Filters

Overview

The following will go through the steps needed to write a simple program which configures a chain of data filters and applies this chain to a point cloud. For information on data filters, refer to the data point filters tutorial. The filtered point cloud is then saved to disk. The source code associated with this tutorial can be found in examples/demo_cmake/convert.cpp.

IMPORTANT: This tutorial makes use of YAML configuration files. If you did not install yaml-cpp before installing libpointmatcher, you must do so before following these instructions. Information on installing yaml-cpp can be found in the installation instructions for Ubuntu, Windows and Mac OS X.

Source Description

First, we include the libpointmatcher and standard library header files.

=== “C++” cpp     #include "pointmatcher/PointMatcher.h"     #include <cassert>     #include <iostream>     #include <fstream>    

Next, we enter the std and PointMatcherSupport namespace scopes and declare type aliases.

=== “C++” ```cpp using namespace std; using namespace PointMatcherSupport;

typedef PointMatcher<float> PM;
typedef PM::DataPoints DP;
```

The following function displays the usage message. This program can be run with three arguments. The first is the path to a yaml configuration file, the second a path to the input point cloud, and the third is a filename to be used to save the filtered point cloud. If the first argument is omitted, the input point cloud is copied to the output point cloud. The usage message will be displayed whenever the program is run with an incorrect number of arguments.

=== “C++” cpp     void usage(char *argv[])     {         cerr << "Usage " << argv[0] << " [CONFIG.yaml] INPUT.csv/.vtk OUTPUT.csv/.vtk" << endl;         cerr << endl << "Example:" << endl;         cerr << argv[0] << " ../examples/data/default-convert.yaml ../examples/data/cloud.00000.vtk /tmp/output.vtk" << endl << endl;     }    

Now entering inside the main function of the program: We create a logger to which warnings and errors are written.

=== “C++” cpp     setLogger(PM::get().LoggerRegistrar.create("FileLogger"));    

We then load the input point cloud into a new DataPoints object d.

=== “C++” cpp     DP d(DP::load(argv[argc-2]));    

Next, the number of arguments is checked, and we attempt to load the configuration file. If the configuration file could not be opened, an error message is printed and the program returns. If it is loaded successfully, a chain of data filters is created and represented in a DataPointsFilters object. The input point cloud is filtered by the chain using the DataPointsFilters::apply(DataPoints d) function.

=== “C++” ```cpp if (argc == 4) { ifstream ifs(argv[1]); if (!ifs.good()) { cerr << “Cannot open config file “ << argv[1] << endl; usage(argv); return 2; } PM::DataPointsFilters f(ifs); f.apply(d);

    }
```

Finally, the filtered point cloud is written to the location specified by the user and the program returns successfully.

=== “C++” ```cpp d.save(argv[argc-1]);

return 0;
```

Configuring the Data Filters Chain

An example configuration file can be found at examples/data/default-convert.yaml. A diagram of this chain is shown in Figure 1.

Figure 1: Default chain of data filters in default-convert.yaml

Default Configuration Chain

Bounding Box Filter

The first element is a bounding box filter. It is configured to reject points inside a 8m x 8m x 8m cube centered at the origin.

- BoundingBoxDataPointsFilter:
   xMin: -4.0
   xMax: 4.0
   yMin: -4.0
   yMax: 4.0
   zMin: -4.0
   zMax: 4.0
   removeInside: 1

Sampling Surface Normal Filter

A sampling surface normal filter can be used in an attempt to subsample points while maintaining the shape structure of objects in the point cloud. The point cloud is divided into boxes containing at most 10 points. Points along flat surfaces are contained in larger boxes and are sparsely sampled while points on more complex surfaces are densely sampled.

- SamplingSurfaceNormalDataPointsFilter:
    knn: 10

Observation Direction Filter

The points are annotated with an observation direction pointing to the sensor location with the observation direction filter.

- ObservationDirectionDataPointsFilter

Orient Normals Filter

The last filter is used to reorient normal vectors so that they point in the same direction. This filter uses the observation directions extracted by the previous filter.

- OrientNormalsDataPointsFilter

Where To Go From Here

For more information on building your own configurations, refer to the tutorial on building yaml configurations.