C++ PCL在八叉树上应用过滤器,无云拷贝

C++ PCL在八叉树上应用过滤器,无云拷贝,c++,point-cloud-library,C++,Point Cloud Library,我有巨大的点云,我想在上面应用体素网格。但由于点云太大,我出现了错误,例如,“[pcl::VoxelGrid::applyFilter]叶大小对于输入数据集太小。整数索引将溢出”。因此,我想首先从我的点云构建一个八叉树,然后在每个叶上应用过滤器(即在索引良好的点云上应用过滤器) 问题出现在这里,当我应用过滤器时,PCL希望我选择一个将保存它的点云,并用过滤器的结果替换原始点云。我想知道是否可以修改过滤器,使其不删除点,而只将必须删除的点云索引处的点放入(0,0,0)中 我的代码: void Oc

我有巨大的点云,我想在上面应用体素网格。但由于点云太大,我出现了错误,例如,
“[pcl::VoxelGrid::applyFilter]叶大小对于输入数据集太小。整数索引将溢出”
。因此,我想首先从我的点云构建一个八叉树,然后在每个叶上应用过滤器(即在索引良好的点云上应用过滤器)
问题出现在这里,当我应用过滤器时,PCL希望我选择一个将保存它的点云,并用过滤器的结果替换原始点云。我想知道是否可以修改过滤器,使其不删除点,而只将必须删除的点云索引处的点放入(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八叉树::applyExample(浮点x,浮点y,浮点z){
pcl::PointCloud::Ptr cloud(新的pcl::PointCloud);
//填写云数据
云->宽度=100000;
云->高度=1;
云->密度=假;
云->点。调整大小(云->宽度*云->高度);
对于(size_t i=0;ipoints.size();++i)
{
云->点[i].x=1024*rand()/(rand_MAX+1.0f);
云->点[i].y=1024*rand()/(rand_MAX+1.0f);
云->点[i].z=1024*rand()/(rand_MAX+1.0f);
}
八叉树setInputCloud(cloud);
octree.addPointsFromInputCloud();
pcl::octree::OctreePointCloud::LeafNodeIt操作符;
pcl::octree::OctreePointCloud::LeafNodeInterator it_end=octree.leaf_end();
for(it=octree.leaf_begin();it!=it_end;++it)
{
pcl::IndicateSPTR indexVector(新向量);
pcl::octree::OctreeContainerPointIndex&container=it.getLeafContainer();
container.getPointIndexs(*indexVector);
filterExample(云,索引向量,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.

}
void filtereExample(pcl::PointCloud::Ptr PointCloud,pcl::indicatesptr index,float x,float y,float z){
体素网格;
sor.setInputCloud(点云);
设定指数(指数);
设定叶大小(x,y,z);
sor.filter(*pointcloud);//问题发生在这里
//每次,点云都会被过滤器的结果替换,但我仍然希望保留“整个”点云,但要么删除过滤点,要么将过滤点设置为0,0,0。
}

有可能做这样的事情吗?

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

...
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);
。。。
typedef pcl::PointCloud PC\t;
PC_t::Ptr temp_PC(新PC_t());
//你的体素网格过滤器代码。。。
// ...
sor.过滤器(温度传感器);
用于(自动&p:temp_pc->points)
点云->推回(p);
一旦
applyExample(…)
函数中的循环完成,您将拥有所有初始点和体素过滤点。然后可以使用
pcl::extractIndexs
过滤器删除原始点云(即
)中的所有点。请注意,您知道一开始有多少点,因此您知道将哪些索引传递到
提取索引
。您还应该注意,删除循环中的点将使八叉树无效,这就是为什么必须推迟删除点的原因。请检查[1]以了解如何使用
pcl::ExtractIndexs

这只是一种获得你想要的结果的方法,可能是效率最低的方法之一。将另一个点云传递到您的
FilterExample()
函数,您将在
temp\u pc
中累积点,这可能有助于加快速度。然而,这里的要点是,在PCL中没有类似于
filterAndAppend(…)
的方法


[1]

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

...
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);
。。。
typedef pcl::PointCloud PC\t;
PC_t::Ptr temp_PC(新PC_t());
//你的体素网格过滤器代码。。。
// ...
sor.过滤器(温度传感器);
用于(自动&p:temp_pc->points)
点云->推回(p);
一旦
applyExample(…)
函数中的循环完成,您将拥有所有初始点和体素过滤点。然后可以使用
pcl::extractIndexs
过滤器删除原始点云(即
)中的所有点。请注意,您知道一开始有多少点,因此您知道将哪些索引传递到
提取索引
。您还应该注意,删除循环中的点将使八叉树无效,这就是为什么必须推迟删除点的原因。请检查[1]以了解如何使用
pcl::ExtractIndexs

这只是一种获得你想要的结果的方法,可能是效率最低的方法之一。将另一个点云传递到您的
FilterExample()
函数,您将在
temp\u pc
中累积点,这可能有助于加快速度。然而,这里的要点是,在PCL中没有类似于
filterAndAppend(…)
的方法


[1] 您的原始点云将被替换,因为它正是您想要的
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);
    }
}