PointCloudLibrary / PointCloudLibrary/pcl

RadiusOutlierRemoval<PCLPointCloud2> implementation is slow and confusing

Open
#2,816 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

effort: medium good first issue kind: bug kind: todo module: filters
Dominant language
C++
Stars
11.1k
Forks
4.7k
Avg merge
4d 10h
Merged PRs (30d)
6

Description

Hi,

Context

I had some troubles with the implementation of the RadiusOutlierRemoval<PCLPointCloud2> filter :
it doesn't have the same behavior as the templated RadiusOutlierRemoval<PointT> implementation.
I wrote the following unit-test to show the problem :

Code to Reproduce

GTEST_TEST(OutlierRemovalTest, SimpleTest)
{
    using namespace pcl;

    PointCloud<PointXYZ>::Ptr pc_in(new PointCloud<PointXYZ>());
    pc_in->push_back(PointXYZ(1.f, 0.f, 0.f));
    pc_in->push_back(PointXYZ(2.f, 0.f, 0.f));
    pc_in->push_back(PointXYZ(3.f, 0.f, 0.f));

    PCLPointCloud2::Ptr pc2_in(new PCLPointCloud2());
    toPCLPointCloud2(*pc_in, *pc2_in);

    {
        RadiusOutlierRemoval<PointXYZ> filter;
        filter.setInputCloud(pc_in);
        filter.setRadiusSearch(1.1);
        filter.setMinNeighborsInRadius(2);
        PointCloud<PointXYZ> pc_out;
        filter.filter(pc_out);
        EXPECT_EQ(pc_out.size(), 1);
        EXPECT_NEAR(pc_out.at(0).x, 2.f, 1e-4f);
        EXPECT_NEAR(pc_out.at(0).y, 0.f, 1e-4f);
        EXPECT_NEAR(pc_out.at(0).z, 0.f, 1e-4f);
    }

    {
        RadiusOutlierRemoval<PCLPointCloud2> filter;
        filter.setInputCloud(pc2_in);
        filter.setRadiusSearch(1.1);
        // the implementation seems to consider itself as a neigbour, the test only works if
        // we change the next line to filter.setMinNeighborsInRadius(3);
        filter.setMinNeighborsInRadius(2);
        PCLPointCloud2 pc2_out;
        PointCloud<PointXYZ> pc_out;
        filter.filter(pc2_out);
        fromPCLPointCloud2(pc2_out, pc_out);
        EXPECT_EQ(pc_out.size(), 1); // this will fail
        EXPECT_NEAR(pc_out.at(0).x, 2.f, 1e-4f);
        EXPECT_NEAR(pc_out.at(0).y, 0.f, 1e-4f);
        EXPECT_NEAR(pc_out.at(0).z, 0.f, 1e-4f);
    }
}

Current Behavior

This test fails for the RadiusOutlierRemoval<PCLPointCloud2> filter.

Moreover the RadiusOutlierRemoval<PCLPointCloud2> implementation is a lot slower in my test cases :
For a dataset of ~12000 points from a 3D Lidar I measured the following timings :

BM_RadiusOutlierRemoval<PointXYZI>             18.8 ms
BM_RadiusOutlierRemoval<PCLPointCloud2>        143 ms

Possible Solution

It is confusing to have two different implementations for the same filter.
I think the best solution that doesn't break the API for existing projects would be marking the RadiusOutlierRemoval<PCLPointCloud2> implementation as deprecated, explaining RadiusOutlierRemoval<PointT> should be used instead.
If you agree with this change I can make a pull request.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Locate the RadiusOutlierRemoval and RadiusOutlierRemoval implementations and the relevant OutlierRemovalTest coverage. Start by running the supplied SimpleTest with both filters, then compare their neighbor-count behavior and benchmark results. Done means the discrepancy is resolved or the PCLPointCloud2 implementation is clearly deprecated without breaking existing API expectations.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
computer-vision, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.