3

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 ?

Chayanin
  • 281
  • 1
  • 5
  • 11

2 Answers2

6

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.

LoW
  • 582
  • 7
  • 15
serkan.tuerker
  • 1,681
  • 10
  • 20
  • I think MSE makes sense, as it is also the way PCL alignment modules calculate "Fitness". If you look at setEuclideanFitnessEpsilon (http://docs.pointclouds.org/1.8.0/classpcl_1_1_registration.html): "The error is estimated as the sum of the differences between correspondences in an Euclidean sense, divided by the number of correspondences." – Mark Loyman May 01 '19 at 05:59
0

Unfortunately, I don't think it ever got officially documented, but PCL has a command line application to report the Hausdorff distance between two clouds. Try running pcl_compute_hausdorff. It's also available in the PDAL library (https://pdal.io/apps/hausdorff.html), where you would instead run pdal hausdorff.

Another common one is Chamfer distance (as described in https://arxiv.org/abs/1612.00603), though I'm not immediately aware of an implementation.

chambbj
  • 168
  • 1
  • 1
  • 5
  • 1
    Hausdorff - I'd advice against it, as it is too sensitive to outliers. Chamfer - I'd advice against it, as it is too sensitive to the size of the clouds. – Mark Loyman May 01 '19 at 05:38