0

我有巨大的点云,我想在上面应用 voxelGrid。但由于点云太大,我有错误,如"[pcl::VoxelGrid::applyFilter] Leaf size is too small for the input dataset. Integer indices would overflow". 所以我想先从我的点云构建一个八叉树,然后在每个叶子上应用过滤器(即在具有良好索引的点云上应用过滤器)
问题出现在这里,当我应用过滤器时,PCL要我选择一个PointCloud 将保存在其中,并将原始点云替换为过滤器的结果。我想知道是否可以修改过滤器以使其不删除点,而仅将必须删除的点云中索引处的点放入(0,0,0)?

我的代码:

void Octree::applyExample(float x, float y, float z) {
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    // Fill in the cloud data
    cloud->width = 100000;
    cloud->height = 1;
    cloud->is_dense = false;
    cloud->points.resize(cloud->width * cloud->height);

    for (size_t i = 0; i < cloud->points.size(); ++i)
    {
        cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
    }
    octree.setInputCloud(cloud);
    octree.addPointsFromInputCloud();
    pcl::octree::OctreePointCloud<pcl::PointXYZRGB>::LeafNodeIterator it;
    pcl::octree::OctreePointCloud<pcl::PointXYZRGB>::LeafNodeIterator it_end = octree.leaf_end();
    for (it = octree.leaf_begin(); it != it_end; ++it)
    {

        pcl::IndicesPtr indexVector(new vector<int>);
        pcl::octree::OctreeContainerPointIndices& container = it.getLeafContainer();

        container.getPointIndices(*indexVector);
        FILTREexample(cloud, indexVector, x, y, z);
    }
}

和过滤器:

void FILTREexample(pcl::PointCloud<pcl::PointXYZ>::Ptr pointcloud, pcl::IndicesPtr indices, float x, float y, float z) {
    pcl::VoxelGrid<pcl::PointXYZ> sor;
    sor.setInputCloud(pointcloud);
    sor.setIndices(indices);
    sor.setLeafSize(x, y, z);
    sor.filter(*pointcloud); //The problem occurs here
    //Everytime, the pointcloud is substituted with the result of the filter, but I'd like to still have my "entire" pointcloud, but either with the filtered point deleted, or the filtered point put to 0,0,0.

}

有可能做这样的事情吗?

4

2 回答 2

1

您的原始点云正在被替换,因为它正是您通过编写“告诉”PCL 执行的操作:sor.filter(*pointcloud);过滤器方法的参数是“输出云”。您可以传递一个空云,过滤结果将保存到其中。(输入已经通过 定义setInputCloud

因此,您可以将 FILTERExamples 重写为:

pcl::PointCloud<pcl::PointXYZ>::Ptr FILTREexample(pcl::PointCloud<pcl::PointXYZ>::Ptr pointcloud, pcl::IndicesPtr indices, float x, float y, float z) {
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_pointcloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::VoxelGrid<pcl::PointXYZ> sor;
    sor.setInputCloud(pointcloud);
    sor.setIndices(indices);
    sor.setLeafSize(x, y, z);
    sor.filter(*filtered_pointcloud); // No problem :)
    return filtered_pointcloud;
}

而 applyExample 只会连接

void Octree::applyExample(float x, float y, float z) {    

    ... // no change

    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);    
    for (it = octree.leaf_begin(); it != it_end; ++it)
    {

        pcl::IndicesPtr indexVector(new vector<int>);
        pcl::octree::OctreeContainerPointIndices& container = it.getLeafContainer();

        container.getPointIndices(*indexVector);
        *filtered_cloud += *FILTREexample(cloud, indexVector, x,y,z);
    }
}
于 2018-11-18T18:49:38.993 回答
1

据我所知,没有“pcl”方法可以做到这一点。您应该自己进行一些编码以获得您期望的结果。想到的另一种选择是:您可以将来自体素过滤器的结果(过滤)点云添加到输入参数pointcloud中,如下所示。这基本上会使您的原始点云膨胀并可能导致速度变慢,因为点云的点存储在 a 中std::vector<T>,并且调整此容器的大小很昂贵。

...
typedef pcl::PointCloud<pcl::PointXYZ> PC_t;
PC_t::Ptr temp_pc(new PC_t());
// Your voxel grid filter code ...
// ...
sor.filter(temp_pc);
for(auto& p : temp_pc->points)
    pointcloud->push_back(p);

函数中的循环applyExample(...)完成后,您将拥有所有初始点体素过滤点。然后您可以使用pcl::ExtractIndices<T>过滤器删除原始点云中的所有点(即cloud)。请注意,您知道一开始有多少点,因此您知道要传递到哪些索引ExtractIndices。您还应该注意,删除循环中的点将使您的八叉树无效,这就是必须推迟删除点的原因。请检查 [1] 以了解如何 pcl::ExtractIndices<T>使用。

这只是获得所需结果的一种方式,而且可能是效率最低的方式之一。将另一个点云传递给您FILTREexample()将在其中累积点的函数temp_pc可能有助于加快速度。但是,这里的要点是 PCL 中没有类似filterAndAppend(...).

[1] http://pointclouds.org/documentation/tutorials/extract_indices.php

于 2018-11-14T23:20:16.100 回答