首页 > 解决方案 > 以有效的方式将点从一个 PCL 移到另一个

问题描述

类似的问题,但我主要关心的是处理时间

我有两个 PCL,都是 type pcl::PointXYZL,也就是说,每个点都有一个标签/id 信息。我想在 PC B 中删除 A 中存在的所有点(由标签信息识别)。

这种类型的迭代需要太多时间。

我决定将标签从 PC A 保存到boost::container::flat_set<int> labels,并将云 B 设置为std::map<int, pcl::PointXYZL> cloud_B,其中键是该点的标签/ID。然后我这样做:

    for(boost::container::flat_set<int>::iterator it = labels.begin() ; it != labels.end(); ++it){
        if ( auto point{ cloud_B.find( *it ) }; point != std::end(cloud_B)){
            cloud_B.erase(*it);
        }
    }

它现在要快得多,但老实说,我认为可能有更有效的解决方案。

我也尝试:

   for(boost::container::flat_set<int>::iterator it = labels.begin() ; it != labels.end(); ++it){
        try{
            cloud_B.erase(*it);
            throw 505;
        }
        catch (...){
            continue;
        }
    }

但这比我带来的第一个例子要花更多的时间。

我感谢任何帮助!

标签: point-clouds

解决方案


您的两个解决方案都大致为 O(n^2) 复杂度。

用于unordered_set<std::uint32_t>检查它是否存在。的平均情况unordered_set<std::uint32_t>::count恒定的,因此它应该比您的解决方案更好

示例代码(未经测试),但你得到了粗略的想法。

pcl::PointCloud<pcl::PointXYZL> cloud_a;
pcl::PointCloud<pcl::PointXYZL> cloud_b;

... (fill cloud)

// generate unordered_set<uint32_t> O(n)
std::unordered_set<std::uint32_t> labels_in_cloud_a;
for (int i = 0; i < cloud_a.size(); ++i) {
  labels_in_cloud_a.insert(cloud_a.points[i].label);
}

// indices where in cloud_b where label doesn't exist in labels_in_clouda O(n*1) = O(n)
std::vector<int> indices;
for (int i = 0; i < cloud_b.size(); ++i) {
  if (labels_in_cloud_a.count(cloud_b.points[i].label) == 0) {
    indices.push_back(i);
  }
}

// only indices that doesn't exist in cloud_a will remain. O(n)
pcl::copyPointCloud(cloud_b, indices, cloud_b);

推荐阅读