diff --git a/segmentation/include/pcl/segmentation/impl/progressive_morphological_filter.hpp b/segmentation/include/pcl/segmentation/impl/progressive_morphological_filter.hpp index e65aa01bb58..049c4cf98e7 100644 --- a/segmentation/include/pcl/segmentation/impl/progressive_morphological_filter.hpp +++ b/segmentation/include/pcl/segmentation/impl/progressive_morphological_filter.hpp @@ -84,7 +84,9 @@ pcl::ProgressiveMorphologicalFilter::extract (Indices& ground) if (iteration == 0) height_threshold = initial_distance_; else - height_threshold = slope_ * (window_size - window_sizes[iteration-1]) * cell_size_ + initial_distance_; + // Exact PMF window sizes are already in input coordinate units. + height_threshold = + slope_ * (window_size - window_sizes[iteration - 1]) + initial_distance_; // Enforce max distance on height threshold if (height_threshold > max_distance_) diff --git a/test/segmentation/test_progressive_morphological_filter.cpp b/test/segmentation/test_progressive_morphological_filter.cpp index 2a2012e0788..f163b8a7008 100644 --- a/test/segmentation/test_progressive_morphological_filter.cpp +++ b/test/segmentation/test_progressive_morphological_filter.cpp @@ -13,6 +13,36 @@ #include +namespace { +pcl::Indices +classifyScaledCloud(float scale) +{ + auto cloud = pcl::make_shared>(); + cloud->reserve(13); + // The raised seven-point plateau survives the smaller openings and is + // evaluated against the height threshold at the final window size. + for (int i = -6; i <= 6; ++i) { + const float x = 0.25f * static_cast(i) * scale; + const float z = (i >= -3 && i <= 3) ? 0.8f * scale : 0.0f; + cloud->emplace_back(x, 0.0f, z); + } + + pcl::ProgressiveMorphologicalFilter filter; + filter.setInputCloud(cloud); + filter.setCellSize(0.25f * scale); + filter.setMaxWindowSize(2.25f * scale); + filter.setBase(2.0f); + filter.setExponential(true); + filter.setSlope(1.0f); + filter.setInitialDistance(0.1f * scale); + filter.setMaxDistance(100.0f * scale); + + pcl::Indices ground; + filter.extract(ground); + return ground; +} +} // namespace + TEST(ProgressiveMorphologicalFilter, FractionalMaximumWindowSize) { pcl::ProgressiveMorphologicalFilter filter; @@ -23,6 +53,15 @@ TEST(ProgressiveMorphologicalFilter, FractionalMaximumWindowSize) EXPECT_FLOAT_EQ(filter.getMaxWindowSize(), 6.25f); } +TEST(ProgressiveMorphologicalFilter, ClassificationIsInvariantToCoordinateScale) +{ + // Scaling the coordinates and every distance parameter must not change which + // points are classified as ground. + const auto ground = classifyScaledCloud(1.0f); + EXPECT_EQ(ground.size(), 13u); + EXPECT_EQ(ground, classifyScaledCloud(4.0f)); +} + /* ---[ */ int main(int argc, char** argv)