# [PCL self study: Feature8] introduction and use of ROPS (rotating projection statistics) feature recognition object (continuously updated)

Posted by wilzy1 on Sat, 12 Feb 2022 02:00:32 +0100

## 1, Introduction to the characteristic principle of ROPS (rotational projection statistics)

in this article, we continue to learn how to use the PCL:: ropestimate class to extract the features of points. The feature extraction method implemented in this class is written by Yulan Guo, ferdous sohel, Mohammed bennamon, min Lu and Jianwei wane in their article“ Rotational Projection Statistics for 3D Local Surface Description and Object Recognition ”Proposed in.
recognizing 3D objects in the presence of noise, grid resolution change, occlusion and clutter is a very challenging task. Yulan Guo et al. Proposed a new rotational projection statistical method (RoPS). It mainly includes three modules: local reference frame (LRF) definition, RoPS feature description and 3D target recognition. This method defines LRF by calculating the scattering matrix of all points on the local surface. RoPS feature descriptor is obtained by rotating the adjacent points of a feature point onto a two-dimensional plane and calculating a set of Statistics (including low-order central moment and entropy) of the distribution of projection points. Using the proposed LRF and RoPS descriptors, the author proposes a layered 3D object recognition algorithm. The performance of the proposed LRF, RoPS descriptor and target recognition algorithm has been strictly tested on many popular and public data sets. Compared with the existing technology, our proposed technology shows better performance. On Bologna, UWA, Queen and Ca Foscari Venezia data sets, the recognition rates based on RoPS algorithm are 100, 98.9, 95.4 and 96.0 respectively.
[PS: RoPs is based on local features. Compared with the methods based on global features such as deep learning Pointnet + +, RoPs is more robust when there is noise in the point cloud or when the grid resolution changes greatly]

Algorithm idea:
first, clip the local surface for a given point of interest. The local surface consists of points and triangles within a given radius. For a given local surface, the local reference coordinate system is calculated. LRF() is just a triple set of vectors. Comprehensive information about how to calculate these vectors can be found in [article] Found in. Importantly, using these vectors, we can achieve the invariance of point cloud rotation. To do this, simply translate the point of the local surface so that the point of interest becomes the origin, and then rotate the local surface so that the LRF vector is aligned with the Ox, Oy and Oz axes.

after completing the above operations, start feature extraction. For each axis Ox, Oy and Oz, perform the following steps, which we call the current axis.

1. The local surface rotates a given angle around the current axis.
2. Project the points on the rotating local surface onto the XY, XZ and YZ planes.
3. For each projection distribution matrix constructed, this matrix only shows how many points fall on each bin. The number of bin represents the matrix dimension and is the parameter of the algorithm. It supports the projection of point cloud on the inner surface of radius parameter.
4. Calculate the central moment of each distribution matrix: M11, M12, M21, M22, E, where E is Shannon entropy.
5. Then connect the calculated values to form sub features (each axis corresponds to a sub feature).

repeat the above steps for many times. The number of iterations depends on the number of rotations given. The sub characteristics of different axes are connected to form the final RoPS descriptor.

## 2, ROPS (rotational projection statistics) feature example code analysis

in the sample program, we will use the model in the Queen dataset. Of course, you can choose any other point cloud, but in order for the code to work, you will need to use a triangulation algorithm to obtain polygons. You can find the suggested model here:

Github
Point cloud model: RoPs_cloud.pcd

Point cloud index: rops_indices.txt

Triangulation model: RoPs_triangles.txt

Point cloud model website: https://github.com/PointCloudLibrary/pcl/tree/master/test

the next thing you need to do is create a file ROPS in the editor_ feature. CPP and copy the following code in it. My test here uses vs2017 + pcl1 8.1.

``` #include <pcl/features/rops_estimation.h>
#include <pcl/io/pcd_io.h>

int main (int argc, char** argv)
{
if (argc != 4)
return (-1);

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());
if (pcl::io::loadPCDFile (argv[1], *cloud) == -1)
return (-1);

pcl::PointIndicesPtr indices (new pcl::PointIndices);
std::ifstream indices_file;
indices_file.open (argv[2], std::ifstream::in);
for (std::string line; std::getline (indices_file, line);)
{
std::istringstream in (line);
unsigned int index = 0;
in >> index;
indices->indices.push_back (index - 1);
}
indices_file.close ();

std::vector <pcl::Vertices> triangles;
std::ifstream triangles_file;
triangles_file.open (argv[3], std::ifstream::in);
for (std::string line; std::getline (triangles_file, line);)
{
pcl::Vertices triangle;
std::istringstream in (line);
unsigned int vertex = 0;
in >> vertex;
triangle.vertices.push_back (vertex - 1);
in >> vertex;
triangle.vertices.push_back (vertex - 1);
in >> vertex;
triangle.vertices.push_back (vertex - 1);
triangles.push_back (triangle);
}

unsigned int number_of_partition_bins = 5;
unsigned int number_of_rotations = 3;

pcl::search::KdTree<pcl::PointXYZ>::Ptr search_method (new pcl::search::KdTree<pcl::PointXYZ>);
search_method->setInputCloud (cloud);

pcl::ROPSEstimation <pcl::PointXYZ, pcl::Histogram <135> > feature_estimator;
feature_estimator.setSearchMethod (search_method);
feature_estimator.setSearchSurface (cloud);
feature_estimator.setInputCloud (cloud);
feature_estimator.setIndices (indices);
feature_estimator.setTriangles (triangles);
feature_estimator.setNumberOfPartitionBins (number_of_partition_bins);
feature_estimator.setNumberOfRotations (number_of_rotations);

pcl::PointCloud<pcl::Histogram <135> >::Ptr histograms (new pcl::PointCloud <pcl::Histogram <135> > ());
feature_estimator.compute (*histograms);

return (0);
}
```

let's analyze what the above code does paragraph by paragraph (the previous part on how to read the point cloud will not be repeated).

``` pcl::PointIndicesPtr indices (new pcl::PointIndices);
std::ifstream indices_file;
indices_file.open (argv[2], std::ifstream::in);
for (std::string line; std::getline (indices_file, line);)
{
std::istringstream in (line);
unsigned int index = 0;
in >> index;
indices->indices.push_back (index - 1);
}
indices_file.close ();
```

this part of the code is loaded with the index of the point in the point cloud to calculate the RoPS feature. If you want to calculate a feature for each individual point, you can comment it out.

``` std::vector <pcl::Vertices> triangles;
std::ifstream triangles_file;
triangles_file.open (argv[3], std::ifstream::in);
for (std::string line; std::getline (triangles_file, line);)
{
pcl::Vertices triangle;
std::istringstream in (line);
unsigned int vertex = 0;
in >> vertex;
triangle.vertices.push_back (vertex - 1);
in >> vertex;
triangle.vertices.push_back (vertex - 1);
in >> vertex;
triangle.vertices.push_back (vertex - 1);
triangles.push_back (triangle);
}
```

the above code is the function of loading triangulation model. If you only have point clouds without triangulation model files, this step can be used Code for triangulation To replace them. Reference hyperlink.

```  float support_radius = 0.0285f;
unsigned int number_of_partition_bins = 5;
unsigned int number_of_rotations = 3;
```

the above code defines important algorithm parameters: the calculation radius supporting local surface features, the number of partition bins used to form the distribution matrix and the number of rotations. The last parameter affects the length of the descriptor.

```  pcl::search::KdTree<pcl::PointXYZ>::Ptr search_method (new pcl::search::KdTree<pcl::PointXYZ>);
search_method->setInputCloud (cloud);
```

set the point cloud search method of the algorithm as kdtree.

```  pcl::ROPSEstimation <pcl::PointXYZ, pcl::Histogram <135> > feature_estimator;
feature_estimator.setSearchMethod (search_method);
feature_estimator.setSearchSurface (cloud);
feature_estimator.setInputCloud (cloud);
feature_estimator.setIndices (indices);
feature_estimator.setTriangles (triangles);
feature_estimator.setNumberOfPartitionBins (number_of_partition_bins);
feature_estimator.setNumberOfRotations (number_of_rotations);
```

here is the instantiation code of PCL:: ropestimate class. Enter all parameters into the instanced object.

``` pcl::PointCloud<pcl::Histogram <135> >::Ptr histograms (new pcl::PointCloud <pcl::Histogram <135> > ());
feature_estimator.compute (*histograms);
```

then use the above code to start the calculation process.
The subsequent histogram can be output as required, which is similar to the previous point feature histogram.

[blogger profile]
rabbit from Stanford, male, master of mechanical engineering from Tianjin University. Since graduation, he has been engaged in optical three-dimensional imaging and point cloud processing. Since the three-dimensional processing library used in the work is the internal library of the company and does not have universal applicability, self-study the open source PCL library and its related mathematical knowledge for use. I would like to share the self-study process with you.