From 0f9893867224f1d363b21107236392d2bfe7ef9e Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Thu, 16 Jul 2020 17:30:34 +1200 Subject: [PATCH 01/20] Fix logic bug in Organized Edge Detection A bug was introduced in commit 8092d6529eed0b489f3c7ab50be018f20b6da2bb that inadvertantly changed behavior of edge feature extraction for occluding and occluded edges. This commit reverts to previous logic --- features/include/pcl/features/impl/organized_edge_detection.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/include/pcl/features/impl/organized_edge_detection.hpp b/features/include/pcl/features/impl/organized_edge_detection.hpp index 3e5ebb9adf8..c70b8f31ef4 100644 --- a/features/include/pcl/features/impl/organized_edge_detection.hpp +++ b/features/include/pcl/features/impl/organized_edge_detection.hpp @@ -131,7 +131,7 @@ pcl::OrganizedEdgeBase::extractEdges (pcl::PointCloud& std::tie (min_itr, max_itr) = std::minmax_element (nghr_dist.cbegin (), nghr_dist.cend ()); float nghr_dist_min = *min_itr; float nghr_dist_max = *max_itr; - float dist_dominant = std::max(std::abs (nghr_dist_min),std::abs (nghr_dist_max)); + float dist_dominant = std::abs (nghr_dist_min) > std::abs (nghr_dist_max) ? nghr_dist_min : nghr_dist_max; if (std::abs (dist_dominant) > th_depth_discon_*std::abs (curr_depth)) { // Found a depth discontinuity From 21c67dd229bda124522b690e3d430a734a397d6d Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Thu, 16 Jul 2020 22:45:46 +1200 Subject: [PATCH 02/20] Add Unit Test for Organized Edge Detection This unit tests generates a synthetic organized cloud with a known number of occluding and occluded edge points determined from output of the OrganizedEdgeDetection functionality in PCL before 1.10.1. The edges are then found in this cloud and compared to the empirically determined results. --- test/features/CMakeLists.txt | 3 + .../test_organized_edge_detection.cpp | 126 ++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 test/features/test_organized_edge_detection.cpp diff --git a/test/features/CMakeLists.txt b/test/features/CMakeLists.txt index 9775415a1d2..d89d80c1cc0 100644 --- a/test/features/CMakeLists.txt +++ b/test/features/CMakeLists.txt @@ -108,6 +108,9 @@ if(BUILD_io) FILES test_gasd_estimation.cpp LINK_WITH pcl_gtest pcl_io pcl_features ARGUMENTS "${PCL_SOURCE_DIR}/test/bun0.pcd") + PCL_ADD_TEST(feature_organized_edge_detection test_organized_edge_detection + FILES test_organized_edge_detection.cpp + LINK_WITH pcl_gtest pcl_features pcl_io) if(BUILD_keypoints) PCL_ADD_TEST(feature_brisk test_brisk FILES test_brisk.cpp diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp new file mode 100644 index 00000000000..cbfa18e642c --- /dev/null +++ b/test/features/test_organized_edge_detection.cpp @@ -0,0 +1,126 @@ +/* + * Software License Agreement (BSD License) + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2010-2012, Willow Garage, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the copyright holder(s) nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + * + */ + +#include +#include +#include +#include + +pcl::PointCloud ::Ptr cloud; +pcl::PointIndicesPtr indices; +std::vector triangles; + +pcl::PointCloud::Ptr GenerateSyntheticEdgeDetectionCloud(const float &disparity) +{ + auto resolution = .005; + auto box_width = 50; + + auto organized_test_cloud = pcl::make_shared>(); + organized_test_cloud->width = box_width * 4; + organized_test_cloud->height = box_width * 4; + organized_test_cloud->is_dense = false; + organized_test_cloud->points.resize(organized_test_cloud->height * organized_test_cloud->width); + + for(std::size_t i = 0; i < box_width * 2; i++) + { + for(std::size_t j = 0; j < box_width * 2; j++) + { + organized_test_cloud->at(j, i).x = i * resolution - (box_width / 2 * resolution); + organized_test_cloud->at(j, i).y = j * resolution; + organized_test_cloud->at(j, i).z = 2.0 + (disparity * 4); + organized_test_cloud->at(j, i).r = 128; + organized_test_cloud->at(j, i).g = 128; + organized_test_cloud->at(j, i).b = 128; + organized_test_cloud->at(j, i).a = 255; + } + } + + for(std::size_t i = box_width / 2; i < box_width / 2 + box_width; i++) + { + for(std::size_t j = box_width / 2; j < box_width / 2 + box_width; j++) + { + organized_test_cloud->at(j, i).x = i * resolution - (box_width / 2 * resolution); + organized_test_cloud->at(j, i).y = j * resolution; + organized_test_cloud->at(j, i).z = 2.0; + organized_test_cloud->at(j, i).r = 192; + organized_test_cloud->at(j, i).g = 192; + organized_test_cloud->at(j, i).b = 192; + organized_test_cloud->at(j, i).a = 255; + } + } + + return organized_test_cloud; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +TEST (OrganizedPlaneDetection, OccludedAndOccludingEdges ) +{ + float support_radius = 0.0285f; + unsigned int number_of_partition_bins = 5; + unsigned int number_of_rotations = 3; + auto MaxSearchNeighbors = 50; + auto DepthDiscontinuity = .02f; + + cloud = GenerateSyntheticEdgeDetectionCloud(DepthDiscontinuity); + + auto oed = pcl::OrganizedEdgeFromRGB(); + + oed.setEdgeType(oed.EDGELABEL_OCCLUDING | oed.EDGELABEL_OCCLUDED); + oed.setInputCloud(cloud); + oed.setDepthDisconThreshold(DepthDiscontinuity); + oed.setMaxSearchNeighbors(MaxSearchNeighbors); + + auto labels = pcl::PointCloud(); + auto label_indices = std::vector(); + + oed.compute(labels, label_indices); + + EXPECT_EQ (395, label_indices[1].indices.size()); // Occluding Edges Indices Size should be 395 for synthetic cloud + EXPECT_EQ (401, label_indices[2].indices.size()); // Occluded Edge Indices should be 401 for synthentic cloud +} + + +/* ---[ */ +int +main (int argc, char** argv) +{ + testing::InitGoogleTest (&argc, argv); + return (RUN_ALL_TESTS ()); +} +/* ]--- */ From c6924cb474ba658c5022997a61f8d816f248aa29 Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Mon, 20 Jul 2020 23:55:38 -0500 Subject: [PATCH 03/20] Use correct copyright header and SPDX id --- .../test_organized_edge_detection.cpp | 36 ++----------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index cbfa18e642c..2c77aef73bf 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -1,40 +1,10 @@ /* - * Software License Agreement (BSD License) + * SPDX-License-Identifier: BSD-3-Clause * * Point Cloud Library (PCL) - www.pointclouds.org - * Copyright (c) 2010-2012, Willow Garage, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of the copyright holder(s) nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $Id$ + * Copyright (c) 2020-, Open Perception * + * All rights reserved */ #include From 0d3bfd1360924f4b33d3370a2460526d75d1c92c Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Tue, 21 Jul 2020 03:20:29 -0500 Subject: [PATCH 04/20] Use gtest fixture to setup test cloud --- .../test_organized_edge_detection.cpp | 71 ++++++++++++------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index 2c77aef73bf..24ace469654 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -12,27 +12,46 @@ #include #include -pcl::PointCloud ::Ptr cloud; -pcl::PointIndicesPtr indices; -std::vector triangles; - -pcl::PointCloud::Ptr GenerateSyntheticEdgeDetectionCloud(const float &disparity) +namespace { - auto resolution = .005; - auto box_width = 50; + class OrganizedPlaneDetectionTestFixture : public ::testing::Test + { + protected: + static const int kExpectedOccludingEdgePoints = 395; + static const int kExpectedOccludedEdgePoints = 401; + static const int kSyntheticCloudDisparity = .03; + static const int kSyntheticCloudResolution = .005; + static const int kSyntheticCloudInnerBoxWidth = 50; + + pcl::PointCloud ::Ptr cloud_; + pcl::PointIndicesPtr indices_; + OrganizedPlaneDetectionTestFixture() = default; + virtual ~OrganizedPlaneDetectionTestFixture() = default; + virtual void SetUp() + { + cloud_ = GenerateSyntheticEdgeDetectionCloud(kSyntheticCloudDisparity); + } + virtual void TearDown() + { + cloud_.reset(); + } + + private: + pcl::PointCloud::Ptr GenerateSyntheticEdgeDetectionCloud(const float &disparity) + { auto organized_test_cloud = pcl::make_shared>(); - organized_test_cloud->width = box_width * 4; - organized_test_cloud->height = box_width * 4; + organized_test_cloud->width = kSyntheticCloudInnerBoxWidth * 4; + organized_test_cloud->height = kSyntheticCloudInnerBoxWidth * 4; organized_test_cloud->is_dense = false; organized_test_cloud->points.resize(organized_test_cloud->height * organized_test_cloud->width); - - for(std::size_t i = 0; i < box_width * 2; i++) + + for(std::size_t i = 0; i < kSyntheticCloudInnerBoxWidth * 2; i++) { - for(std::size_t j = 0; j < box_width * 2; j++) + for(std::size_t j = 0; j < kSyntheticCloudInnerBoxWidth * 2; j++) { - organized_test_cloud->at(j, i).x = i * resolution - (box_width / 2 * resolution); - organized_test_cloud->at(j, i).y = j * resolution; + organized_test_cloud->at(j, i).x = i * kSyntheticCloudResolution - (kSyntheticCloudInnerBoxWidth / 2 * kSyntheticCloudResolution); + organized_test_cloud->at(j, i).y = j * kSyntheticCloudResolution; organized_test_cloud->at(j, i).z = 2.0 + (disparity * 4); organized_test_cloud->at(j, i).r = 128; organized_test_cloud->at(j, i).g = 128; @@ -41,12 +60,12 @@ pcl::PointCloud::Ptr GenerateSyntheticEdgeDetectionCloud(cons } } - for(std::size_t i = box_width / 2; i < box_width / 2 + box_width; i++) + for(std::size_t i = kSyntheticCloudInnerBoxWidth / 2; i < kSyntheticCloudInnerBoxWidth / 2 + kSyntheticCloudInnerBoxWidth; i++) { - for(std::size_t j = box_width / 2; j < box_width / 2 + box_width; j++) + for(std::size_t j = kSyntheticCloudInnerBoxWidth / 2; j < kSyntheticCloudInnerBoxWidth / 2 + kSyntheticCloudInnerBoxWidth; j++) { - organized_test_cloud->at(j, i).x = i * resolution - (box_width / 2 * resolution); - organized_test_cloud->at(j, i).y = j * resolution; + organized_test_cloud->at(j, i).x = i * kSyntheticCloudResolution - (kSyntheticCloudInnerBoxWidth / 2 * kSyntheticCloudResolution); + organized_test_cloud->at(j, i).y = j * kSyntheticCloudResolution; organized_test_cloud->at(j, i).z = 2.0; organized_test_cloud->at(j, i).r = 192; organized_test_cloud->at(j, i).g = 192; @@ -54,25 +73,23 @@ pcl::PointCloud::Ptr GenerateSyntheticEdgeDetectionCloud(cons organized_test_cloud->at(j, i).a = 255; } } - return organized_test_cloud; + } + + + }; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -TEST (OrganizedPlaneDetection, OccludedAndOccludingEdges ) +TEST_F (OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) { - float support_radius = 0.0285f; - unsigned int number_of_partition_bins = 5; - unsigned int number_of_rotations = 3; - auto MaxSearchNeighbors = 50; + auto MaxSearchNeighbors = 50; auto DepthDiscontinuity = .02f; - cloud = GenerateSyntheticEdgeDetectionCloud(DepthDiscontinuity); - auto oed = pcl::OrganizedEdgeFromRGB(); oed.setEdgeType(oed.EDGELABEL_OCCLUDING | oed.EDGELABEL_OCCLUDED); - oed.setInputCloud(cloud); + oed.setInputCloud(cloud_); oed.setDepthDisconThreshold(DepthDiscontinuity); oed.setMaxSearchNeighbors(MaxSearchNeighbors); From 31c25675e85f9727eb66b29a47f0c4fb2eaceb67 Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Tue, 21 Jul 2020 05:14:13 -0500 Subject: [PATCH 05/20] Use proper image conventions Detail how test works Use proper cloud constructor Remove magic numbers --- .../test_organized_edge_detection.cpp | 100 +++++++++++------- 1 file changed, 59 insertions(+), 41 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index 24ace469654..5044220f2f0 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -17,11 +17,14 @@ namespace class OrganizedPlaneDetectionTestFixture : public ::testing::Test { protected: - static const int kExpectedOccludingEdgePoints = 395; - static const int kExpectedOccludedEdgePoints = 401; - static const int kSyntheticCloudDisparity = .03; - static const int kSyntheticCloudResolution = .005; - static const int kSyntheticCloudInnerBoxWidth = 50; + const int kSyntheticCloudInnerSquareEdgeLength = 124; + const int kSyntheticCloudOuterSquareEdgeLength = kSyntheticCloudInnerSquareEdgeLength * 2; + + const int kExpectedOccludingEdgePoints = kSyntheticCloudInnerSquareEdgeLength * 4 - 8; // Empirically determined + const int kExpectedOccludedEdgePoints = kSyntheticCloudInnerSquareEdgeLength * 4; // Each edge pixed of inner square should generate an occluded point + + const float kSyntheticCloudDisparity = .03f; + const float kSyntheticCloudResolution = 0.01f; pcl::PointCloud ::Ptr cloud_; pcl::PointIndicesPtr indices_; @@ -40,66 +43,81 @@ namespace private: pcl::PointCloud::Ptr GenerateSyntheticEdgeDetectionCloud(const float &disparity) { - auto organized_test_cloud = pcl::make_shared>(); - organized_test_cloud->width = kSyntheticCloudInnerBoxWidth * 4; - organized_test_cloud->height = kSyntheticCloudInnerBoxWidth * 4; - organized_test_cloud->is_dense = false; - organized_test_cloud->points.resize(organized_test_cloud->height * organized_test_cloud->width); + auto organized_test_cloud = pcl::make_shared>(kSyntheticCloudOuterSquareEdgeLength, kSyntheticCloudOuterSquareEdgeLength); + organized_test_cloud->is_dense = true; - for(std::size_t i = 0; i < kSyntheticCloudInnerBoxWidth * 2; i++) - { - for(std::size_t j = 0; j < kSyntheticCloudInnerBoxWidth * 2; j++) - { - organized_test_cloud->at(j, i).x = i * kSyntheticCloudResolution - (kSyntheticCloudInnerBoxWidth / 2 * kSyntheticCloudResolution); - organized_test_cloud->at(j, i).y = j * kSyntheticCloudResolution; - organized_test_cloud->at(j, i).z = 2.0 + (disparity * 4); - organized_test_cloud->at(j, i).r = 128; - organized_test_cloud->at(j, i).g = 128; - organized_test_cloud->at(j, i).b = 128; - organized_test_cloud->at(j, i).a = 255; - } - } + const auto kBaseDepth = 2.0f; - for(std::size_t i = kSyntheticCloudInnerBoxWidth / 2; i < kSyntheticCloudInnerBoxWidth / 2 + kSyntheticCloudInnerBoxWidth; i++) + // Draw a smaller red square in front of a larger green square both centered on the view axis to generate synthetic occluding and occluded edges based on depth disparity between neighboring pixels + for(auto row = 0; row < kSyntheticCloudOuterSquareEdgeLength; row++) { - for(std::size_t j = kSyntheticCloudInnerBoxWidth / 2; j < kSyntheticCloudInnerBoxWidth / 2 + kSyntheticCloudInnerBoxWidth; j++) - { - organized_test_cloud->at(j, i).x = i * kSyntheticCloudResolution - (kSyntheticCloudInnerBoxWidth / 2 * kSyntheticCloudResolution); - organized_test_cloud->at(j, i).y = j * kSyntheticCloudResolution; - organized_test_cloud->at(j, i).z = 2.0; - organized_test_cloud->at(j, i).r = 192; - organized_test_cloud->at(j, i).g = 192; - organized_test_cloud->at(j, i).b = 192; - organized_test_cloud->at(j, i).a = 255; + for(auto col = 0; col < kSyntheticCloudOuterSquareEdgeLength; col++) + { + float x = col - (kSyntheticCloudOuterSquareEdgeLength / 2); + float y = row - (kSyntheticCloudOuterSquareEdgeLength / 2); + + const auto outer_square_ctr = kSyntheticCloudOuterSquareEdgeLength / 2; + const auto inner_square_ctr = kSyntheticCloudInnerSquareEdgeLength / 2; + + auto depth = kBaseDepth + (disparity * 2); + auto r = 0; + auto g = 255; + + // If pixels correspond to smaller box, then set depth and color appropriately + if (col > outer_square_ctr - inner_square_ctr && col < outer_square_ctr + inner_square_ctr) + { + if (row > outer_square_ctr - inner_square_ctr && row < outer_square_ctr + inner_square_ctr) + { + depth = kBaseDepth; + r = 255; + g = 0; + } + } + + organized_test_cloud->at(col, row).x = x * kSyntheticCloudResolution; + organized_test_cloud->at(col, row).y = y * kSyntheticCloudResolution; + organized_test_cloud->at(col, row).z = depth; + organized_test_cloud->at(col, row).r = r; + organized_test_cloud->at(col, row).g = g; + organized_test_cloud->at(col, row).b = 0; + organized_test_cloud->at(col, row).a = 255; } } - return organized_test_cloud; - } + return organized_test_cloud; + } }; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* +This test is designed to ensure that the organized edge detection appropriately classifies occluding and occluding +edges and to speifically detect the type of regression detailed in PR 4275 +(https://github.com/PointCloudLibrary/pcl/pull/4275). This test works by generating a synthentic cloud of one +square slightly in front of another square, so that occluding edges and occluded edges are generated. The +regression introduced in PCL 1.10.1 was a logic bug that caused both occluding and occluded edges to erroneously +be categorized as occluding edges. This test should catch this and similar bugs. +*/ TEST_F (OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) { - auto MaxSearchNeighbors = 50; - auto DepthDiscontinuity = .02f; + const auto kMaxSearchNeighbors = 50; + const auto kDepthDiscontinuity = .02f; auto oed = pcl::OrganizedEdgeFromRGB(); oed.setEdgeType(oed.EDGELABEL_OCCLUDING | oed.EDGELABEL_OCCLUDED); oed.setInputCloud(cloud_); - oed.setDepthDisconThreshold(DepthDiscontinuity); - oed.setMaxSearchNeighbors(MaxSearchNeighbors); + oed.setDepthDisconThreshold(kDepthDiscontinuity); + oed.setMaxSearchNeighbors(kMaxSearchNeighbors); auto labels = pcl::PointCloud(); auto label_indices = std::vector(); oed.compute(labels, label_indices); - EXPECT_EQ (395, label_indices[1].indices.size()); // Occluding Edges Indices Size should be 395 for synthetic cloud - EXPECT_EQ (401, label_indices[2].indices.size()); // Occluded Edge Indices should be 401 for synthentic cloud + EXPECT_EQ (kExpectedOccludingEdgePoints, label_indices[1].indices.size()); // Occluding Edges Indices Size should be 395 for synthetic cloud + EXPECT_EQ (kExpectedOccludedEdgePoints, label_indices[2].indices.size()); // Occluded Edge Indices should be 401 for synthentic cloud } From edf401a2b9fa8bb458c406a07272d1a09d25e2cf Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Wed, 22 Jul 2020 17:34:46 -0500 Subject: [PATCH 06/20] Use PCL variable naming style and formatting Use "depth discontinuity" instead of "disparity" to avoid confusion Move expected data constants to actual test Use simpler variable names Remove extraneous ctors and dtors Removed extraneous smart pointer reset call Removed extraneous setting of cloud is_dense member variable Use override keyword rather than virtual Use prefix instead of postfix operators in for loops --- .../test_organized_edge_detection.cpp | 199 +++++++++--------- 1 file changed, 101 insertions(+), 98 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index 5044220f2f0..b44ada59ab7 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -7,125 +7,128 @@ * All rights reserved */ -#include -#include #include +#include +#include #include -namespace -{ - class OrganizedPlaneDetectionTestFixture : public ::testing::Test +namespace { +class OrganizedPlaneDetectionTestFixture : public ::testing::Test { +protected: + const int INNER_SQUARE_EDGE_LENGTH = 50; + const int OUTER_SQUARE_EDGE_LENGTH = INNER_SQUARE_EDGE_LENGTH * 2; + const float SYNTHETIC_CLOUD_BASE_DEPTH = 2.0; + const float SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY = .02f; + const float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; + + pcl::PointCloud::Ptr cloud_; + pcl::PointIndicesPtr indices_; + + void + SetUp() override { - protected: - const int kSyntheticCloudInnerSquareEdgeLength = 124; - const int kSyntheticCloudOuterSquareEdgeLength = kSyntheticCloudInnerSquareEdgeLength * 2; - - const int kExpectedOccludingEdgePoints = kSyntheticCloudInnerSquareEdgeLength * 4 - 8; // Empirically determined - const int kExpectedOccludedEdgePoints = kSyntheticCloudInnerSquareEdgeLength * 4; // Each edge pixed of inner square should generate an occluded point - - const float kSyntheticCloudDisparity = .03f; - const float kSyntheticCloudResolution = 0.01f; - - pcl::PointCloud ::Ptr cloud_; - pcl::PointIndicesPtr indices_; - - OrganizedPlaneDetectionTestFixture() = default; - virtual ~OrganizedPlaneDetectionTestFixture() = default; - virtual void SetUp() - { - cloud_ = GenerateSyntheticEdgeDetectionCloud(kSyntheticCloudDisparity); - } - virtual void TearDown() - { - cloud_.reset(); - } - - private: - pcl::PointCloud::Ptr GenerateSyntheticEdgeDetectionCloud(const float &disparity) - { - auto organized_test_cloud = pcl::make_shared>(kSyntheticCloudOuterSquareEdgeLength, kSyntheticCloudOuterSquareEdgeLength); - organized_test_cloud->is_dense = true; - - const auto kBaseDepth = 2.0f; - - // Draw a smaller red square in front of a larger green square both centered on the view axis to generate synthetic occluding and occluded edges based on depth disparity between neighboring pixels - for(auto row = 0; row < kSyntheticCloudOuterSquareEdgeLength; row++) - { - for(auto col = 0; col < kSyntheticCloudOuterSquareEdgeLength; col++) - { - float x = col - (kSyntheticCloudOuterSquareEdgeLength / 2); - float y = row - (kSyntheticCloudOuterSquareEdgeLength / 2); - - const auto outer_square_ctr = kSyntheticCloudOuterSquareEdgeLength / 2; - const auto inner_square_ctr = kSyntheticCloudInnerSquareEdgeLength / 2; - - auto depth = kBaseDepth + (disparity * 2); - auto r = 0; - auto g = 255; - - // If pixels correspond to smaller box, then set depth and color appropriately - if (col > outer_square_ctr - inner_square_ctr && col < outer_square_ctr + inner_square_ctr) - { - if (row > outer_square_ctr - inner_square_ctr && row < outer_square_ctr + inner_square_ctr) - { - depth = kBaseDepth; - r = 255; - g = 0; - } - } - - organized_test_cloud->at(col, row).x = x * kSyntheticCloudResolution; - organized_test_cloud->at(col, row).y = y * kSyntheticCloudResolution; - organized_test_cloud->at(col, row).z = depth; - organized_test_cloud->at(col, row).r = r; - organized_test_cloud->at(col, row).g = g; - organized_test_cloud->at(col, row).b = 0; - organized_test_cloud->at(col, row).a = 255; - } - } - - - return organized_test_cloud; - } - }; -} + cloud_ = generateSyntheticEdgeDetectionCloud(); + } + void + TearDown() override + {} + +private: + pcl::PointCloud::Ptr + generateSyntheticEdgeDetectionCloud() + { + auto organized_test_cloud = pcl::make_shared>( + OUTER_SQUARE_EDGE_LENGTH, OUTER_SQUARE_EDGE_LENGTH); + + // Draw a smaller red square in front of a larger green square both centered on the + // view axis to generate synthetic occluding and occluded edges based on depth + // discontinuity between neighboring pixels. The base depth and resolution are + // arbitrary and useful for visualizing the cloud. The discontinuity of the + // generated cloud must be greater than the threshold set when running the + // organized edge detection algorithm. + for (auto row = 0; row < OUTER_SQUARE_EDGE_LENGTH; ++row) { + for (auto col = 0; col < OUTER_SQUARE_EDGE_LENGTH; ++col) { + float x = col - (OUTER_SQUARE_EDGE_LENGTH / 2); + float y = row - (OUTER_SQUARE_EDGE_LENGTH / 2); + + const auto outer_square_ctr = OUTER_SQUARE_EDGE_LENGTH / 2; + const auto inner_square_ctr = INNER_SQUARE_EDGE_LENGTH / 2; + + auto depth = SYNTHETIC_CLOUD_BASE_DEPTH; + auto r = 0; + auto g = 255; + + // If pixels correspond to smaller box, then set depth and color appropriately + if (col > outer_square_ctr - inner_square_ctr && + col < outer_square_ctr + inner_square_ctr) { + if (row > outer_square_ctr - inner_square_ctr && + row < outer_square_ctr + inner_square_ctr) { + depth = SYNTHETIC_CLOUD_BASE_DEPTH - SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY; + r = 255; + g = 0; + } + } + + organized_test_cloud->at(col, row).x = x * SYNTHETIC_CLOUD_RESOLUTION; + organized_test_cloud->at(col, row).y = y * SYNTHETIC_CLOUD_RESOLUTION; + organized_test_cloud->at(col, row).z = depth; + organized_test_cloud->at(col, row).r = r; + organized_test_cloud->at(col, row).g = g; + organized_test_cloud->at(col, row).b = 0; + organized_test_cloud->at(col, row).a = 255; + } + } + + return organized_test_cloud; + } +}; +} // namespace ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* -This test is designed to ensure that the organized edge detection appropriately classifies occluding and occluding -edges and to speifically detect the type of regression detailed in PR 4275 -(https://github.com/PointCloudLibrary/pcl/pull/4275). This test works by generating a synthentic cloud of one -square slightly in front of another square, so that occluding edges and occluded edges are generated. The -regression introduced in PCL 1.10.1 was a logic bug that caused both occluding and occluded edges to erroneously -be categorized as occluding edges. This test should catch this and similar bugs. +This test is designed to ensure that the organized edge detection appropriately +classifies occluding and occluding edges and to specifically detect the type of +regression detailed in PR 4275 (https://github.com/PointCloudLibrary/pcl/pull/4275). +This test works by generating a synthetic cloud of one square slightly in front of +another square, so that occluding edges and occluded edges are generated. The +regression introduced in PCL 1.10.1 was a logic bug that caused both occluding and +occluded edges to erroneously be categorized as occluding edges. This test should catch +this and similar bugs. */ -TEST_F (OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) +TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) { - const auto kMaxSearchNeighbors = 50; - const auto kDepthDiscontinuity = .02f; + pcl::io::savePCDFileBinaryCompressed("/home/perception/VagrantProjects/synthe.pcd", *cloud_); - auto oed = pcl::OrganizedEdgeFromRGB(); + const auto MAX_SEARCH_NEIGHBORS = 50; + const auto DEPTH_DISCONTINUITY_THRESHOLD = SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY / 2.1f; - oed.setEdgeType(oed.EDGELABEL_OCCLUDING | oed.EDGELABEL_OCCLUDED); - oed.setInputCloud(cloud_); - oed.setDepthDisconThreshold(kDepthDiscontinuity); - oed.setMaxSearchNeighbors(kMaxSearchNeighbors); + // The expected number of occluded edge points is the number of pixels along the + // perimeter of the inner square, subject to certain conditions including that the + // inner square edge length is an even number. The expected number of occluding edge + // points is similar, but as empirically determined to be 8 less than the number + // of perimeter points. + const int EXPECTED_OCCLUDING_EDGE_POINTS = INNER_SQUARE_EDGE_LENGTH * 4 - 8; + const int EXPECTED_OCCLUDED_EDGE_POINTS = INNER_SQUARE_EDGE_LENGTH * 4; + auto oed = pcl::OrganizedEdgeFromRGB(); auto labels = pcl::PointCloud(); auto label_indices = std::vector(); + oed.setEdgeType(oed.EDGELABEL_OCCLUDING | oed.EDGELABEL_OCCLUDED); + oed.setInputCloud(cloud_); + oed.setDepthDisconThreshold(DEPTH_DISCONTINUITY_THRESHOLD); + oed.setMaxSearchNeighbors(MAX_SEARCH_NEIGHBORS); oed.compute(labels, label_indices); - EXPECT_EQ (kExpectedOccludingEdgePoints, label_indices[1].indices.size()); // Occluding Edges Indices Size should be 395 for synthetic cloud - EXPECT_EQ (kExpectedOccludedEdgePoints, label_indices[2].indices.size()); // Occluded Edge Indices should be 401 for synthentic cloud + EXPECT_EQ(EXPECTED_OCCLUDING_EDGE_POINTS, label_indices[1].indices.size()); + EXPECT_EQ(EXPECTED_OCCLUDED_EDGE_POINTS, label_indices[2].indices.size()); } - /* ---[ */ int -main (int argc, char** argv) +main(int argc, char** argv) { - testing::InitGoogleTest (&argc, argv); - return (RUN_ALL_TESTS ()); + testing::InitGoogleTest(&argc, argv); + return (RUN_ALL_TESTS()); } /* ]--- */ From 5ffb2b69c1c1bce508ce1f103d9bfaee5addf3c2 Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Wed, 22 Jul 2020 17:41:29 -0500 Subject: [PATCH 07/20] Use clearer grammar --- test/features/test_organized_edge_detection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index b44ada59ab7..edd992a29f3 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -92,7 +92,7 @@ regression detailed in PR 4275 (https://github.com/PointCloudLibrary/pcl/pull/42 This test works by generating a synthetic cloud of one square slightly in front of another square, so that occluding edges and occluded edges are generated. The regression introduced in PCL 1.10.1 was a logic bug that caused both occluding and -occluded edges to erroneously be categorized as occluding edges. This test should catch +occluded edges to be miscategorized as occluding edges. This test should catch this and similar bugs. */ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) From 86aa14e90998e082332d0f70a8eb4b442325836d Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Wed, 22 Jul 2020 17:51:43 -0500 Subject: [PATCH 08/20] Remove PCD saving --- test/features/test_organized_edge_detection.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index edd992a29f3..5cd3b64d2b0 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -97,8 +97,6 @@ this and similar bugs. */ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) { - pcl::io::savePCDFileBinaryCompressed("/home/perception/VagrantProjects/synthe.pcd", *cloud_); - const auto MAX_SEARCH_NEIGHBORS = 50; const auto DEPTH_DISCONTINUITY_THRESHOLD = SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY / 2.1f; From c4d34675ab22663ea9625aa800b7bc33df544090 Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Thu, 23 Jul 2020 21:05:34 +1200 Subject: [PATCH 09/20] Use PointXYZ instead of PointXYZRGBA --- .../test_organized_edge_detection.cpp | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index 5cd3b64d2b0..dc676803594 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -8,9 +8,9 @@ */ #include -#include -#include #include +#include +#include namespace { class OrganizedPlaneDetectionTestFixture : public ::testing::Test { @@ -21,7 +21,7 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { const float SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY = .02f; const float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; - pcl::PointCloud::Ptr cloud_; + pcl::PointCloud::Ptr cloud_; pcl::PointIndicesPtr indices_; void @@ -34,13 +34,13 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { {} private: - pcl::PointCloud::Ptr + pcl::PointCloud::Ptr generateSyntheticEdgeDetectionCloud() { - auto organized_test_cloud = pcl::make_shared>( + auto organized_test_cloud = pcl::make_shared>( OUTER_SQUARE_EDGE_LENGTH, OUTER_SQUARE_EDGE_LENGTH); - // Draw a smaller red square in front of a larger green square both centered on the + // Draw a smaller square in front of a larger square both centered on the // view axis to generate synthetic occluding and occluded edges based on depth // discontinuity between neighboring pixels. The base depth and resolution are // arbitrary and useful for visualizing the cloud. The discontinuity of the @@ -55,8 +55,6 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { const auto inner_square_ctr = INNER_SQUARE_EDGE_LENGTH / 2; auto depth = SYNTHETIC_CLOUD_BASE_DEPTH; - auto r = 0; - auto g = 255; // If pixels correspond to smaller box, then set depth and color appropriately if (col > outer_square_ctr - inner_square_ctr && @@ -64,18 +62,12 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { if (row > outer_square_ctr - inner_square_ctr && row < outer_square_ctr + inner_square_ctr) { depth = SYNTHETIC_CLOUD_BASE_DEPTH - SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY; - r = 255; - g = 0; } } organized_test_cloud->at(col, row).x = x * SYNTHETIC_CLOUD_RESOLUTION; organized_test_cloud->at(col, row).y = y * SYNTHETIC_CLOUD_RESOLUTION; organized_test_cloud->at(col, row).z = depth; - organized_test_cloud->at(col, row).r = r; - organized_test_cloud->at(col, row).g = g; - organized_test_cloud->at(col, row).b = 0; - organized_test_cloud->at(col, row).a = 255; } } @@ -108,7 +100,7 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) const int EXPECTED_OCCLUDING_EDGE_POINTS = INNER_SQUARE_EDGE_LENGTH * 4 - 8; const int EXPECTED_OCCLUDED_EDGE_POINTS = INNER_SQUARE_EDGE_LENGTH * 4; - auto oed = pcl::OrganizedEdgeFromRGB(); + auto oed = pcl::OrganizedEdgeBase(); auto labels = pcl::PointCloud(); auto label_indices = std::vector(); From d1806ca065842ed469a718070c9165b5909bd6f3 Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Thu, 23 Jul 2020 22:45:14 +1200 Subject: [PATCH 10/20] Use correct pcl include Remove unused TearDown method in gtest fixture Make depth discontinuity threshold dependent on cloud parameters in order to match logic in detection class --- test/features/test_organized_edge_detection.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index dc676803594..db25c20d09f 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -8,9 +8,9 @@ */ #include -#include #include #include +#include namespace { class OrganizedPlaneDetectionTestFixture : public ::testing::Test { @@ -29,9 +29,6 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { { cloud_ = generateSyntheticEdgeDetectionCloud(); } - void - TearDown() override - {} private: pcl::PointCloud::Ptr @@ -90,7 +87,16 @@ this and similar bugs. TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) { const auto MAX_SEARCH_NEIGHBORS = 50; - const auto DEPTH_DISCONTINUITY_THRESHOLD = SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY / 2.1f; + + // The depth discontinuity check to determine whether an edge exists is linearly + // dependent on the depth of the points in the cloud (not a fixed distance). The + // algorithm iterates through each point in the cloud and finding the neighboring + // point with largest discontinuity value. That value is compared against a threshold + // multiplied by the actual depth value of the point. Therefore: + // abs(SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY) must be greater than + // DEPTH_DISCONTINUITY_THRESHOLD * abs(SYNTHETIC_CLOUD_BASE_DEPTH) + const auto DEPTH_DISCONTINUITY_THRESHOLD = + SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY / (SYNTHETIC_CLOUD_BASE_DEPTH * 1.1f); // The expected number of occluded edge points is the number of pixels along the // perimeter of the inner square, subject to certain conditions including that the From 0d3646bdb1a259751ac183a453ebb4dc64029d4b Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Fri, 24 Jul 2020 11:26:31 +1200 Subject: [PATCH 11/20] Added explanation of how depth discontinuity threshold functions to doxygen comments of getter / setter of threshold --- features/include/pcl/features/organized_edge_detection.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/features/include/pcl/features/organized_edge_detection.h b/features/include/pcl/features/organized_edge_detection.h index 5551640ec5e..14cce1bdc17 100644 --- a/features/include/pcl/features/organized_edge_detection.h +++ b/features/include/pcl/features/organized_edge_detection.h @@ -93,14 +93,18 @@ namespace pcl void compute (pcl::PointCloud& labels, std::vector& label_indices) const; - /** \brief Set the tolerance in meters for difference in depth values between neighboring points. */ + /** \brief Set the tolerance in meters for difference in depth values between neighboring points. + * (The value is set for 1 meter and is adapted with respect to depth value linearly. + * (e.g. 2.0*th_depth_discon_ in 2 meter depth)) */ inline void setDepthDisconThreshold (const float th) { th_depth_discon_ = th; } - /** \brief Get the tolerance in meters for difference in depth values between neighboring points. */ + /** \brief Get the tolerance in meters for difference in depth values between neighboring points. + * (The value is set for 1 meter and is adapted with respect to depth value linearly. + * (e.g. 2.0*th_depth_discon_ in 2 meter depth)) */ inline float getDepthDisconThreshold () const { From f350767959c6ed5072db77c562fb9eb654f5d100 Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Fri, 24 Jul 2020 12:38:57 +1200 Subject: [PATCH 12/20] Fix bug in size of generated cloud and expected number of edge points found --- test/features/test_organized_edge_detection.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index db25c20d09f..b40b10575eb 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -54,9 +54,9 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { auto depth = SYNTHETIC_CLOUD_BASE_DEPTH; // If pixels correspond to smaller box, then set depth and color appropriately - if (col > outer_square_ctr - inner_square_ctr && + if (col >= outer_square_ctr - inner_square_ctr && col < outer_square_ctr + inner_square_ctr) { - if (row > outer_square_ctr - inner_square_ctr && + if (row >= outer_square_ctr - inner_square_ctr && row < outer_square_ctr + inner_square_ctr) { depth = SYNTHETIC_CLOUD_BASE_DEPTH - SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY; } @@ -98,13 +98,8 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) const auto DEPTH_DISCONTINUITY_THRESHOLD = SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY / (SYNTHETIC_CLOUD_BASE_DEPTH * 1.1f); - // The expected number of occluded edge points is the number of pixels along the - // perimeter of the inner square, subject to certain conditions including that the - // inner square edge length is an even number. The expected number of occluding edge - // points is similar, but as empirically determined to be 8 less than the number - // of perimeter points. - const int EXPECTED_OCCLUDING_EDGE_POINTS = INNER_SQUARE_EDGE_LENGTH * 4 - 8; - const int EXPECTED_OCCLUDED_EDGE_POINTS = INNER_SQUARE_EDGE_LENGTH * 4; + const int EXPECTED_OCCLUDING_EDGE_POINTS = (INNER_SQUARE_EDGE_LENGTH - 1) * 4; + const int EXPECTED_OCCLUDED_EDGE_POINTS = (INNER_SQUARE_EDGE_LENGTH + 1) * 4; auto oed = pcl::OrganizedEdgeBase(); auto labels = pcl::PointCloud(); From edcc4ce2d86639e7550ea156875bc9e2b2adea49 Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Mon, 27 Jul 2020 15:44:01 +1200 Subject: [PATCH 13/20] Record occluding and occluded indices when generating cloud and compare to edges found by algorithm Changed max search neighbors to 8 Cleanup square geometry logic for readability --- .../test_organized_edge_detection.cpp | 67 ++++++++++++++----- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index b40b10575eb..4d15258cd64 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -22,7 +22,8 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { const float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; pcl::PointCloud::Ptr cloud_; - pcl::PointIndicesPtr indices_; + pcl::PointIndices small_outer_perimeter_; + pcl::PointIndices large_inner_perimeter_; void SetUp() override @@ -37,28 +38,58 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { auto organized_test_cloud = pcl::make_shared>( OUTER_SQUARE_EDGE_LENGTH, OUTER_SQUARE_EDGE_LENGTH); + auto occluded = std::set{}; + // Draw a smaller square in front of a larger square both centered on the // view axis to generate synthetic occluding and occluded edges based on depth // discontinuity between neighboring pixels. The base depth and resolution are // arbitrary and useful for visualizing the cloud. The discontinuity of the // generated cloud must be greater than the threshold set when running the // organized edge detection algorithm. + const auto outer_square_ctr = OUTER_SQUARE_EDGE_LENGTH / 2; + const auto inner_square_ctr = INNER_SQUARE_EDGE_LENGTH / 2; + const auto left_col = outer_square_ctr - inner_square_ctr; + const auto right_col = outer_square_ctr + inner_square_ctr; + const auto top_row = outer_square_ctr - inner_square_ctr; + const auto bottom_row = outer_square_ctr + inner_square_ctr; + for (auto row = 0; row < OUTER_SQUARE_EDGE_LENGTH; ++row) { for (auto col = 0; col < OUTER_SQUARE_EDGE_LENGTH; ++col) { - float x = col - (OUTER_SQUARE_EDGE_LENGTH / 2); - float y = row - (OUTER_SQUARE_EDGE_LENGTH / 2); - - const auto outer_square_ctr = OUTER_SQUARE_EDGE_LENGTH / 2; - const auto inner_square_ctr = INNER_SQUARE_EDGE_LENGTH / 2; + float x = col - outer_square_ctr; + float y = row - inner_square_ctr; auto depth = SYNTHETIC_CLOUD_BASE_DEPTH; // If pixels correspond to smaller box, then set depth and color appropriately - if (col >= outer_square_ctr - inner_square_ctr && - col < outer_square_ctr + inner_square_ctr) { - if (row >= outer_square_ctr - inner_square_ctr && - row < outer_square_ctr + inner_square_ctr) { + if (col >= left_col && col < right_col) { + if (row >= top_row && row < bottom_row) { + depth = SYNTHETIC_CLOUD_BASE_DEPTH - SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY; + + // Record outer perimeter points of small inner square that correspond to + // the occluding edge points + if ((col == outer_square_ctr - inner_square_ctr || + col == outer_square_ctr + inner_square_ctr - 1) || + (row == outer_square_ctr - inner_square_ctr || + row == outer_square_ctr + inner_square_ctr - 1)) { + small_outer_perimeter_.indices.push_back( + row * organized_test_cloud->width + col); + } + } + } + + // Record inner perimeter points of large outer square that correspond to the + // occluded edge points + if (row == top_row - 1 || row == bottom_row) { + if (col >= left_col - 1 && col <= right_col) { + large_inner_perimeter_.indices.push_back(row * organized_test_cloud->width + + col); + } + } + else if (row >= top_row && row < bottom_row) { + if (col == left_col - 1 || col == right_col) { + large_inner_perimeter_.indices.push_back(row * organized_test_cloud->width + + col); } } @@ -86,7 +117,7 @@ this and similar bugs. */ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) { - const auto MAX_SEARCH_NEIGHBORS = 50; + const auto MAX_SEARCH_NEIGHBORS = 8; // The depth discontinuity check to determine whether an edge exists is linearly // dependent on the depth of the points in the cloud (not a fixed distance). The @@ -98,9 +129,6 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) const auto DEPTH_DISCONTINUITY_THRESHOLD = SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY / (SYNTHETIC_CLOUD_BASE_DEPTH * 1.1f); - const int EXPECTED_OCCLUDING_EDGE_POINTS = (INNER_SQUARE_EDGE_LENGTH - 1) * 4; - const int EXPECTED_OCCLUDED_EDGE_POINTS = (INNER_SQUARE_EDGE_LENGTH + 1) * 4; - auto oed = pcl::OrganizedEdgeBase(); auto labels = pcl::PointCloud(); auto label_indices = std::vector(); @@ -111,8 +139,15 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) oed.setMaxSearchNeighbors(MAX_SEARCH_NEIGHBORS); oed.compute(labels, label_indices); - EXPECT_EQ(EXPECTED_OCCLUDING_EDGE_POINTS, label_indices[1].indices.size()); - EXPECT_EQ(EXPECTED_OCCLUDED_EDGE_POINTS, label_indices[2].indices.size()); + EXPECT_EQ(label_indices[1].indices.size(), small_outer_perimeter_.indices.size()); + for (auto i = 0; i < small_outer_perimeter_.indices.size(); ++i) { + EXPECT_EQ(label_indices[1].indices[i], small_outer_perimeter_.indices[i]); + } + + EXPECT_EQ(label_indices[2].indices.size(), large_inner_perimeter_.indices.size()); + for (auto i = 0; i < large_inner_perimeter_.indices.size(); ++i) { + EXPECT_EQ(label_indices[2].indices[i], large_inner_perimeter_.indices[i]); + } } /* ---[ */ From da455ca4dcef4be7da9a0f61107db15d5e9db9ea Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Mon, 27 Jul 2020 22:26:04 +1200 Subject: [PATCH 14/20] Update documentation strings for methods related to discontinuity threshold --- .../pcl/features/organized_edge_detection.h | 61 +++++++++---------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/features/include/pcl/features/organized_edge_detection.h b/features/include/pcl/features/organized_edge_detection.h index 14cce1bdc17..faa2c790fab 100644 --- a/features/include/pcl/features/organized_edge_detection.h +++ b/features/include/pcl/features/organized_edge_detection.h @@ -42,9 +42,9 @@ namespace pcl { - /** \brief OrganizedEdgeBase, OrganizedEdgeFromRGB, OrganizedEdgeFromNormals, - * and OrganizedEdgeFromRGBNormals find 3D edges from an organized point - * cloud data. Given an organized point cloud, they will output a PointCloud + /** \brief OrganizedEdgeBase, OrganizedEdgeFromRGB, OrganizedEdgeFromNormals, + * and OrganizedEdgeFromRGBNormals find 3D edges from an organized point + * cloud data. Given an organized point cloud, they will output a PointCloud * of edge labels and a vector of PointIndices. * OrganizedEdgeBase accepts PCL_XYZ_POINT_TYPES and returns EDGELABEL_NAN_BOUNDARY, EDGELABEL_OCCLUDING, and EDGELABEL_OCCLUDED. * OrganizedEdgeFromRGB accepts PCL_RGB_POINT_TYPES and returns EDGELABEL_NAN_BOUNDARY, EDGELABEL_OCCLUDING, EDGELABEL_OCCLUDED, and EDGELABEL_RGB_CANNY. @@ -59,7 +59,7 @@ namespace pcl using PointCloud = pcl::PointCloud; using PointCloudPtr = typename PointCloud::Ptr; using PointCloudConstPtr = typename PointCloud::ConstPtr; - + using PointCloudL = pcl::PointCloud; using PointCloudLPtr = typename PointCloudL::Ptr; using PointCloudLConstPtr = typename PointCloudL::ConstPtr; @@ -81,7 +81,7 @@ namespace pcl } /** \brief Destructor for OrganizedEdgeBase */ - + ~OrganizedEdgeBase () { } @@ -92,19 +92,17 @@ namespace pcl */ void compute (pcl::PointCloud& labels, std::vector& label_indices) const; - - /** \brief Set the tolerance in meters for difference in depth values between neighboring points. - * (The value is set for 1 meter and is adapted with respect to depth value linearly. - * (e.g. 2.0*th_depth_discon_ in 2 meter depth)) */ + + /** \brief Set the tolerance in meters for the relative difference in depth values between neighboring points. + * e.g. If a point has a depth (z) value of 2.0 meters, a neighboring point is discontinuous if its depth differs by > 2.0 * th_depth_discon_. */ inline void setDepthDisconThreshold (const float th) { th_depth_discon_ = th; } - /** \brief Get the tolerance in meters for difference in depth values between neighboring points. - * (The value is set for 1 meter and is adapted with respect to depth value linearly. - * (e.g. 2.0*th_depth_discon_ in 2 meter depth)) */ + /** \brief Get the tolerance in meters for the relative difference in depth values between neighboring points. + * e.g. If a point has a depth (z) value of 2.0 meters, a neighboring point is discontinuous if its depth differs by > 2.0 * th_depth_discon_. */ inline float getDepthDisconThreshold () const { @@ -138,7 +136,7 @@ namespace pcl { return detecting_edge_types_; } - + enum {EDGELABEL_NAN_BOUNDARY=1, EDGELABEL_OCCLUDING=2, EDGELABEL_OCCLUDED=4, EDGELABEL_HIGH_CURVATURE=8, EDGELABEL_RGB_CANNY=16}; static const int num_of_edgetype_ = 5; @@ -148,14 +146,14 @@ namespace pcl */ void extractEdges (pcl::PointCloud& labels) const; - + /** \brief Assign point indices for each edge label * \param[out] labels a PointCloud of edge labels * \param[out] label_indices a vector of PointIndices corresponding to each edge label */ void assignLabelIndices (pcl::PointCloud& labels, std::vector& label_indices) const; - + struct Neighbor { Neighbor (int dx, int dy, int didx) @@ -163,16 +161,15 @@ namespace pcl , d_y (dy) , d_index (didx) {} - + int d_x; int d_y; int d_index; // = dy * width + dx: pre-calculated }; - /** \brief The tolerance in meters for difference in depth values between neighboring points - * (The value is set for 1 meter and is adapted with respect to depth value linearly. - * (e.g. 2.0*th_depth_discon_ in 2 meter depth)) - */ + /** \brief The tolerance in meters for the relative difference in depth values between neighboring points + * (The default value is set for .02 meters and is adapted with respect to depth value linearly. + * e.g. If a point has a depth (z) value of 2.0 meters, a neighboring point is discontinuous if its depth differs by > 2.0 * th_depth_discon_. */ float th_depth_discon_; /** \brief The max search distance for deciding occluding and occluded edges */ @@ -188,7 +185,7 @@ namespace pcl using PointCloud = pcl::PointCloud; using PointCloudPtr = typename PointCloud::Ptr; using PointCloudConstPtr = typename PointCloud::ConstPtr; - + using PointCloudL = pcl::PointCloud; using PointCloudLPtr = typename PointCloudL::Ptr; using PointCloudLConstPtr = typename PointCloudL::ConstPtr; @@ -214,7 +211,7 @@ namespace pcl } /** \brief Destructor for OrganizedEdgeFromRGB */ - + ~OrganizedEdgeFromRGB () { } @@ -225,7 +222,7 @@ namespace pcl */ void compute (pcl::PointCloud& labels, std::vector& label_indices) const; - + /** \brief Set the low threshold value for RGB Canny edge detection */ inline void setRGBCannyLowThreshold (const float th) @@ -274,7 +271,7 @@ namespace pcl using PointCloud = pcl::PointCloud; using PointCloudPtr = typename PointCloud::Ptr; using PointCloudConstPtr = typename PointCloud::ConstPtr; - + using PointCloudN = pcl::PointCloud; using PointCloudNPtr = typename PointCloudN::Ptr; using PointCloudNConstPtr = typename PointCloudN::ConstPtr; @@ -295,7 +292,7 @@ namespace pcl using OrganizedEdgeBase::EDGELABEL_HIGH_CURVATURE; /** \brief Constructor for OrganizedEdgeFromNormals */ - OrganizedEdgeFromNormals () + OrganizedEdgeFromNormals () : OrganizedEdgeBase () , normals_ () , th_hc_canny_low_ (0.4f) @@ -305,7 +302,7 @@ namespace pcl } /** \brief Destructor for OrganizedEdgeFromNormals */ - + ~OrganizedEdgeFromNormals () { } @@ -321,7 +318,7 @@ namespace pcl * \param[in] normals the input normal cloud */ inline void - setInputNormals (const PointCloudNConstPtr &normals) + setInputNormals (const PointCloudNConstPtr &normals) { normals_ = normals; } @@ -360,7 +357,7 @@ namespace pcl { return (th_hc_canny_high_); } - + protected: /** \brief Perform the 3D edge detection (edges from depth discontinuities and high curvature regions) * \param[out] labels a PointCloud of edge labels @@ -384,7 +381,7 @@ namespace pcl using PointCloud = pcl::PointCloud; using PointCloudPtr = typename PointCloud::Ptr; using PointCloudConstPtr = typename PointCloud::ConstPtr; - + using PointCloudN = pcl::PointCloud; using PointCloudNPtr = typename PointCloudN::Ptr; using PointCloudNConstPtr = typename PointCloudN::ConstPtr; @@ -404,9 +401,9 @@ namespace pcl using OrganizedEdgeBase::EDGELABEL_OCCLUDED; using OrganizedEdgeBase::EDGELABEL_HIGH_CURVATURE; using OrganizedEdgeBase::EDGELABEL_RGB_CANNY; - + /** \brief Constructor for OrganizedEdgeFromRGBNormals */ - OrganizedEdgeFromRGBNormals () + OrganizedEdgeFromRGBNormals () : OrganizedEdgeFromRGB () , OrganizedEdgeFromNormals () { @@ -414,7 +411,7 @@ namespace pcl } /** \brief Destructor for OrganizedEdgeFromRGBNormals */ - + ~OrganizedEdgeFromRGBNormals () { } From d40c4a9fb552e1e60892d58caa842c8643643369 Mon Sep 17 00:00:00 2001 From: Matt Middleton Date: Mon, 27 Jul 2020 22:35:41 +1200 Subject: [PATCH 15/20] Use std::set to store indices and change / simplify test accordingly Simply cloud indices generation loop conditions Adjust variable names for clarity Use defined constants --- .../test_organized_edge_detection.cpp | 51 ++++++++----------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index 4d15258cd64..b690523421b 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -22,8 +22,8 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { const float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; pcl::PointCloud::Ptr cloud_; - pcl::PointIndices small_outer_perimeter_; - pcl::PointIndices large_inner_perimeter_; + std::set outer_perimeter_; + std::set inner_perimeter_; void SetUp() override @@ -66,31 +66,22 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { depth = SYNTHETIC_CLOUD_BASE_DEPTH - SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY; - // Record outer perimeter points of small inner square that correspond to - // the occluding edge points - if ((col == outer_square_ctr - inner_square_ctr || - col == outer_square_ctr + inner_square_ctr - 1) || - (row == outer_square_ctr - inner_square_ctr || - row == outer_square_ctr + inner_square_ctr - 1)) { - small_outer_perimeter_.indices.push_back( - row * organized_test_cloud->width + col); + // Record indices of the outer perimeter points of small inner square that + // correspond to the occluding edge points + if ((col == left_col || col == right_col - 1) || + (row == top_row || row == bottom_row - 1)) { + outer_perimeter_.insert(row * organized_test_cloud->width + col); } } } - // Record inner perimeter points of large outer square that correspond to the - // occluded edge points - if (row == top_row - 1 || row == bottom_row) { - if (col >= left_col - 1 && col <= right_col) { - large_inner_perimeter_.indices.push_back(row * organized_test_cloud->width + - col); - } - } - else if (row >= top_row && row < bottom_row) { - if (col == left_col - 1 || col == right_col) { - large_inner_perimeter_.indices.push_back(row * organized_test_cloud->width + - col); - } + // Record indices of the inner perimeter points of large outer square that + // correspond to the occluded edge points + if (((row == top_row - 1 || row == bottom_row) && + (col >= left_col - 1 && col <= right_col)) || + ((row >= top_row && row < bottom_row) && + (col == left_col - 1 || col == right_col))) { + inner_perimeter_.insert(row * organized_test_cloud->width + col); } organized_test_cloud->at(col, row).x = x * SYNTHETIC_CLOUD_RESOLUTION; @@ -139,15 +130,13 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) oed.setMaxSearchNeighbors(MAX_SEARCH_NEIGHBORS); oed.compute(labels, label_indices); - EXPECT_EQ(label_indices[1].indices.size(), small_outer_perimeter_.indices.size()); - for (auto i = 0; i < small_outer_perimeter_.indices.size(); ++i) { - EXPECT_EQ(label_indices[1].indices[i], small_outer_perimeter_.indices[i]); - } + auto occluding_indices = + std::set(label_indices[1].indices.begin(), label_indices[1].indices.end()); + EXPECT_EQ(occluding_indices, outer_perimeter_); - EXPECT_EQ(label_indices[2].indices.size(), large_inner_perimeter_.indices.size()); - for (auto i = 0; i < large_inner_perimeter_.indices.size(); ++i) { - EXPECT_EQ(label_indices[2].indices[i], large_inner_perimeter_.indices[i]); - } + auto occluded_indices = + std::set(label_indices[2].indices.begin(), label_indices[2].indices.end()); + EXPECT_EQ(occluded_indices, inner_perimeter_); } /* ---[ */ From 014d8c014684170b5a950659ed9aadd90815a197 Mon Sep 17 00:00:00 2001 From: Kunal Tyagi Date: Fri, 7 Aug 2020 02:27:29 +0900 Subject: [PATCH 16/20] Addressing review comments --- test/features/test_organized_edge_detection.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index b690523421b..afaf98aedec 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -22,8 +22,8 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { const float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; pcl::PointCloud::Ptr cloud_; - std::set outer_perimeter_; - std::set inner_perimeter_; + std::set outer_perimeter_; + std::set inner_perimeter_; void SetUp() override @@ -38,8 +38,6 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { auto organized_test_cloud = pcl::make_shared>( OUTER_SQUARE_EDGE_LENGTH, OUTER_SQUARE_EDGE_LENGTH); - auto occluded = std::set{}; - // Draw a smaller square in front of a larger square both centered on the // view axis to generate synthetic occluding and occluded edges based on depth // discontinuity between neighboring pixels. The base depth and resolution are @@ -131,11 +129,11 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) oed.compute(labels, label_indices); auto occluding_indices = - std::set(label_indices[1].indices.begin(), label_indices[1].indices.end()); + std::set(label_indices[1].indices.begin(), label_indices[1].indices.end()); EXPECT_EQ(occluding_indices, outer_perimeter_); auto occluded_indices = - std::set(label_indices[2].indices.begin(), label_indices[2].indices.end()); + std::set(label_indices[2].indices.begin(), label_indices[2].indices.end()); EXPECT_EQ(occluded_indices, inner_perimeter_); } From a9bd27398605b4c5a214e61539f33ec37f3e7491 Mon Sep 17 00:00:00 2001 From: Kunal Tyagi Date: Fri, 7 Aug 2020 02:30:46 +0900 Subject: [PATCH 17/20] Spell corrections --- features/include/pcl/features/organized_edge_detection.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/include/pcl/features/organized_edge_detection.h b/features/include/pcl/features/organized_edge_detection.h index faa2c790fab..dd889caa588 100644 --- a/features/include/pcl/features/organized_edge_detection.h +++ b/features/include/pcl/features/organized_edge_detection.h @@ -94,7 +94,7 @@ namespace pcl compute (pcl::PointCloud& labels, std::vector& label_indices) const; /** \brief Set the tolerance in meters for the relative difference in depth values between neighboring points. - * e.g. If a point has a depth (z) value of 2.0 meters, a neighboring point is discontinuous if its depth differs by > 2.0 * th_depth_discon_. */ + * e.g. If a point has a depth (z) value of 2.0 meters, a neighboring point is discontinuous if its depth differs by > 2.0 * th. */ inline void setDepthDisconThreshold (const float th) { @@ -102,7 +102,7 @@ namespace pcl } /** \brief Get the tolerance in meters for the relative difference in depth values between neighboring points. - * e.g. If a point has a depth (z) value of 2.0 meters, a neighboring point is discontinuous if its depth differs by > 2.0 * th_depth_discon_. */ + * e.g. If a point has a depth (z) value of 2.0 meters, a neighboring point is discontinuous if its depth differs by > 2.0 * th. */ inline float getDepthDisconThreshold () const { @@ -169,7 +169,7 @@ namespace pcl /** \brief The tolerance in meters for the relative difference in depth values between neighboring points * (The default value is set for .02 meters and is adapted with respect to depth value linearly. - * e.g. If a point has a depth (z) value of 2.0 meters, a neighboring point is discontinuous if its depth differs by > 2.0 * th_depth_discon_. */ + * e.g. If a point has a depth (z) value of 2.0 meters, a neighboring point is discontinuous if its depth differs by > 2.0 * th. */ float th_depth_discon_; /** \brief The max search distance for deciding occluding and occluded edges */ From 48a2df1c573b26dc082348e9f37de319736a0bc5 Mon Sep 17 00:00:00 2001 From: Kunal Tyagi Date: Fri, 7 Aug 2020 05:24:35 +0900 Subject: [PATCH 18/20] Const all the things --- .../test_organized_edge_detection.cpp | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index afaf98aedec..61c1a3503a6 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -15,11 +15,11 @@ namespace { class OrganizedPlaneDetectionTestFixture : public ::testing::Test { protected: - const int INNER_SQUARE_EDGE_LENGTH = 50; - const int OUTER_SQUARE_EDGE_LENGTH = INNER_SQUARE_EDGE_LENGTH * 2; - const float SYNTHETIC_CLOUD_BASE_DEPTH = 2.0; - const float SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY = .02f; - const float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; + constexpr int INNER_SQUARE_EDGE_LENGTH = 50; + constexpr int OUTER_SQUARE_EDGE_LENGTH = INNER_SQUARE_EDGE_LENGTH * 2; + constexpr float SYNTHETIC_CLOUD_BASE_DEPTH = 2.0; + constexpr float SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY = .02f; + constexpr float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; pcl::PointCloud::Ptr cloud_; std::set outer_perimeter_; @@ -44,17 +44,17 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { // arbitrary and useful for visualizing the cloud. The discontinuity of the // generated cloud must be greater than the threshold set when running the // organized edge detection algorithm. - const auto outer_square_ctr = OUTER_SQUARE_EDGE_LENGTH / 2; - const auto inner_square_ctr = INNER_SQUARE_EDGE_LENGTH / 2; - const auto left_col = outer_square_ctr - inner_square_ctr; - const auto right_col = outer_square_ctr + inner_square_ctr; - const auto top_row = outer_square_ctr - inner_square_ctr; - const auto bottom_row = outer_square_ctr + inner_square_ctr; + constexpr auto outer_square_ctr = OUTER_SQUARE_EDGE_LENGTH / 2; + constexpr auto inner_square_ctr = INNER_SQUARE_EDGE_LENGTH / 2; + constexpr auto left_col = outer_square_ctr - inner_square_ctr; + constexpr auto right_col = outer_square_ctr + inner_square_ctr; + constexpr auto top_row = outer_square_ctr - inner_square_ctr; + constexpr auto bottom_row = outer_square_ctr + inner_square_ctr; for (auto row = 0; row < OUTER_SQUARE_EDGE_LENGTH; ++row) { for (auto col = 0; col < OUTER_SQUARE_EDGE_LENGTH; ++col) { - float x = col - outer_square_ctr; - float y = row - inner_square_ctr; + const float x = col - outer_square_ctr; + const float y = row - inner_square_ctr; auto depth = SYNTHETIC_CLOUD_BASE_DEPTH; @@ -106,7 +106,7 @@ this and similar bugs. */ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) { - const auto MAX_SEARCH_NEIGHBORS = 8; + constexpr auto MAX_SEARCH_NEIGHBORS = 8; // The depth discontinuity check to determine whether an edge exists is linearly // dependent on the depth of the points in the cloud (not a fixed distance). The @@ -115,7 +115,7 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) // multiplied by the actual depth value of the point. Therefore: // abs(SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY) must be greater than // DEPTH_DISCONTINUITY_THRESHOLD * abs(SYNTHETIC_CLOUD_BASE_DEPTH) - const auto DEPTH_DISCONTINUITY_THRESHOLD = + constexpr auto DEPTH_DISCONTINUITY_THRESHOLD = SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY / (SYNTHETIC_CLOUD_BASE_DEPTH * 1.1f); auto oed = pcl::OrganizedEdgeBase(); @@ -128,11 +128,11 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) oed.setMaxSearchNeighbors(MAX_SEARCH_NEIGHBORS); oed.compute(labels, label_indices); - auto occluding_indices = + const auto occluding_indices = std::set(label_indices[1].indices.begin(), label_indices[1].indices.end()); EXPECT_EQ(occluding_indices, outer_perimeter_); - auto occluded_indices = + const auto occluded_indices = std::set(label_indices[2].indices.begin(), label_indices[2].indices.end()); EXPECT_EQ(occluded_indices, inner_perimeter_); } From 138b17951f9d30164bd1ef9b0206c59363d50273 Mon Sep 17 00:00:00 2001 From: Kunal Tyagi Date: Fri, 7 Aug 2020 05:27:46 +0900 Subject: [PATCH 19/20] Fixes and fixes --- .../test_organized_edge_detection.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index 61c1a3503a6..09f46e73b04 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -15,15 +15,15 @@ namespace { class OrganizedPlaneDetectionTestFixture : public ::testing::Test { protected: - constexpr int INNER_SQUARE_EDGE_LENGTH = 50; - constexpr int OUTER_SQUARE_EDGE_LENGTH = INNER_SQUARE_EDGE_LENGTH * 2; - constexpr float SYNTHETIC_CLOUD_BASE_DEPTH = 2.0; - constexpr float SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY = .02f; - constexpr float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; + static constexpr int INNER_SQUARE_EDGE_LENGTH = 50; + static constexpr int OUTER_SQUARE_EDGE_LENGTH = INNER_SQUARE_EDGE_LENGTH * 2; + static constexpr float SYNTHETIC_CLOUD_BASE_DEPTH = 2.0; + static constexpr float SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY = .02f; + static constexpr float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; pcl::PointCloud::Ptr cloud_; - std::set outer_perimeter_; - std::set inner_perimeter_; + std::set outer_perimeter_; + std::set inner_perimeter_; void SetUp() override @@ -128,12 +128,12 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) oed.setMaxSearchNeighbors(MAX_SEARCH_NEIGHBORS); oed.compute(labels, label_indices); - const auto occluding_indices = - std::set(label_indices[1].indices.begin(), label_indices[1].indices.end()); + const auto occluding_indices = std::set( + label_indices[1].indices.begin(), label_indices[1].indices.end()); EXPECT_EQ(occluding_indices, outer_perimeter_); - const auto occluded_indices = - std::set(label_indices[2].indices.begin(), label_indices[2].indices.end()); + const auto occluded_indices = std::set(label_indices[2].indices.begin(), + label_indices[2].indices.end()); EXPECT_EQ(occluded_indices, inner_perimeter_); } From 3bd2de28f2f75359c7a1d751b9509d7e484f5947 Mon Sep 17 00:00:00 2001 From: Kunal Tyagi Date: Fri, 7 Aug 2020 07:49:13 +0900 Subject: [PATCH 20/20] Removing constexpr for the CI --- .../test_organized_edge_detection.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/features/test_organized_edge_detection.cpp b/test/features/test_organized_edge_detection.cpp index 09f46e73b04..6fc0c686185 100644 --- a/test/features/test_organized_edge_detection.cpp +++ b/test/features/test_organized_edge_detection.cpp @@ -15,11 +15,11 @@ namespace { class OrganizedPlaneDetectionTestFixture : public ::testing::Test { protected: - static constexpr int INNER_SQUARE_EDGE_LENGTH = 50; - static constexpr int OUTER_SQUARE_EDGE_LENGTH = INNER_SQUARE_EDGE_LENGTH * 2; - static constexpr float SYNTHETIC_CLOUD_BASE_DEPTH = 2.0; - static constexpr float SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY = .02f; - static constexpr float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; + const int INNER_SQUARE_EDGE_LENGTH = 50; + const int OUTER_SQUARE_EDGE_LENGTH = INNER_SQUARE_EDGE_LENGTH * 2; + const float SYNTHETIC_CLOUD_BASE_DEPTH = 2.0; + const float SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY = .02f; + const float SYNTHETIC_CLOUD_RESOLUTION = 0.01f; pcl::PointCloud::Ptr cloud_; std::set outer_perimeter_; @@ -44,12 +44,12 @@ class OrganizedPlaneDetectionTestFixture : public ::testing::Test { // arbitrary and useful for visualizing the cloud. The discontinuity of the // generated cloud must be greater than the threshold set when running the // organized edge detection algorithm. - constexpr auto outer_square_ctr = OUTER_SQUARE_EDGE_LENGTH / 2; - constexpr auto inner_square_ctr = INNER_SQUARE_EDGE_LENGTH / 2; - constexpr auto left_col = outer_square_ctr - inner_square_ctr; - constexpr auto right_col = outer_square_ctr + inner_square_ctr; - constexpr auto top_row = outer_square_ctr - inner_square_ctr; - constexpr auto bottom_row = outer_square_ctr + inner_square_ctr; + const auto outer_square_ctr = OUTER_SQUARE_EDGE_LENGTH / 2; + const auto inner_square_ctr = INNER_SQUARE_EDGE_LENGTH / 2; + const auto left_col = outer_square_ctr - inner_square_ctr; + const auto right_col = outer_square_ctr + inner_square_ctr; + const auto top_row = outer_square_ctr - inner_square_ctr; + const auto bottom_row = outer_square_ctr + inner_square_ctr; for (auto row = 0; row < OUTER_SQUARE_EDGE_LENGTH; ++row) { for (auto col = 0; col < OUTER_SQUARE_EDGE_LENGTH; ++col) { @@ -115,7 +115,7 @@ TEST_F(OrganizedPlaneDetectionTestFixture, OccludedAndOccludingEdges) // multiplied by the actual depth value of the point. Therefore: // abs(SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY) must be greater than // DEPTH_DISCONTINUITY_THRESHOLD * abs(SYNTHETIC_CLOUD_BASE_DEPTH) - constexpr auto DEPTH_DISCONTINUITY_THRESHOLD = + const auto DEPTH_DISCONTINUITY_THRESHOLD = SYNTHETIC_CLOUD_DEPTH_DISCONTINUITY / (SYNTHETIC_CLOUD_BASE_DEPTH * 1.1f); auto oed = pcl::OrganizedEdgeBase();