From 3f37fa504f3a7f0976bc43fa444ac4530ba19fee Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 17 Apr 2018 12:23:39 +0200 Subject: [PATCH] WIP: better API of feature generators + eigen analysis --- .../CGAL/Classification/Feature/Eigenvalue.h | 2 - .../include/CGAL/Classification/Feature/Hsv.h | 2 - .../include/CGAL/Classification/Feature_set.h | 41 ++- .../Classification/Local_eigen_analysis.h | 251 ++++++++++------- .../Classification/Mesh_feature_generator.h | 146 ++++------ .../Point_set_feature_generator.h | 257 +++++++----------- .../Classification/Cluster_classification.cpp | 70 +++-- .../Classification/Cluster_classification.h | 6 +- .../Point_set_item_classification.cpp | 48 ++-- .../Surface_mesh_item_classification.cpp | 10 + 10 files changed, 423 insertions(+), 410 deletions(-) diff --git a/Classification/include/CGAL/Classification/Feature/Eigenvalue.h b/Classification/include/CGAL/Classification/Feature/Eigenvalue.h index dcb009b19ed..55f53ca9b2f 100644 --- a/Classification/include/CGAL/Classification/Feature/Eigenvalue.h +++ b/Classification/include/CGAL/Classification/Feature/Eigenvalue.h @@ -48,8 +48,6 @@ public: std::size_t idx) : eigen (eigen), m_idx (idx) { - std::cerr << "[" << idx << "]" << std::endl; - std::cerr << "[" << m_idx << "]" << std::endl; std::ostringstream oss; oss << "eigenvalue" << (idx+1); this->set_name (oss.str()); diff --git a/Classification/include/CGAL/Classification/Feature/Hsv.h b/Classification/include/CGAL/Classification/Feature/Hsv.h index 9394b0e43fe..5b7ae2e4d6e 100644 --- a/Classification/include/CGAL/Classification/Feature/Hsv.h +++ b/Classification/include/CGAL/Classification/Feature/Hsv.h @@ -138,8 +138,6 @@ public: * (c[std::size_t(channel)] - mean) / (2. * sd * sd))); } #endif - std::cerr << "[" << channel << " / " << mean << " / " << sd << "]" << std::endl; - std::cerr << "[" << m_channel << " / " << m_mean << " / " << m_sd << "]" << std::endl; std::ostringstream oss; if (channel == HUE) oss << "hue"; else if (channel == SATURATION) oss << "saturation"; diff --git a/Classification/include/CGAL/Classification/Feature_set.h b/Classification/include/CGAL/Classification/Feature_set.h index 06beefc0ee9..4a4da6a471f 100644 --- a/Classification/include/CGAL/Classification/Feature_set.h +++ b/Classification/include/CGAL/Classification/Feature_set.h @@ -80,6 +80,8 @@ public: #ifdef CGAL_LINKED_WITH_TBB if (m_tasks != NULL) delete m_tasks; + for (std::size_t i = 0; i < m_adders.size(); ++ i) + delete m_adders[i]; #endif } /// \endcond @@ -118,6 +120,31 @@ public: return m_features.back(); } + /// \cond SKIP_IN_MANUAL + template + Feature_handle add_with_scale_id (std::size_t i, T&& ... t) + { +#ifdef CGAL_LINKED_WITH_TBB + if (m_tasks != NULL) + { + m_features.push_back (Feature_handle()); + + Parallel_feature_adder* adder + = new Parallel_feature_adder(i, m_features.back(), std::forward(t)...); + + m_adders.push_back (adder); + m_tasks->run (*adder); + } + else +#endif + { + m_features.push_back (Feature_handle (new Feature(std::forward(t)...))); + m_features.back()->set_name (m_features.back()->name() + "_" + std::to_string(i)); + } + return m_features.back(); + } + /// \end + #if defined(CGAL_LINKED_WITH_TBB) || defined(DOXYGEN_RUNNING) void begin_parallel_additions() { @@ -132,6 +159,7 @@ public: for (std::size_t i = 0; i < m_adders.size(); ++ i) delete m_adders[i]; + m_adders.clear(); } #endif @@ -202,11 +230,18 @@ private: template struct Parallel_feature_adder : Abstract_parallel_feature_adder { - Feature_handle fh; + std::size_t scale; + mutable Feature_handle fh; boost::shared_ptr > args; Parallel_feature_adder (Feature_handle fh, T&& ... t) - : fh (fh) + : scale (std::size_t(-1)), fh (fh) + { + args = boost::make_shared >(std::forward(t)...); + } + + Parallel_feature_adder (std::size_t scale, Feature_handle fh, T&& ... t) + : scale(scale), fh (fh) { args = boost::make_shared >(std::forward(t)...); } @@ -230,6 +265,8 @@ private: void add_feature (Tuple& t, seq) const { fh.attach (new Feature (std::forward(std::get(t))...)); + if (scale != std::size_t(-1)) + fh->set_name (fh->name() + "_" + std::to_string(scale)); } void operator()() const diff --git a/Classification/include/CGAL/Classification/Local_eigen_analysis.h b/Classification/include/CGAL/Classification/Local_eigen_analysis.h index d4e04edb3dc..0c79dd21550 100644 --- a/Classification/include/CGAL/Classification/Local_eigen_analysis.h +++ b/Classification/include/CGAL/Classification/Local_eigen_analysis.h @@ -195,18 +195,22 @@ private: }; - typedef CGAL::cpp11::array float3; - std::vector m_eigenvalues; - std::vector m_sum_eigenvalues; - std::vector m_centroids; - std::vector m_smallest_eigenvectors; + + struct Content + { + std::vector eigenvalues; + std::vector sum_eigenvalues; + std::vector centroids; + std::vector smallest_eigenvectors; #ifdef CGAL_CLASSIFICATION_EIGEN_FULL_STORAGE - std::vector m_middle_eigenvectors; - std::vector m_largest_eigenvectors; + std::vector middle_eigenvectors; + std::vector largest_eigenvectors; #endif - float m_mean_range; + float mean_range; + }; + boost::shared_ptr m_content; // To avoid copies with named constructors public: @@ -214,9 +218,12 @@ public: Local_eigen_analysis () { } /// \endcond + /// \name Named Constructors + /// @{ + /*! - \brief Computes the local eigen analysis of an input range based - on a local neighborhood. + \brief Computes the local eigen analysis of an input point set + based on a local neighborhood. \tparam PointRange model of `ConstRange`. Its iterator type is `RandomAccessIterator` and its value type is the key type of @@ -252,22 +259,24 @@ public: #else typename DiagonalizeTraits = CGAL::Default_diagonalize_traits > #endif - Local_eigen_analysis (const PointRange& input, - PointMap point_map, - const NeighborQuery& neighbor_query, - const ConcurrencyTag& = ConcurrencyTag(), - const DiagonalizeTraits& = DiagonalizeTraits()) + static Local_eigen_analysis create_from_point_set(const PointRange& input, + PointMap point_map, + const NeighborQuery& neighbor_query, + const ConcurrencyTag& = ConcurrencyTag(), + const DiagonalizeTraits& = DiagonalizeTraits()) { - m_eigenvalues.resize (input.size()); - m_sum_eigenvalues.resize (input.size()); - m_centroids.resize (input.size()); - m_smallest_eigenvectors.resize (input.size()); + Local_eigen_analysis out; + out.m_content = boost::make_shared(); + out.m_content->eigenvalues.resize (input.size()); + out.m_content->sum_eigenvalues.resize (input.size()); + out.m_content->centroids.resize (input.size()); + out.m_content->smallest_eigenvectors.resize (input.size()); #ifdef CGAL_CLASSIFICATION_EIGEN_FULL_STORAGE - m_middle_eigenvectors.resize (input.size()); - m_largest_eigenvectors.resize (input.size()); + out.m_content->middle_eigenvectors.resize (input.size()); + out.m_content->largest_eigenvectors.resize (input.size()); #endif - m_mean_range = 0.; + out.m_content->mean_range = 0.; #ifndef CGAL_LINKED_WITH_TBB CGAL_static_assertion_msg (!(boost::is_convertible::value), @@ -277,7 +286,7 @@ public: { tbb::mutex mutex; Compute_eigen_values - f(*this, input, point_map, neighbor_query, m_mean_range, mutex); + f(out, input, point_map, neighbor_query, out.m_content->mean_range, mutex); tbb::parallel_for(tbb::blocked_range(0, input.size ()), f); } else @@ -292,22 +301,38 @@ public: for (std::size_t j = 0; j < neighbors.size(); ++ j) neighbor_points.push_back (get(point_map, *(input.begin()+neighbors[j]))); - m_mean_range += float(CGAL::sqrt (CGAL::squared_distance + out.m_content->mean_range += float(CGAL::sqrt (CGAL::squared_distance (get(point_map, *(input.begin() + i)), get(point_map, *(input.begin() + neighbors.back()))))); - compute + out.compute (i, get(point_map, *(input.begin()+i)), neighbor_points); } } - m_mean_range /= input.size(); - } + out.m_content->mean_range /= input.size(); - // Experimental feature, not used officially - /// \cond SKIP_IN_MANUAL - struct Input_is_clusters { }; - struct Input_is_face_graph { }; + return out; + } + + /*! + \brief Computes the local eigen analysis of an input face graph + based on a local neighborhood. + + \tparam FaceListGraph model of `FaceListGraph`. + \tparam NeighborQuery model of `NeighborQuery` + \tparam ConcurrencyTag enables sequential versus parallel + algorithm. Possible values are `Parallel_tag` (default value is %CGAL + is linked with TBB) or `Sequential_tag` (default value otherwise). + \tparam DiagonalizeTraits model of `DiagonalizeTraits` used for + matrix diagonalization. It can be omitted: if Eigen 3 (or greater) + is available and `CGAL_EIGEN3_ENABLED` is defined then an overload + using `Eigen_diagonalize_traits` is provided. Otherwise, the + internal implementation `Diagonalize_traits` is used. + + \param input face graph. + \param neighbor_query object used to access neighborhoods of points. + */ template > #endif - Local_eigen_analysis (const Input_is_face_graph&, - const FaceListGraph& input, - const NeighborQuery& neighbor_query, - const ConcurrencyTag& = ConcurrencyTag(), - const DiagonalizeTraits& = DiagonalizeTraits()) + static Local_eigen_analysis create_from_face_graph (const FaceListGraph& input, + const NeighborQuery& neighbor_query, + const ConcurrencyTag& = ConcurrencyTag(), + const DiagonalizeTraits& = DiagonalizeTraits()) { typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef typename boost::graph_traits::face_iterator face_iterator; typedef typename CGAL::Iterator_range Face_range; typedef typename boost::property_map::type::value_type face_index; + + Local_eigen_analysis out; + out.m_content = boost::make_shared(); Face_range range (faces(input)); - m_eigenvalues.resize (range.size()); - m_sum_eigenvalues.resize (range.size()); - m_centroids.resize (range.size()); - m_smallest_eigenvectors.resize (range.size()); + out.m_content->eigenvalues.resize (range.size()); + out.m_content->sum_eigenvalues.resize (range.size()); + out.m_content->centroids.resize (range.size()); + out.m_content->smallest_eigenvectors.resize (range.size()); #ifdef CGAL_CLASSIFICATION_EIGEN_FULL_STORAGE - m_middle_eigenvectors.resize (range.size()); - m_largest_eigenvectors.resize (range.size()); + out.m_content->middle_eigenvectors.resize (range.size()); + out.m_content->largest_eigenvectors.resize (range.size()); #endif - m_mean_range = 0.; + out.m_content->mean_range = 0.; #ifndef CGAL_LINKED_WITH_TBB CGAL_static_assertion_msg (!(boost::is_convertible::value), @@ -354,7 +381,7 @@ public: { tbb::mutex mutex; Compute_eigen_values_graph - f(*this, input, neighbor_query, m_mean_range, mutex); + f(out, input, neighbor_query, out.m_content->mean_range, mutex); tbb::parallel_for(tbb::blocked_range(0, range.size()), f); } @@ -366,17 +393,41 @@ public: std::vector neighbors; neighbor_query (fd, std::back_inserter (neighbors)); - m_mean_range += face_radius(fd, input); + out.m_content->mean_range += out.face_radius(fd, input); - compute_triangles + out.compute_triangles (input, fd, neighbors); } } - m_mean_range /= range.size(); + out.m_content->mean_range /= range.size(); + return out; } + /*! + \brief Computes the local eigen analysis of an input set of point + clusters based on a local neighborhood. + + \tparam ClusterRange model of `ConstRange`. Its iterator type is + `RandomAccessIterator` and its value type is the key type of + `PointMap`. + \tparam PointMap model of `ReadablePropertyMap` whose key + type is the value type of the iterator of `PointRange` and value type + is `CGAL::Point_3`. + \tparam ConcurrencyTag enables sequential versus parallel + algorithm. Possible values are `Parallel_tag` (default value is %CGAL + is linked with TBB) or `Sequential_tag` (default value otherwise). + \tparam DiagonalizeTraits model of `DiagonalizeTraits` used for + matrix diagonalization. It can be omitted: if Eigen 3 (or greater) + is available and `CGAL_EIGEN3_ENABLED` is defined then an overload + using `Eigen_diagonalize_traits` is provided. Otherwise, the + internal implementation `Diagonalize_traits` is used. + + \param input point range. + \param point_map property map to access the input points. + \param neighbor_query object used to access neighborhoods of points. + */ template > #endif - Local_eigen_analysis (const Input_is_clusters&, - const ClusterRange& input, - PointMap point_map, - const ConcurrencyTag& = ConcurrencyTag(), - const DiagonalizeTraits& = DiagonalizeTraits()) + static Local_eigen_analysis create_from_point_clusters (const ClusterRange& input, + PointMap point_map, + const ConcurrencyTag& = ConcurrencyTag(), + const DiagonalizeTraits& = DiagonalizeTraits()) { - m_eigenvalues.resize (input.size()); - m_sum_eigenvalues.resize (input.size()); - m_centroids.resize (input.size()); - m_smallest_eigenvectors.resize (input.size()); + Local_eigen_analysis out; + out.m_content = boost::make_shared(); + + out.m_content->eigenvalues.resize (input.size()); + out.m_content->sum_eigenvalues.resize (input.size()); + out.m_content->centroids.resize (input.size()); + out.m_content->smallest_eigenvectors.resize (input.size()); #ifdef CGAL_CLASSIFICATION_EIGEN_FULL_STORAGE - m_middle_eigenvectors.resize (input.size()); - m_largest_eigenvectors.resize (input.size()); + out.m_content->middle_eigenvectors.resize (input.size()); + out.m_content->largest_eigenvectors.resize (input.size()); #endif - m_mean_range = 0.; + out.m_content->mean_range = 0.; Compute_clusters_eigen_values - f(*this, input, point_map); + f(out, input, point_map); #ifndef CGAL_LINKED_WITH_TBB @@ -426,8 +479,14 @@ public: for (std::size_t i = 0; i < input.size(); ++ i) f.apply (i); } + return out; } - /// \endcond + + + /// @} + + /// \name Analysis + /// @{ /*! \brief Returns the estimated unoriented normal vector of the point at position `index`. @@ -436,9 +495,9 @@ public: template typename GeomTraits::Vector_3 normal_vector (std::size_t index) const { - return typename GeomTraits::Vector_3(double(m_smallest_eigenvectors[index][0]), - double(m_smallest_eigenvectors[index][1]), - double(m_smallest_eigenvectors[index][2])); + return typename GeomTraits::Vector_3(double(m_content->smallest_eigenvectors[index][0]), + double(m_content->smallest_eigenvectors[index][1]), + double(m_content->smallest_eigenvectors[index][2])); } /*! @@ -449,26 +508,28 @@ public: typename GeomTraits::Plane_3 plane (std::size_t index) const { return typename GeomTraits::Plane_3 - (typename GeomTraits::Point_3 (double(m_centroids[index][0]), - double(m_centroids[index][1]), - double(m_centroids[index][2])), - typename GeomTraits::Vector_3 (double(m_smallest_eigenvectors[index][0]), - double(m_smallest_eigenvectors[index][1]), - double(m_smallest_eigenvectors[index][2]))); + (typename GeomTraits::Point_3 (double(m_content->centroids[index][0]), + double(m_content->centroids[index][1]), + double(m_content->centroids[index][2])), + typename GeomTraits::Vector_3 (double(m_content->smallest_eigenvectors[index][0]), + double(m_content->smallest_eigenvectors[index][1]), + double(m_content->smallest_eigenvectors[index][2]))); } /*! \brief Returns the normalized eigenvalues of the point at position `index`. */ - const Eigenvalues& eigenvalue (std::size_t index) const { return m_eigenvalues[index]; } + const Eigenvalues& eigenvalue (std::size_t index) const { return m_content->eigenvalues[index]; } /*! \brief Returns the sum of eigenvalues of the point at position `index`. */ - float sum_of_eigenvalues (std::size_t index) const { return m_sum_eigenvalues[index]; } + float sum_of_eigenvalues (std::size_t index) const { return m_content->sum_eigenvalues[index]; } + + /// @} /// \cond SKIP_IN_MANUAL - float mean_range() const { return m_mean_range; } + float mean_range() const { return m_content->mean_range; } /// \endcond private: @@ -497,18 +558,18 @@ private: if (neighbor_points.size() == 0) { Eigenvalues v = make_array( 0.f, 0.f, 0.f ); - m_eigenvalues[index] = v; - m_centroids[index] = make_array(float(query.x()), float(query.y()), float(query.z()) ); - m_smallest_eigenvectors[index] = make_array( 0.f, 0.f, 1.f ); + m_content->eigenvalues[index] = v; + m_content->centroids[index] = make_array(float(query.x()), float(query.y()), float(query.z()) ); + m_content->smallest_eigenvectors[index] = make_array( 0.f, 0.f, 1.f ); #ifdef CGAL_CLASSIFICATION_EIGEN_FULL_STORAGE - m_middle_eigenvectors[index] = make_array( 0.f, 1.f, 0.f ); - m_largest_eigenvectors[index] = make_array( 1.f, 0.f, 0.f ); + m_content->middle_eigenvectors[index] = make_array( 0.f, 1.f, 0.f ); + m_content->largest_eigenvectors[index] = make_array( 1.f, 0.f, 0.f ); #endif return; } Point centroid = CGAL::centroid (neighbor_points.begin(), neighbor_points.end()); - m_centroids[index] = make_array( float(centroid.x()), float(centroid.y()), float(centroid.z()) ); + m_content->centroids[index] = make_array( float(centroid.x()), float(centroid.y()), float(centroid.z()) ); CGAL::cpp11::array covariance = make_array( 0.f, 0.f, 0.f, 0.f, 0.f, 0.f ); @@ -536,12 +597,12 @@ private: if (sum > 0.f) for (std::size_t i = 0; i < 3; ++ i) evalues[i] = evalues[i] / sum; - m_sum_eigenvalues[index] = float(sum); - m_eigenvalues[index] = make_array( float(evalues[0]), float(evalues[1]), float(evalues[2]) ); - m_smallest_eigenvectors[index] = make_array( float(evectors[0]), float(evectors[1]), float(evectors[2]) ); + m_content->sum_eigenvalues[index] = float(sum); + m_content->eigenvalues[index] = make_array( float(evalues[0]), float(evalues[1]), float(evalues[2]) ); + m_content->smallest_eigenvectors[index] = make_array( float(evectors[0]), float(evectors[1]), float(evectors[2]) ); #ifdef CGAL_CLASSIFICATION_EIGEN_FULL_STORAGE - m_middle_eigenvectors[index] = make_array( float(evectors[3]), float(evectors[4]), float(evectors[5]) ); - m_largest_eigenvectors[index] = make_array( float(evectors[6]), float(evectors[7]), float(evectors[8]) ); + m_content->middle_eigenvectors[index] = make_array( float(evectors[3]), float(evectors[4]), float(evectors[5]) ); + m_content->largest_eigenvectors[index] = make_array( float(evectors[6]), float(evectors[7]), float(evectors[8]) ); #endif } @@ -560,7 +621,7 @@ private: if (neighbor_faces.size() == 0) { Eigenvalues v = {{ 0.f, 0.f, 0.f }}; - m_eigenvalues[get(get(CGAL::face_index,g), query)] = v; + m_content->eigenvalues[get(get(CGAL::face_index,g), query)] = v; CGAL::cpp11::array tr = {{ Triangle (get(get (CGAL::vertex_point, g), target(halfedge(query, g), g)), @@ -569,12 +630,12 @@ private: Point c = CGAL::centroid(tr.begin(), tr.end(), Kernel(), CGAL::Dimension_tag<2>()); - m_centroids[get(get(CGAL::face_index,g), query)] = {{ float(c.x()), float(c.y()), float(c.z()) }}; + m_content->centroids[get(get(CGAL::face_index,g), query)] = {{ float(c.x()), float(c.y()), float(c.z()) }}; - m_smallest_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ 0.f, 0.f, 1.f }}; + m_content->smallest_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ 0.f, 0.f, 1.f }}; #ifdef CGAL_CLASSIFICATION_EIGEN_FULL_STORAGE - m_middle_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ 0.f, 1.f, 0.f }}; - m_largest_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ 1.f, 0.f, 0.f }}; + m_content->middle_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ 0.f, 1.f, 0.f }}; + m_content->largest_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ 1.f, 0.f, 0.f }}; #endif return; } @@ -600,7 +661,7 @@ private: c, Kernel(), (Triangle*)NULL, CGAL::Dimension_tag<2>(), DiagonalizeTraits()); - m_centroids[get(get(CGAL::face_index,g), query)] = {{ float(c.x()), float(c.y()), float(c.z()) }}; + m_content->centroids[get(get(CGAL::face_index,g), query)] = {{ float(c.x()), float(c.y()), float(c.z()) }}; CGAL::cpp11::array evalues = {{ 0.f, 0.f, 0.f }}; CGAL::cpp11::array evectors = {{ 0.f, 0.f, 0.f, @@ -615,12 +676,12 @@ private: if (sum > 0.f) for (std::size_t i = 0; i < 3; ++ i) evalues[i] = evalues[i] / sum; - m_sum_eigenvalues[get(get(CGAL::face_index,g), query)] = float(sum); - m_eigenvalues[get(get(CGAL::face_index,g), query)] = {{ float(evalues[0]), float(evalues[1]), float(evalues[2]) }}; - m_smallest_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ float(evectors[0]), float(evectors[1]), float(evectors[2]) }}; + m_content->sum_eigenvalues[get(get(CGAL::face_index,g), query)] = float(sum); + m_content->eigenvalues[get(get(CGAL::face_index,g), query)] = {{ float(evalues[0]), float(evalues[1]), float(evalues[2]) }}; + m_content->smallest_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ float(evectors[0]), float(evectors[1]), float(evectors[2]) }}; #ifdef CGAL_CLASSIFICATION_EIGEN_FULL_STORAGE - m_middle_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ float(evectors[3]), float(evectors[4]), float(evectors[5]) }}; - m_largest_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ float(evectors[6]), float(evectors[7]), float(evectors[8]) }}; + m_content->middle_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ float(evectors[3]), float(evectors[4]), float(evectors[5]) }}; + m_content->largest_eigenvectors[get(get(CGAL::face_index,g), query)] = {{ float(evectors[6]), float(evectors[7]), float(evectors[8]) }}; #endif } diff --git a/Classification/include/CGAL/Classification/Mesh_feature_generator.h b/Classification/include/CGAL/Classification/Mesh_feature_generator.h index c171878712e..4d93ba25e66 100644 --- a/Classification/include/CGAL/Classification/Mesh_feature_generator.h +++ b/Classification/include/CGAL/Classification/Mesh_feature_generator.h @@ -152,9 +152,10 @@ private: t.reset(); t.start(); - eigen = new Local_eigen_analysis (typename Local_eigen_analysis::Input_is_face_graph(), - input, neighborhood->n_ring_neighbor_query(nb_scale + 1), - ConcurrencyTag(), DiagonalizeTraits()); + eigen = new Local_eigen_analysis + (Local_eigen_analysis::create_from_face_graph + (input, neighborhood->n_ring_neighbor_query(nb_scale + 1), + ConcurrencyTag(), DiagonalizeTraits())); float mrange = eigen->mean_range(); if (this->voxel_size < 0) this->voxel_size = mrange; @@ -216,15 +217,29 @@ public: Mesh_feature_generator(Feature_set& features, const FaceListGraph& input, PointMap point_map, - std::size_t nb_scales) + std::size_t nb_scales, + float voxel_size = -1.f) : m_input (input), m_range(faces(input)), m_point_map (point_map), m_features (features) { m_bbox = CGAL::bounding_box (boost::make_transform_iterator (m_range.begin(), CGAL::Property_map_to_unary_function(m_point_map)), boost::make_transform_iterator (m_range.end(), CGAL::Property_map_to_unary_function(m_point_map))); - generate_features_impl (nb_scales); + CGAL::Real_timer t; t.start(); + + m_scales.reserve (nb_scales); + + m_scales.push_back (new Scale (m_input, m_range, m_point_map, m_bbox, voxel_size, 0)); + voxel_size = m_scales[0]->grid_resolution(); + for (std::size_t i = 1; i < nb_scales; ++ i) + { + voxel_size *= 2; + m_scales.push_back (new Scale (m_input, m_range, m_point_map, m_bbox, voxel_size, i, m_scales[i-1]->grid)); + } + t.stop(); + CGAL_CLASSIFICATION_CERR << "Scales computed in " << t.time() << " second(s)" << std::endl; + t.reset(); } @@ -244,6 +259,42 @@ public: /// \endcond + void generate_point_based_features () + { +#ifdef DO_NOT_USE_EIGEN_FEATURES + for (int j = 0; j < 3; ++ j) + { + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, eigen(i), std::size_t(j)); + } +#else + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, i, m_range, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, eigen(i)); +#endif + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, m_point_map, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, m_point_map, grid(i), radius_neighbors(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, m_point_map, grid(i), radius_dtm(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_range, eigen(i)); + } + /*! \brief Returns the bounding box of the input point set. */ @@ -297,51 +348,6 @@ private: m_scales.clear(); } - void add (Feature_handle fh, std::size_t i) - { - m_features_to_rename.push_back (std::make_pair (fh, i)); - } - - void generate_point_based_features () - { -#ifdef DO_NOT_USE_EIGEN_FEATURES - for (int j = 0; j < 3; ++ j) - { - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i), std::size_t(j)), i); - } -#else - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i)), i); -#endif - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, m_point_map, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, m_point_map, grid(i), radius_neighbors(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, m_point_map, grid(i), radius_dtm(i)), i); - } - - void generate_normal_based_features(const CGAL::Default_property_map&) - { - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_range, eigen(i)), i); - } - template const T& get_parameter (const T& t) { @@ -355,46 +361,6 @@ private: return Default_property_map(); } - void generate_features_impl (std::size_t nb_scales) - { - CGAL::Real_timer t; t.start(); - - m_scales.reserve (nb_scales); - - float voxel_size = -1; - - m_scales.push_back (new Scale (m_input, m_range, m_point_map, m_bbox, voxel_size, 0)); - voxel_size = m_scales[0]->grid_resolution(); - for (std::size_t i = 1; i < nb_scales; ++ i) - { - voxel_size *= 2; - m_scales.push_back (new Scale (m_input, m_range, m_point_map, m_bbox, voxel_size, i, m_scales[i-1]->grid)); - } - t.stop(); - CGAL_CLASSIFICATION_CERR << "Scales computed in " << t.time() << " second(s)" << std::endl; - t.reset(); - - t.start(); - -#ifdef CGAL_LINKED_WITH_TBB - m_features.begin_parallel_additions(); -#endif - - generate_point_based_features (); - generate_normal_based_features (CGAL::Default_property_map()); - -#ifdef CGAL_LINKED_WITH_TBB - m_features.end_parallel_additions(); -#endif - - for (std::size_t i = 0; i < m_features_to_rename.size(); ++ i) - m_features_to_rename[i].first->set_name - (m_features_to_rename[i].first->name() + "_" + std::to_string(m_features_to_rename[i].second)); - - t.stop(); - CGAL_CLASSIFICATION_CERR << "Features computed in " << t.time() << " second(s)" << std::endl; - } - }; diff --git a/Classification/include/CGAL/Classification/Point_set_feature_generator.h b/Classification/include/CGAL/Classification/Point_set_feature_generator.h index e21db14afc0..29a0b2daf7b 100644 --- a/Classification/include/CGAL/Classification/Point_set_feature_generator.h +++ b/Classification/include/CGAL/Classification/Point_set_feature_generator.h @@ -171,7 +171,7 @@ private: { CGAL::Real_timer t; t.start(); - if (voxel_size < 0.) + if (lower_grid == NULL) neighborhood = new Neighborhood (input, point_map); else neighborhood = new Neighborhood (input, point_map, voxel_size); @@ -186,7 +186,8 @@ private: t.start(); eigen = new Local_eigen_analysis - (input, point_map, neighborhood->k_neighbor_query(12), ConcurrencyTag(), DiagonalizeTraits()); + (Local_eigen_analysis::create_from_point_set + (input, point_map, neighborhood->k_neighbor_query(12), ConcurrencyTag(), DiagonalizeTraits())); float range = eigen->mean_range(); if (this->voxel_size < 0) @@ -237,7 +238,6 @@ private: const PointRange& m_input; PointMap m_point_map; Feature_set& m_features; - std::vector > m_features_to_rename; public: @@ -309,37 +309,34 @@ public: \param color_map property map to access the colors of the input points (if any). \param echo_map property map to access the echo values of the input points (if any). */ - template Point_set_feature_generator(Feature_set& features, const PointRange& input, PointMap point_map, std::size_t nb_scales, - VectorMap normal_map = VectorMap(), - ColorMap color_map = ColorMap(), - EchoMap echo_map = EchoMap() -#ifndef DOXYGEN_RUNNING - , float voxel_size = -1.f // Undocumented way of changing base voxel size -#endif - ) + float voxel_size = -1.f) : m_input (input), m_point_map (point_map), m_features (features) { m_bbox = CGAL::bounding_box (boost::make_transform_iterator (m_input.begin(), CGAL::Property_map_to_unary_function(m_point_map)), boost::make_transform_iterator (m_input.end(), CGAL::Property_map_to_unary_function(m_point_map))); - typedef typename Default::Get::type - Vmap; - typedef typename Default::Get::type - Cmap; - typedef typename Default::Get::type - Emap; + CGAL::Real_timer t; t.start(); + + m_scales.reserve (nb_scales); + + m_scales.push_back (new Scale (m_input, m_point_map, m_bbox, voxel_size)); - generate_features_impl (nb_scales, voxel_size, - get_parameter(normal_map), - get_parameter(color_map), - get_parameter(echo_map)); + if (voxel_size == -1.f) + voxel_size = m_scales[0]->grid_resolution(); + + for (std::size_t i = 1; i < nb_scales; ++ i) + { + voxel_size *= 2; + m_scales.push_back (new Scale (m_input, m_point_map, m_bbox, voxel_size, m_scales[i-1]->grid)); + } + t.stop(); + CGAL_CLASSIFICATION_CERR << "Scales computed in " << t.time() << " second(s)" << std::endl; + t.reset(); } @@ -359,6 +356,77 @@ public: /// \endcond + void generate_point_based_features () + { +#ifdef DO_NOT_USE_EIGEN_FEATURES + for (int j = 0; j < 3; ++ j) + { + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i), std::size_t(j)); + } +#else + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i)); +#endif + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, m_point_map, eigen(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, m_point_map, grid(i), radius_neighbors(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, m_point_map, grid(i), radius_dtm(i)); + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, eigen(i)); + } + + template + void generate_normal_based_features(const VectorMap& normal_map) + { + m_features.add (m_input, normal_map); + } + + template + void generate_color_based_features(const ColorMap& color_map) + { +#ifdef DO_NOT_USE_HSV_FEATURES + typedef Feature::Color_channel Color_channel; + for (std::size_t i = 0; i < 3; ++ i) + m_features.add (m_input, color_map, typename Color_channel::Channel(i)); +#else + typedef Feature::Hsv Hsv; + + for (std::size_t i = 0; i <= 8; ++ i) + m_features.add (m_input, color_map, typename Hsv::Channel(0), 45.f * float(i), 22.5f); + + for (std::size_t i = 0; i <= 4; ++ i) + m_features.add (m_input, color_map, typename Hsv::Channel(1), 25.f * float(i), 12.5f); + + for (std::size_t i = 0; i <= 4; ++ i) + m_features.add (m_input, color_map, typename Hsv::Channel(2), 25.f * float(i), 12.5f); +#endif + } + + template + void generate_echo_based_features(const EchoMap& echo_map) + { + typedef Feature::Echo_scatter Echo_scatter; + for (std::size_t i = 0; i < m_scales.size(); ++ i) + m_features.add_with_scale_id (i, m_input, echo_map, grid(i), radius_neighbors(i)); + } + /*! \brief Returns the bounding box of the input point set. */ @@ -412,94 +480,6 @@ private: m_scales.clear(); } - void add (Feature_handle fh, std::size_t i) - { - m_features_to_rename.push_back (std::make_pair (fh, i)); - } - - void generate_point_based_features () - { -#ifdef DO_NOT_USE_EIGEN_FEATURES - for (int j = 0; j < 3; ++ j) - { - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i), std::size_t(j)), i); - } -#else - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i)), i); -#endif - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, m_point_map, eigen(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, m_point_map, grid(i), radius_neighbors(i)), i); - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, m_point_map, grid(i), radius_dtm(i)), i); - } - - template - void generate_normal_based_features(const VectorMap& normal_map) - { - m_features.add (m_input, normal_map); - } - - void generate_normal_based_features(const CGAL::Constant_property_map&) - { - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, eigen(i)), i); - } - - template - void generate_color_based_features(const ColorMap& color_map) - { -#ifdef DO_NOT_USE_HSV_FEATURES - typedef Feature::Color_channel Color_channel; - for (std::size_t i = 0; i < 3; ++ i) - m_features.add (m_input, color_map, typename Color_channel::Channel(i)); -#else - typedef Feature::Hsv Hsv; - - for (std::size_t i = 0; i <= 8; ++ i) - m_features.add (m_input, color_map, typename Hsv::Channel(0), 45.f * float(i), 22.5f); - - for (std::size_t i = 0; i <= 4; ++ i) - m_features.add (m_input, color_map, typename Hsv::Channel(1), 25.f * float(i), 12.5f); - - for (std::size_t i = 0; i <= 4; ++ i) - m_features.add (m_input, color_map, typename Hsv::Channel(2), 25.f * float(i), 12.5f); -#endif - } - - void generate_color_based_features(const CGAL::Constant_property_map&) - { - } - - template - void generate_echo_based_features(const EchoMap& echo_map) - { - typedef Feature::Echo_scatter Echo_scatter; - for (std::size_t i = 0; i < m_scales.size(); ++ i) - add(m_features.add (m_input, echo_map, grid(i), radius_neighbors(i)), i); - } - - void generate_echo_based_features(const CGAL::Constant_property_map&) - { - } - void generate_gradient_features() { #ifdef CGAL_CLASSIFICATION_USE_GRADIENT_OF_FEATURE @@ -535,61 +515,6 @@ private: return Constant_property_map(); } - template - void generate_features_impl (std::size_t nb_scales, float voxel_size, - VectorMap normal_map, - ColorMap color_map, - EchoMap echo_map) - { - CGAL::Real_timer t; t.start(); - - m_scales.reserve (nb_scales); - - m_scales.push_back (new Scale (m_input, m_point_map, m_bbox, -1.f)); - - if (voxel_size == -1.f) - voxel_size = m_scales[0]->grid_resolution(); - - for (std::size_t i = 1; i < nb_scales; ++ i) - { - voxel_size *= 2; - m_scales.push_back (new Scale (m_input, m_point_map, m_bbox, voxel_size, m_scales[i-1]->grid)); - } - t.stop(); - CGAL_CLASSIFICATION_CERR << "Scales computed in " << t.time() << " second(s)" << std::endl; - t.reset(); - - t.start(); - -#ifdef CGAL_LINKED_WITH_TBB - if (boost::is_convertible::value) - m_features.begin_parallel_additions(); -#else - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#endif - - generate_point_based_features (); - generate_normal_based_features (normal_map); - generate_color_based_features (color_map); - generate_echo_based_features (echo_map); - -#ifdef CGAL_LINKED_WITH_TBB - if (boost::is_convertible::value) - m_features.end_parallel_additions(); -#else - CGAL_static_assertion_msg (!(boost::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#endif - - for (std::size_t i = 0; i < m_features_to_rename.size(); ++ i) - m_features_to_rename[i].first->set_name - (m_features_to_rename[i].first->name() + "_" + std::to_string(m_features_to_rename[i].second)); - - t.stop(); - CGAL_CLASSIFICATION_CERR << "Features computed in " << t.time() << " second(s)" << std::endl; - } - }; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index 601dbe7c33d..b70eac9baa6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -553,8 +553,6 @@ void Cluster_classification::compute_features (std::size_t nb_scales) { CGAL_assertion (!(m_points->point_set()->empty())); - Generator* generator; - reset_indices(); std::cerr << "Computing pointwise features with " << nb_scales << " scale(s)" << std::endl; @@ -570,32 +568,40 @@ void Cluster_classification::compute_features (std::size_t nb_scales) Feature_set pointwise_features; + Generator generator (pointwise_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales); + + CGAL::Real_timer t; + t.start(); + +#ifdef CGAL_LINKED_WITH_TBB + pointwise_features.begin_parallel_additions(); +#endif + + generator.generate_point_based_features(); + if (normals) + generator.generate_normal_based_features (m_points->point_set()->normal_map()); + if (colors) + generator.generate_color_based_features (m_color); + if (echo) + generator.generate_echo_based_features (echo_map); + add_remaining_point_set_properties_as_features(pointwise_features); - if (!normals && !colors && !echo) - generator = new Generator (pointwise_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales); - else if (!normals && !colors && echo) - generator = new Generator (pointwise_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - CGAL::Default(), CGAL::Default(), echo_map); - else if (!normals && colors && !echo) - generator = new Generator (pointwise_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - CGAL::Default(), m_color); - else if (!normals && colors && echo) - generator = new Generator (pointwise_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - CGAL::Default(), m_color, echo_map); - else if (normals && !colors && !echo) - generator = new Generator (pointwise_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - m_points->point_set()->normal_map()); - else if (normals && !colors && echo) - generator = new Generator (pointwise_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - m_points->point_set()->normal_map(), CGAL::Default(), echo_map); - else if (normals && colors && !echo) - generator = new Generator (pointwise_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - m_points->point_set()->normal_map(), m_color); - else - generator = new Generator (pointwise_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - m_points->point_set()->normal_map(), m_color, echo_map); + +#ifdef CGAL_LINKED_WITH_TBB + pointwise_features.end_parallel_additions(); +#endif + + t.stop(); + std::cerr << pointwise_features.size() << " feature(s) computed in " << t.time() << " second(s)" << std::endl; + t.reset(); std::cerr << "Computing cluster features" << std::endl; + t.start(); + +#ifdef CGAL_LINKED_WITH_TBB + m_features.begin_parallel_additions(); +#endif + for (std::size_t i = 0; i < pointwise_features.size(); ++ i) { m_features.template add (*(m_points->point_set()), @@ -603,6 +609,11 @@ void Cluster_classification::compute_features (std::size_t nb_scales) pointwise_features[i]); } +#ifdef CGAL_LINKED_WITH_TBB + m_features.end_parallel_additions(); + m_features.begin_parallel_additions(); +#endif + for (std::size_t i = 0; i < pointwise_features.size(); ++ i) { m_features.template add (*(m_points->point_set()), @@ -613,6 +624,14 @@ void Cluster_classification::compute_features (std::size_t nb_scales) add_cluster_features(); +#ifdef CGAL_LINKED_WITH_TBB + m_features.end_parallel_additions(); +#endif + + t.stop(); + std::cerr << m_features.size() << " feature(s) computed in " << t.time() << " second(s)" << std::endl; + + delete m_sowf; m_sowf = new Sum_of_weighted_features (m_labels, m_features); delete m_ethz; @@ -622,7 +641,6 @@ void Cluster_classification::compute_features (std::size_t nb_scales) m_random_forest = new Random_forest (m_labels, m_features); #endif - delete generator; std::cerr << "Features = " << m_features.size() << std::endl; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h index 62710b88f18..6cf0697d089 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.h @@ -310,10 +310,10 @@ class Cluster_classification : public Item_classification_base void add_cluster_features () { - m_eigen = boost::make_shared (Local_eigen_analysis::Input_is_clusters(), - m_clusters, + m_eigen = boost::make_shared + (Local_eigen_analysis::create_from_point_clusters(m_clusters, Cluster_index_to_point_map (m_points->point_set()), - Concurrency_tag()); + Concurrency_tag())); m_features.template add (m_clusters); m_features.template add (m_clusters, m_points->point_set()); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index 81bfdc074e4..e790a73e7c9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -450,41 +450,41 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) if (!echo) boost::tie (echo_map, echo) = m_points->point_set()->template property_map("number_of_returns"); + m_generator = new Generator (m_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales); + + CGAL::Real_timer t; + t.start(); + +#ifdef CGAL_LINKED_WITH_TBB + m_features.begin_parallel_additions(); +#endif + + m_generator->generate_point_based_features(); + if (normals) + m_generator->generate_normal_based_features (m_points->point_set()->normal_map()); + if (colors) + m_generator->generate_color_based_features (m_color); + if (echo) + m_generator->generate_echo_based_features (echo_map); + add_remaining_point_set_properties_as_features(); - if (!normals && !colors && !echo) - m_generator = new Generator (m_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales); - else if (!normals && !colors && echo) - m_generator = new Generator (m_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - CGAL::Default(), CGAL::Default(), echo_map); - else if (!normals && colors && !echo) - m_generator = new Generator (m_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - CGAL::Default(), m_color); - else if (!normals && colors && echo) - m_generator = new Generator (m_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - CGAL::Default(), m_color, echo_map); - else if (normals && !colors && !echo) - m_generator = new Generator (m_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - m_points->point_set()->normal_map()); - else if (normals && !colors && echo) - m_generator = new Generator (m_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - m_points->point_set()->normal_map(), CGAL::Default(), echo_map); - else if (normals && colors && !echo) - m_generator = new Generator (m_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - m_points->point_set()->normal_map(), m_color); - else - m_generator = new Generator (m_features, *(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, - m_points->point_set()->normal_map(), m_color, echo_map); +#ifdef CGAL_LINKED_WITH_TBB + m_features.end_parallel_additions(); +#endif delete m_sowf; m_sowf = new Sum_of_weighted_features (m_labels, m_features); delete m_ethz; m_ethz = new ETHZ_random_forest (m_labels, m_features); + #ifdef CGAL_LINKED_WITH_OPENCV delete m_random_forest; m_random_forest = new Random_forest (m_labels, m_features); #endif - std::cerr << "Features = " << m_features.size() << std::endl; + + t.stop(); + std::cerr << m_features.size() << " feature(s) computed in " << t.time() << " second(s)" << std::endl; } void Point_set_item_classification::select_random_region() diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index 0048a3df4ff..e1c5a1ce04b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -163,6 +163,16 @@ void Surface_mesh_item_classification::compute_features (std::size_t nb_scales) m_generator = new Generator (m_features, *(m_mesh->polyhedron()), fc_map, nb_scales); +#ifdef CGAL_LINKED_WITH_TBB + m_features.begin_parallel_additions(); +#endif + + m_generator->generate_point_based_features(); + +#ifdef CGAL_LINKED_WITH_TBB + m_features.end_parallel_additions(); +#endif + delete m_sowf; m_sowf = new Sum_of_weighted_features (m_labels, m_features); #ifdef CGAL_LINKED_WITH_OPENCV