Spatial change detection of pcl unordered point cloud data

Posted by behrk2 on Thu, 20 Jan 2022 19:53:18 +0100

principle

Octree is a tree structure for managing sparse 3D data. Octree is used to detect the spatial change between multiple disordered point clouds, which may be in size. There are differences in resolution, density, and point order. By recursively comparing the tree structure of octree, the spatial changes represented by the differences in voxel composition generated by octree can be identified, and the differences in spatial composition among multiple point clouds can be detected in real time through octree's "double buffer" technology.

The detection of the spatial change of disordered point clouds is actually the difference detection of the front and rear point clouds under the octree structure. Therefore, we should first load an original point cloud and generate the first octree structure; Then cut the buffer, load the second point cloud and generate the second octree structure; Finally, for comparison, if some leaf nodes are on the second octree, but not on the first octree, then the points in these leaf nodes are considered to be the points with more spatial changes.

Code

=====================================================

#include <pcl/point_cloud.h>
#include <pcl/octree/octree.h>
#include <iostream>
#include <vector>
#include <ctime>

Included header file

=====================================================

    //It is used to create time random seeds and take random numbers
    srand ((unsigned int) time (NULL));

    //Declare A point cloud A pointer and allocate space
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloudA (new pcl::PointCloud<pcl::PointXYZ> );
    
    //Define the point cloud size, 128 point clouds, out of order
    cloudA->width =128;
    cloudA->height =1;
    cloudA->points.resize (cloudA->width *cloudA->height);
    //Circularly assign a value to the point cloud through the coordinates 0-64 of the random number point cloud
    for (size_t i=0; i<cloudA->points.size (); ++i)
    {
        cloudA->points[i].x =64.0f* rand () / (RAND_MAX +1.0f);
        cloudA->points[i].y =64.0f* rand () / (RAND_MAX +1.0f);
        cloudA->points[i].z =64.0f* rand () / (RAND_MAX +1.0f);
    }

Create a point cloud cloudA
The number is 128, and the coordinates 0-64 of x, y and z take random values

=====================================================

     /* Setting the resolution describes the size of the smallest voxel of the lowest level octree*/
    float resolution =32.0f;
    
    /* Build the class of octree change detection and set the resolution */
    pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ>octree (resolution);  

Build the class of octree change detection and set the resolution

=====================================================

    /* Point cloud of assignment octree */
    octree.setInputCloud (cloudA);//Set the imported point cloud
    octree.addPointsFromInputCloud ();//Add the imported point cloud to the octree

Input cloudA into octree, build its data structure and use it as base point cloud
Later, more points than its point cloud can be detected. However, you cannot detect points that are less than the second point cloud

=====================================================

   /*Swap the octree cache, but the octree corresponding to cloudA is still in memory*/ 
    octree.switchBuffers ();

Point cloud cloudA is a reference point cloud, and its octree object is used to describe its spatial distribution
OctreePointCloudChangeDetector inherits from the Octree2BufBase class, which allows two octrees to be saved and managed in memory at the same time
It applies the memory pool, reuses the allocated node objects, and reduces memory allocation and release operations
By visiting octree Switchbuffers () resets the cache of octree objects, but keeps the previous octree in the cache

=====================================================

    //Declare a point cloud B pointer and allocate space
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloudB (new pcl::PointCloud<pcl::PointXYZ> );
    
    //Define the point cloud size, 128 point clouds, out of order
    cloudB->width =128;
    cloudB->height =1;
    cloudB->points.resize (cloudB->width *cloudB->height);
    //Circularly assign a value to the point cloud through the coordinates 0-64 of the random number point cloud
    for (size_t i=0; i<cloudB->points.size (); ++i)
    {
        cloudB->points[i].x =90.0f* rand () / (RAND_MAX +1.0f);
        cloudB->points[i].y =90.0f* rand () / (RAND_MAX +1.0f);
        cloudB->points[i].z =90.0f* rand () / (RAND_MAX +1.0f);
    }

Declare a point cloud B pointer and allocate space
The number is 128, and the coordinates 0-90 of x, y and z take random values

The range is A little larger than A, which is easy to be effective

=====================================================

    /*Declare the index value save vector of point cloud with more B than A*/
    std::vector<int>newPointIdxVector;

    /* Get the index value that B is more than A. note that the index value that B is less than a will not be obtained  */
    octree.getPointIndicesFromNewVoxels (newPointIdxVector);

Get more index values of B than A through the function getpointindexfromnewvoxels

=====================================================

    // The terminal prints more point clouds from B than A
    std::cout<<"Output from getPointIndicesFromNewVoxels:"<<std::endl;
    for (size_t i=0; i<newPointIdxVector.size (); ++i)
    std::cout<<i<<"# Index:"<<newPointIdxVector[i]
    <<"  Point:"<<cloudB->points[newPointIdxVector[i]].x <<" "
    <<cloudB->points[newPointIdxVector[i]].y <<" "
    <<cloudB->points[newPointIdxVector[i]].z <<std::endl;

The terminal prints more point clouds from B than A

=====================================================

        //Declare a point cloud C pointer and allocate space
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloudC (new pcl::PointCloud<pcl::PointXYZ> );
    //Define the size of the point cloud and the number of point clouds. The number of B calculated above is more than A, which is out of order
    cloudC->width =newPointIdxVector.size ();
    cloudC->height =1;
    cloudC->points.resize (cloudC->width *cloudC->height);

    for(size_t i=0;i<newPointIdxVector.size ();++i)
    {
        cloudC->points[i]=cloudB->points[newPointIdxVector[i]];

    }

Create A new point cloud C to save more points from B than A

=====================================================

    //Visualization module
    pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewwe"));//Create pointer viewer
    viewer->initCameraParameters();//Initialize camera parameters

Add a visual module to display the point cloud

=====================================================

    int v1(0);//Parameters of the first window
    viewer->createViewPort(0.0,0.0,0.33,1,v1); //Sets the size of the first window, located on the left side of the screen
    viewer->setBackgroundColor(0,0,0,v1);//background of first port
    viewer->addText("cloudA",10,10,"cloudA",v1);//It's like a note
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color1(cloudA,255,0,0);//Sets the color of the first point cloud
    viewer->addPointCloud<pcl::PointXYZ>(cloudA,single_color1,"cloudA",v1);//Show first point cloud

Display point cloud A in red

=====================================================

    int v2(0);//Parameters of the first window
    viewer->createViewPort(0.33,0,0.66,1,v2);//Sets the size of the second window, located on the right side of the screen
    viewer->setBackgroundColor(0,0,0,v2);//background of second port
    viewer->addText("cloudB",10,9,"cloudB",v2);//Output a line of text
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color2(cloudB,0,255,0);//Sets the color of the second point cloud
    viewer->addPointCloud<pcl::PointXYZ>(cloudB,single_color2,"simple_cloud2",v2);//Displays the second point cloud

The second window Point Cloud B is displayed in green

=====================================================

    //Third point cloud window
    int v3(0);//Parameters of the third window
    viewer->createViewPort(0.66,0,1,1,v3);//Window size
    viewer->setBackgroundColor(0,0,0,v3);//background color 
    viewer->addText("cloud_result",10,8,"cloud_result",v3);//It's like a note
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color3(cloudC,255,255,255);//Point cloud color

    viewer->addPointCloud<pcl::PointXYZ>(cloudA,single_color1,"cloud1",v3);//Show point cloud
    viewer->addPointCloud<pcl::PointXYZ>(cloudB,single_color2,"cloud2",v3);//Show point cloud
    viewer->addPointCloud<pcl::PointXYZ>(cloudC,single_color3,"cloud3",v3);//Show point cloud
    viewer->addCoordinateSystem(2);//Add coordinate system
    viewer->spin();

The third window displays point clouds A, B, and C together. Let's see the overall effect

=====================================================

Result

The terminal prints more point clouds of B than A

Point cloud display

Point cloud A is on the left and point cloud B is in the middle

On the right is the combination of three point clouds;
The red ones are those that point cloud A has and point cloud B does not have; Green is shared by A and B; White is more B than A.

Topics: PCL