比较两个点云相似度的度量
Metric to compare two point clouds similarity
有哪些指标或方法广泛用于比较两个点云对象的相似性? (例如,它可以是 PCD 文件或 PLY 文件)。
我在 PCL 图书馆的文档中搜索过,但没有找到。用谷歌搜索,找到了一些研究,但他们谈论的是新方法,而不是广泛使用或已经使用的方法。
有什么比较点云相似度的基本方法吗?或者甚至 PCL 库中的某些函数可以完成这项工作?
不幸的是,我认为它没有正式记录,但 PCL 有一个命令行应用程序来报告 Hausdorff distance between two clouds. Try running pcl_compute_hausdorff
. It's also available in the PDAL library (https://pdal.io/apps/hausdorff.html),而你会 运行 pdal hausdorff
.
另一个常见的是倒角距离(如 https://arxiv.org/abs/1612.00603 中所述),尽管我没有立即意识到实现。
这是我的方法:
#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);
}
这个想法是通过搜索 B 的每个点到邻居的最近距离来比较点云 B 和 A。通过平均找到的距离(排除异常值),您可以得到一个很好的估计的相似性。
有哪些指标或方法广泛用于比较两个点云对象的相似性? (例如,它可以是 PCD 文件或 PLY 文件)。
我在 PCL 图书馆的文档中搜索过,但没有找到。用谷歌搜索,找到了一些研究,但他们谈论的是新方法,而不是广泛使用或已经使用的方法。
有什么比较点云相似度的基本方法吗?或者甚至 PCL 库中的某些函数可以完成这项工作?
不幸的是,我认为它没有正式记录,但 PCL 有一个命令行应用程序来报告 Hausdorff distance between two clouds. Try running pcl_compute_hausdorff
. It's also available in the PDAL library (https://pdal.io/apps/hausdorff.html),而你会 运行 pdal hausdorff
.
另一个常见的是倒角距离(如 https://arxiv.org/abs/1612.00603 中所述),尽管我没有立即意识到实现。
这是我的方法:
#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);
}
这个想法是通过搜索 B 的每个点到邻居的最近距离来比较点云 B 和 A。通过平均找到的距离(排除异常值),您可以得到一个很好的估计的相似性。