From d9b5f4f1e56ece8fab3235409b870458bbd5d98a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 2 Apr 2020 10:44:15 +0200 Subject: [PATCH] Use CGAL::for_each in classify functions --- .../include/CGAL/Classification/classify.h | 505 +++++------------- 1 file changed, 145 insertions(+), 360 deletions(-) diff --git a/Classification/include/CGAL/Classification/classify.h b/Classification/include/CGAL/Classification/classify.h index 6fac8e3c819..db1b16c3728 100644 --- a/Classification/include/CGAL/Classification/classify.h +++ b/Classification/include/CGAL/Classification/classify.h @@ -17,9 +17,12 @@ #include #include +#include #include #include +#include + #ifdef CGAL_LINKED_WITH_TBB #include #include @@ -31,299 +34,6 @@ namespace CGAL { namespace Classification { - -/// \cond SKIP_IN_MANUAL -namespace internal { - - template - class Classify_functor - { - const Label_set& m_labels; - const Classifier& m_classifier; - LabelIndexRange& m_out; - - public: - - Classify_functor (const Label_set& labels, - const Classifier& classifier, - LabelIndexRange& out) - : m_labels (labels), m_classifier (classifier), m_out (out) - { } - -#ifdef CGAL_LINKED_WITH_TBB - void operator()(const tbb::blocked_range& r) const - { - for (std::size_t s = r.begin(); s != r.end(); ++ s) - apply(s); - } -#endif // CGAL_LINKED_WITH_TBB - - inline void apply (std::size_t s) const - { - std::size_t nb_class_best=0; - std::vector values; - m_classifier (s, values); - - float val_class_best = 0.f; - for(std::size_t k = 0; k < m_labels.size(); ++ k) - { - if(val_class_best < values[k]) - { - val_class_best = values[k]; - nb_class_best = k; - } - } - - m_out[s] = static_cast(nb_class_best); - } - - }; - - template - class Classify_detailed_output_functor - { - const Label_set& m_labels; - const Classifier& m_classifier; - LabelIndexRange& m_out; - ProbabilitiesRanges& m_prob; - - public: - - Classify_detailed_output_functor (const Label_set& labels, - const Classifier& classifier, - LabelIndexRange& out, - ProbabilitiesRanges& prob) - : m_labels (labels), m_classifier (classifier), m_out (out), m_prob (prob) - { } - -#ifdef CGAL_LINKED_WITH_TBB - void operator()(const tbb::blocked_range& r) const - { - for (std::size_t s = r.begin(); s != r.end(); ++ s) - apply(s); - } -#endif // CGAL_LINKED_WITH_TBB - - inline void apply (std::size_t s) const - { - std::size_t nb_class_best=0; - std::vector values; - m_classifier (s, values); - - float val_class_best = 0.f; - for(std::size_t k = 0; k < m_labels.size(); ++ k) - { - m_prob[k][s] = values[k]; - if(val_class_best < values[k]) - { - val_class_best = values[k]; - nb_class_best = k; - } - } - - m_out[s] = static_cast(nb_class_best); - } - - }; - - template - class Classify_functor_local_smoothing_preprocessing - { - const Label_set& m_labels; - const Classifier& m_classifier; - std::vector >& m_values; - - public: - - Classify_functor_local_smoothing_preprocessing - (const Label_set& labels, - const Classifier& classifier, - std::vector >& values) - : m_labels (labels), m_classifier (classifier), m_values (values) - { } - -#ifdef CGAL_LINKED_WITH_TBB - void operator()(const tbb::blocked_range& r) const - { - for (std::size_t s = r.begin(); s != r.end(); ++ s) - apply (s); - } -#endif - - inline void apply (std::size_t s) const - { - std::vector values; - m_classifier(s, values); - for(std::size_t k = 0; k < m_labels.size(); ++ k) - m_values[k][s] = values[k]; - } - }; - - template - class Classify_functor_local_smoothing - { - const ItemRange& m_input; - const ItemMap m_item_map; - const Label_set& m_labels; - const std::vector >& m_values; - const NeighborQuery& m_neighbor_query; - LabelIndexRange& m_out; - - public: - - Classify_functor_local_smoothing (const ItemRange& input, - ItemMap item_map, - const Label_set& labels, - const std::vector >& values, - const NeighborQuery& neighbor_query, - LabelIndexRange& out) - : m_input (input), m_item_map (item_map), m_labels (labels), - m_values(values), - m_neighbor_query (neighbor_query), - m_out (out) - { } - -#ifdef CGAL_LINKED_WITH_TBB - void operator()(const tbb::blocked_range& r) const - { - for (std::size_t s = r.begin(); s != r.end(); ++ s) - apply (s); - } -#endif - - inline void apply (std::size_t s) const - { - std::vector neighbors; - m_neighbor_query (get (m_item_map, *(m_input.begin()+s)), std::back_inserter (neighbors)); - - std::vector mean (m_values.size(), 0.); - for (std::size_t n = 0; n < neighbors.size(); ++ n) - for (std::size_t j = 0; j < m_values.size(); ++ j) - mean[j] += m_values[j][neighbors[n]]; - - std::size_t nb_class_best=0; - float val_class_best = 0.f; - for(std::size_t k = 0; k < mean.size(); ++ k) - { - mean[k] /= neighbors.size(); - if(val_class_best < mean[k]) - { - val_class_best = mean[k]; - nb_class_best = k; - } - } - - m_out[s] = static_cast(nb_class_best); - } - - - }; - - template - class Classify_functor_graphcut - { - const ItemRange& m_input; - ItemMap m_item_map; - const Label_set& m_labels; - const Classifier& m_classifier; - const NeighborQuery& m_neighbor_query; - float m_strength; - const std::vector >& m_indices; - const std::vector >& m_input_to_indices; - LabelIndexRange& m_out; - -#ifdef CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE - typedef CGAL::internal::Alpha_expansion_graph_cut_boost Alpha_expansion; -#else - typedef CGAL::internal::Alpha_expansion_graph_cut_boykov_kolmogorov Alpha_expansion; -#endif - - public: - - Classify_functor_graphcut (const ItemRange& input, - ItemMap item_map, - const Label_set& labels, - const Classifier& classifier, - const NeighborQuery& neighbor_query, - float strength, - const std::vector >& indices, - const std::vector >& input_to_indices, - LabelIndexRange& out) - : m_input (input), m_item_map (item_map), m_labels (labels), - m_classifier (classifier), m_neighbor_query (neighbor_query), - m_strength (strength), m_indices (indices), m_input_to_indices (input_to_indices), m_out (out) - { } - -#ifdef CGAL_LINKED_WITH_TBB - void operator()(const tbb::blocked_range& r) const - { - for (std::size_t s = r.begin(); s != r.end(); ++ s) - apply(s); - } -#endif // CGAL_LINKED_WITH_TBB - - - inline void apply (std::size_t sub) const - { - if (m_indices[sub].empty()) - return; - - std::vector > edges; - std::vector edge_weights; - std::vector > probability_matrix - (m_labels.size(), std::vector(m_indices[sub].size(), 0.)); - std::vector assigned_label (m_indices[sub].size()); - - for (std::size_t j = 0; j < m_indices[sub].size(); ++ j) - { - std::size_t s = m_indices[sub][j]; - - std::vector neighbors; - - m_neighbor_query (get(m_item_map, *(m_input.begin()+s)), std::back_inserter (neighbors)); - - for (std::size_t i = 0; i < neighbors.size(); ++ i) - if (sub == m_input_to_indices[neighbors[i]].first - && j != m_input_to_indices[neighbors[i]].second) - { - edges.push_back (std::make_pair (j, m_input_to_indices[neighbors[i]].second)); - edge_weights.push_back (m_strength); - } - - std::vector values; - m_classifier(s, values); - std::size_t nb_class_best = 0; - float val_class_best = 0.f; - for(std::size_t k = 0; k < m_labels.size(); ++ k) - { - float value = values[k]; - probability_matrix[k][j] = -std::log(value); - - if(val_class_best < value) - { - val_class_best = value; - nb_class_best = k; - } - } - assigned_label[j] = nb_class_best; - } - - Alpha_expansion graphcut; - graphcut(edges, edge_weights, probability_matrix, assigned_label); - - for (std::size_t i = 0; i < assigned_label.size(); ++ i) - m_out[m_indices[sub][i]] = static_cast(assigned_label[i]); - } - - }; - -} // namespace internal - -/// \endcond - - /*! \ingroup PkgClassificationMain @@ -362,23 +72,28 @@ namespace internal { const Classifier& classifier, LabelIndexRange& output) { - internal::Classify_functor - f (labels, classifier, output); + CGAL::for_each + (CGAL::make_range (boost::counting_iterator(0), + boost::counting_iterator(input.size())), + [&](const std::size_t& s) -> bool + { + std::size_t nb_class_best=0; + std::vector values; + classifier (s, values); -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(std::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - if (std::is_convertible::value) - { - tbb::parallel_for(tbb::blocked_range(0, input.size ()), f); - } - else -#endif - { - for (std::size_t i = 0; i < input.size(); ++ i) - f.apply(i); - } + float val_class_best = 0.f; + for(std::size_t k = 0; k < labels.size(); ++ k) + { + if(val_class_best < values[k]) + { + val_class_best = values[k]; + nb_class_best = k; + } + } + output[s] = static_cast(nb_class_best); + + return true; + }); } /// \cond SKIP_IN_MANUAL @@ -394,23 +109,30 @@ namespace internal { LabelIndexRange& output, ProbabilitiesRanges& probabilities) { - internal::Classify_detailed_output_functor - f (labels, classifier, output, probabilities); + CGAL::for_each + (CGAL::make_range (boost::counting_iterator(0), + boost::counting_iterator(input.size())), + [&](const std::size_t& s) -> bool + { + std::size_t nb_class_best=0; + std::vector values; + classifier (s, values); -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(std::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - if (std::is_convertible::value) - { - tbb::parallel_for(tbb::blocked_range(0, input.size ()), f); - } - else -#endif - { - for (std::size_t i = 0; i < input.size(); ++ i) - f.apply(i); - } + float val_class_best = 0.f; + for(std::size_t k = 0; k < labels.size(); ++ k) + { + probabilities[k][s] = values[k]; + if(val_class_best < values[k]) + { + val_class_best = values[k]; + nb_class_best = k; + } + } + + output[s] = static_cast(nb_class_best); + + return true; + }); } /// \endcond @@ -460,28 +182,49 @@ namespace internal { { std::vector > values (labels.size(), std::vector (input.size(), -1.)); - internal::Classify_functor_local_smoothing_preprocessing - f1 (labels, classifier, values); - internal::Classify_functor_local_smoothing - f2 (input, item_map, labels, values, neighbor_query, output); -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(std::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - if (std::is_convertible::value) - { - tbb::parallel_for(tbb::blocked_range(0, input.size ()), f1); - tbb::parallel_for(tbb::blocked_range(0, input.size ()), f2); - } - else -#endif - { - for (std::size_t i = 0; i < input.size(); ++ i) - f1.apply(i); - for (std::size_t i = 0; i < input.size(); ++ i) - f2.apply(i); - } + CGAL::for_each + (CGAL::make_range (boost::counting_iterator(0), + boost::counting_iterator(input.size())), + [&](const std::size_t& s) -> bool + { + std::vector v; + classifier(s, v); + for(std::size_t k = 0; k < labels.size(); ++ k) + values[k][s] = v[k]; + + return true; + }); + + CGAL::for_each + (CGAL::make_range (boost::counting_iterator(0), + boost::counting_iterator(input.size())), + [&](const std::size_t& s) -> bool + { + std::vector neighbors; + neighbor_query (get (item_map, *(input.begin()+s)), std::back_inserter (neighbors)); + + std::vector mean (values.size(), 0.); + for (std::size_t n = 0; n < neighbors.size(); ++ n) + for (std::size_t j = 0; j < values.size(); ++ j) + mean[j] += values[j][neighbors[n]]; + + std::size_t nb_class_best=0; + float val_class_best = 0.f; + for(std::size_t k = 0; k < mean.size(); ++ k) + { + mean[k] /= neighbors.size(); + if(val_class_best < mean[k]) + { + val_class_best = mean[k]; + nb_class_best = k; + } + } + + output[s] = static_cast(nb_class_best); + + return true; + }); } /*! @@ -594,23 +337,65 @@ namespace internal { CGAL_assertion_msg (i != bboxes.size(), "Point was not assigned to any subdivision."); } - internal::Classify_functor_graphcut - f (input, item_map, labels, classifier, neighbor_query, strength, indices, input_to_indices, output); + CGAL::for_each + (CGAL::make_range (boost::counting_iterator(0), + boost::counting_iterator(indices.size())), + [&](const std::size_t& sub) -> bool + { + if (indices[sub].empty()) + return true; -#ifndef CGAL_LINKED_WITH_TBB - CGAL_static_assertion_msg (!(std::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); + std::vector > edges; + std::vector edge_weights; + std::vector > probability_matrix + (labels.size(), std::vector(indices[sub].size(), 0.)); + std::vector assigned_label (indices[sub].size()); + + for (std::size_t j = 0; j < indices[sub].size(); ++ j) + { + std::size_t s = indices[sub][j]; + + std::vector neighbors; + + neighbor_query (get(item_map, *(input.begin()+s)), std::back_inserter (neighbors)); + + for (std::size_t i = 0; i < neighbors.size(); ++ i) + if (sub == input_to_indices[neighbors[i]].first + && j != input_to_indices[neighbors[i]].second) + { + edges.push_back (std::make_pair (j, input_to_indices[neighbors[i]].second)); + edge_weights.push_back (strength); + } + + std::vector values; + classifier(s, values); + std::size_t nb_class_best = 0; + float val_class_best = 0.f; + for(std::size_t k = 0; k < labels.size(); ++ k) + { + float value = values[k]; + probability_matrix[k][j] = -std::log(value); + + if(val_class_best < value) + { + val_class_best = value; + nb_class_best = k; + } + } + assigned_label[j] = nb_class_best; + } + +#ifdef CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE + CGAL::internal::Alpha_expansion_graph_cut_boost graphcut; #else - if (std::is_convertible::value) - { - tbb::parallel_for(tbb::blocked_range(0, indices.size ()), f); - } - else + CGAL::internal::Alpha_expansion_graph_cut_boykov_kolmogorov graphcut; #endif - { - for (std::size_t sub = 0; sub < indices.size(); ++ sub) - f.apply (sub); - } + graphcut(edges, edge_weights, probability_matrix, assigned_label); + + for (std::size_t i = 0; i < assigned_label.size(); ++ i) + output[indices[sub][i]] = static_cast(assigned_label[i]); + return true; + }); }