Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Metric to compare two point clouds similarity

What are some metrics or methods that are used widely to compare similarity of two point clouds objects ? ( Ex. It could be PCD file or PLY file).

I have searched in PCL library's document but not found. Googled it, found some research but they talk about new method not what is widely or already used.

Is there any basic method to compare similarity of point clouds ? Or even some function in PCL library that will do the job ?

like image 617
Chayanin Avatar asked Oct 27 '25 04:10

Chayanin


1 Answers

Here is my approach:

    #include <algorithm>
    #include <numeric>
    
    #include <pcl/point_cloud.h>
    #include <pcl/point_types.h>
    #include <pcl/common/geometry.h>
    #include <pcl/search/kdtree.h>
    
    template<typename TreeT, typename PointT>
    float nearestDistance(const TreeT& tree, const PointT& pt)
    {
      const int k = 1;
      std::vector<int> indices (k);
      std::vector<float> sqr_distances (k);
    
      tree.nearestKSearch(pt, k, indices, sqr_distances);
    
      return sqr_distances[0];
    }
    
    // compare cloudB to cloudA
    // use threshold for identifying outliers and not considering those for the similarity
    // a good value for threshold is 5 * <cloud_resolution>, e.g. 10cm for a cloud with 2cm resolution
    template<typename CloudT>
    float _similarity(const CloudT& cloudA, const CloudT& cloudB, float threshold)
    {
      // compare B to A
      int num_outlier = 0;
      pcl::search::KdTree<typename CloudT::PointType> tree;
      tree.setInputCloud(cloudA.makeShared());
      auto sum = std::accumulate(cloudB.begin(), cloudB.end(), 0.0f, [&](auto current_sum, const auto& pt) {
        const auto dist = nearestDistance(tree, pt);
    
        if(dist < threshold)
        {
          return current_sum + dist;
        }
        else
        {
          num_outlier++;
          return current_sum;
        }
      });
    
      return sum / (cloudB.size() - num_outlier);
    }
    
    // comparing the clouds each way, A->B, B->A and taking the average
    template<typename CloudT>
    float similarity(const CloudT& cloudA, const CloudT& cloudB, float threshold = std::numeric_limits<float>::max())
    {
      // compare B to A
      const auto similarityB2A = _similarity(cloudA, cloudB, threshold);
      // compare A to B
      const auto similarityA2B = _similarity(cloudB, cloudA, threshold);
    
      return (similarityA2B * 0.5f) + (similarityB2A * 0.5f);
    }

The idea is that you compare point cloud B to A by searching for the nearest distance to a neighbour for each point of B. By averaging the found distances (with exclusion of outliers), you can get a pretty good estimate of the similarity.

like image 185
kanstar Avatar answered Oct 30 '25 13:10

kanstar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!