From f9384c3453fc3edfa348ad152feb9d7ca6513747 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 5 Oct 2017 08:49:53 +0200 Subject: [PATCH 01/70] Select random regions + interpret LAS classification property in plugin --- .../Classification/Classification_plugin.cpp | 16 ++- .../Classification/Item_classification_base.h | 1 + .../Point_set_item_classification.cpp | 134 +++++++++++++++--- .../Point_set_item_classification.h | 2 + 4 files changed, 131 insertions(+), 22 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index f9a0c15326c..b5d924e70db 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -157,7 +157,7 @@ public: action_train = ui_widget.menu->menu()->addAction ("Train classifier"); connect(action_train, SIGNAL(triggered()), this, SLOT(on_train_clicked())); - + action_reset = ui_widget.menu->menu()->addAction ("Reset all training sets"); connect(action_reset, SIGNAL(triggered()), this, SLOT(on_reset_training_sets_clicked())); @@ -742,6 +742,20 @@ public Q_SLOTS: classif->validate_selection(); } + void on_select_random_region_clicked() + { + Item_classification_base* classif + = get_classification(); + if(!classif) + { + print_message("Error: there is no point set classification item!"); + return; + } + + classif->select_random_region(); + item_changed(classif->item()); + } + void on_train_clicked() { Item_classification_base* classif diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 0dc2e0947c1..5d48b8137dd 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -40,6 +40,7 @@ public: virtual void reset_training_set (const char* name) = 0; virtual void reset_training_sets() = 0; + virtual void select_random_region() = 0; virtual void validate_selection () = 0; virtual void train(int classifier, unsigned int nb_trials) = 0; virtual bool run (int method, int classifier, std::size_t subdivisions, double smoothing) = 0; 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 523f4efe9ac..e260ad78b6d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -29,10 +29,32 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n boost::tie (m_training, training_found) = m_points->point_set()->add_property_map("training", -1); bool classif_found = false; boost::tie (m_classif, classif_found) = m_points->point_set()->add_property_map("label", -1); - + training_found = !training_found; // add_property_map returns false if classif_found = !classif_found; // property was already there - + + bool las_found = false; + + if (!classif_found) + { + Point_set::Property_map las_classif; + boost::tie (las_classif, las_found) = m_points->point_set()->property_map("classification"); + if (las_found) + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + unsigned char uc = las_classif[*it]; + m_classif[*it] = int(uc); + if (!training_found) + m_training[*it] = int(uc); + } + m_points->point_set()->remove_property_map (las_classif); + classif_found = true; + training_found = true; + } + } + if (training_found || classif_found) { int lmax = 0; @@ -51,22 +73,47 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n lmax = (std::max)(l, lmax); } } - - // Try to recover label names from PLY comments + std::map label_names; - const std::string& comments = m_points->comments(); - std::istringstream stream (comments); - std::string line; - while (getline(stream, line)) + if (las_found) // Use LAS standard { - std::stringstream iss (line); - std::string tag; - if (iss >> tag && tag == "label") + label_names.insert (std::make_pair (0, std::string("never_clfied"))); + label_names.insert (std::make_pair (1, std::string("unclassified"))); + label_names.insert (std::make_pair (2, std::string("ground"))); + label_names.insert (std::make_pair (3, std::string("low_veget"))); + label_names.insert (std::make_pair (4, std::string("med_veget"))); + label_names.insert (std::make_pair (5, std::string("high_veget"))); + label_names.insert (std::make_pair (6, std::string("building"))); + label_names.insert (std::make_pair (7, std::string("noise"))); + label_names.insert (std::make_pair (8, std::string("reserved"))); + label_names.insert (std::make_pair (9, std::string("water"))); + label_names.insert (std::make_pair (10, std::string("rail"))); + label_names.insert (std::make_pair (11, std::string("road surface"))); + label_names.insert (std::make_pair (12, std::string("reserved_2"))); + label_names.insert (std::make_pair (13, std::string("wire_guard"))); + label_names.insert (std::make_pair (14, std::string("wire_conduct"))); + label_names.insert (std::make_pair (15, std::string("trans_tower"))); + label_names.insert (std::make_pair (16, std::string("wire_connect"))); + label_names.insert (std::make_pair (17, std::string("bridge_deck"))); + label_names.insert (std::make_pair (18, std::string("high_noise"))); + } + else // Try to recover label names from PLY comments + { + + const std::string& comments = m_points->comments(); + std::istringstream stream (comments); + std::string line; + while (getline(stream, line)) { - int idx; - std::string name; - if (iss >> idx >> name) - label_names.insert (std::make_pair (idx, name)); + std::stringstream iss (line); + std::string tag; + if (iss >> tag && tag == "label") + { + int idx; + std::string name; + if (iss >> idx >> name) + label_names.insert (std::make_pair (idx, name)); + } } } @@ -83,12 +130,9 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n m_labels.add(oss.str().c_str()); } - CGAL::Classification::HSV_Color hsv; - hsv[0] = 360. * (i / double(lmax + 1)); - hsv[1] = 76.; - hsv[2] = 85.; - Color rgb = CGAL::Classification::hsv_to_rgb(hsv); - m_label_colors.push_back (QColor(rgb[0], rgb[1], rgb[2])); + m_label_colors.push_back (QColor (64 + rand() % 192, + 64 + rand() % 192, + 64 + rand() % 192)); } } else @@ -369,7 +413,55 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) std::cerr << "Features = " << m_features.size() << std::endl; } +void Point_set_item_classification::select_random_region() +{ + m_points->point_set()->reset_indices(); + + std::size_t scale = (rand() % m_generator->number_of_scales()); + bool use_grid = (rand() % 2); + + std::vector selected; + + if (use_grid) + { + std::size_t x = (rand() % m_generator->grid(scale).width()); + std::size_t y = (rand() % m_generator->grid(scale).height()); + std::copy (m_generator->grid(scale).indices_begin(x,y), + m_generator->grid(scale).indices_end(x,y), + std::back_inserter (selected)); + } + else + { + m_generator->neighborhood(0).sphere_neighbor_query (m_generator->radius_neighbors(scale)) + (*(m_points->point_set()->points().begin() + (rand() % m_points->point_set()->size())), + std::back_inserter (selected)); + } + + if (selected.empty()) + return; + + std::sort (selected.begin(), selected.end()); + std::size_t current_idx = 0; + + std::vector unselected; + + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->end(); ++ it) + if (std::size_t(*it) == selected[current_idx]) + current_idx ++; + else + unselected.push_back (*it); + + for (std::size_t i = 0; i < unselected.size(); ++ i) + *(m_points->point_set()->begin() + i) = unselected[i]; + for (std::size_t i = 0; i < selected.size(); ++ i) + *(m_points->point_set()->begin() + (unselected.size() + i)) = selected[i]; + + m_points->point_set()->set_first_selected + (m_points->point_set()->begin() + unselected.size()); + +} void Point_set_item_classification::train(int classifier, unsigned int nb_trials) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index ee15079e8fd..12450aa9e78 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -46,6 +46,8 @@ class Point_set_item_classification : public Item_classification_base void erase_item() { m_points = NULL; } void compute_features (std::size_t nb_scales); + + void select_random_region(); void add_selection_to_training_set (const char* name) { From b74b1fd226c40c609d927c4a15852128f1701b36 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 5 Oct 2017 09:50:45 +0200 Subject: [PATCH 02/70] Filter unused indices in plugin --- .../Point_set_item_classification.cpp | 65 +++++++++++++++++-- 1 file changed, 58 insertions(+), 7 deletions(-) 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 e260ad78b6d..e721e65d681 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -57,7 +57,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n if (training_found || classif_found) { - int lmax = 0; + std::vector used_indices; for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) @@ -65,20 +65,68 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n if (training_found) { int l = m_training[*it]; - lmax = (std::max)(l, lmax); + if (l >= 0) + { + if (std::size_t(l) >= used_indices.size()) + used_indices.resize(std::size_t(l + 1), -1); + used_indices[std::size_t(l)] = 0; + } } if (classif_found) { int l = m_classif[*it]; - lmax = (std::max)(l, lmax); + if (l >= 0) + { + if (std::size_t(l) >= used_indices.size()) + used_indices.resize(std::size_t(l + 1), -1); + used_indices[std::size_t(l)] = 0; + } + } + } + + // map indices to filtered indices + int current_idx = 0; + for (std::size_t i = 0; i < used_indices.size(); ++ i) + { + if (las_found && i < 2) + { + used_indices[i] = -1; + continue; + } + if (used_indices[i] == -1) + continue; + + used_indices[i] = current_idx; + ++ current_idx; + } + + if (current_idx != used_indices.size()) // Empty indices -> reorder indices in point set + { + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->first_selected(); ++ it) + { + if (training_found) + { + if (las_found && (m_training[*it] == 0 || m_training[*it] == 1)) // Unclassified class in LAS + m_training[*it] = -1; + else if (m_training[*it] != -1) + m_training[*it] = used_indices[std::size_t(m_training[*it])]; + } + if (classif_found) + { + if (las_found && (m_classif[*it] == 0 || m_classif[*it] == 1)) // Unclassified class in LAS + m_classif[*it] = -1; + else if (m_classif[*it] != -1) + m_classif[*it] = used_indices[std::size_t(m_classif[*it])]; + } } } std::map label_names; if (las_found) // Use LAS standard { - label_names.insert (std::make_pair (0, std::string("never_clfied"))); - label_names.insert (std::make_pair (1, std::string("unclassified"))); + // label_names.insert (std::make_pair (0, std::string("never_clfied"))); + // label_names.insert (std::make_pair (1, std::string("unclassified"))); label_names.insert (std::make_pair (2, std::string("ground"))); label_names.insert (std::make_pair (3, std::string("low_veget"))); label_names.insert (std::make_pair (4, std::string("med_veget"))); @@ -117,9 +165,12 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n } } - for (int i = 0; i <= lmax; ++ i) + for (int i = 0; i < used_indices.size(); ++ i) { - std::map::iterator found + if (used_indices[i] == std::size_t(-1)) + continue; + + typename std::map::iterator found = label_names.find (i); if (found != label_names.end()) m_labels.add(found->second.c_str()); From dce942dd7ef9120f649a6ef2a1a9f41090b83f8c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 5 Oct 2017 14:38:11 +0200 Subject: [PATCH 03/70] Bugfix: sort features by name after generation --- .../include/CGAL/Classification/Feature_set.h | 14 ++++++++++++++ .../Classification/Point_set_feature_generator.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/Classification/include/CGAL/Classification/Feature_set.h b/Classification/include/CGAL/Classification/Feature_set.h index a620c64bff0..2c68d4112d0 100644 --- a/Classification/include/CGAL/Classification/Feature_set.h +++ b/Classification/include/CGAL/Classification/Feature_set.h @@ -47,6 +47,14 @@ class Feature_set { typedef std::vector Base; Base m_features; + + struct Compare_name + { + bool operator() (const Feature_handle& a, const Feature_handle& b) const + { + return a->name() < b->name(); + } + }; #ifdef CGAL_LINKED_WITH_TBB tbb::mutex m_mutex; @@ -136,6 +144,12 @@ public: { m_features[i] = Feature_handle(); } + + void sort_features_by_name() + { + std::sort (m_features.begin(), m_features.end(), + Compare_name()); + } /// \endcond }; diff --git a/Classification/include/CGAL/Classification/Point_set_feature_generator.h b/Classification/include/CGAL/Classification/Point_set_feature_generator.h index ced5fa9b39e..006a4885edc 100644 --- a/Classification/include/CGAL/Classification/Point_set_feature_generator.h +++ b/Classification/include/CGAL/Classification/Point_set_feature_generator.h @@ -343,6 +343,8 @@ public: get_parameter(normal_map), get_parameter(color_map), get_parameter(echo_map)); + + m_features->sort_features_by_name(); } From a3ff9f72b123ff6a6aeb50d6e5c47f7241ca95b2 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 5 Oct 2017 14:39:22 +0200 Subject: [PATCH 04/70] Add #define to activate quick estimation in training --- .../Sum_of_weighted_features_classifier.h | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Classification/include/CGAL/Classification/Sum_of_weighted_features_classifier.h b/Classification/include/CGAL/Classification/Sum_of_weighted_features_classifier.h index 99270a0bebd..539cd299ec3 100644 --- a/Classification/include/CGAL/Classification/Sum_of_weighted_features_classifier.h +++ b/Classification/include/CGAL/Classification/Sum_of_weighted_features_classifier.h @@ -42,6 +42,7 @@ #include #endif // CGAL_LINKED_WITH_TBB +#define CLASSIFICATION_TRAINING_QUICK_ESTIMATION namespace CGAL { @@ -311,6 +312,11 @@ public: ++ nb_tot; } +#ifdef CLASSIFICATION_TRAINING_QUICK_ESTIMATION + for (std::size_t i = 0; i < m_labels.size(); ++ i) + std::random_shuffle (training_sets[i].begin(), training_sets[i].end()); +#endif + CGAL_CLASSIFICATION_CERR << "Training using " << nb_tot << " inliers" << std::endl; for (std::size_t i = 0; i < m_labels.size(); ++ i) @@ -841,12 +847,19 @@ private: for (std::size_t j = 0; j < m_labels.size(); ++ j) { - for (std::size_t k = 0; k < training_sets[j].size(); ++ k) +#ifdef CLASSIFICATION_TRAINING_QUICK_ESTIMATION + std::size_t training_set_size = (std::min) (std::size_t(0.1 * training_sets[j].size()), + std::size_t(10000)); +#else + std::size_t training_set_size = training_sets[j].size(); +#endif + + for (std::size_t k = 0; k < training_set_size; ++ k) { float val = normalized(feature, training_sets[j][k]); mean[j] += val; } - mean[j] /= training_sets[j].size(); + mean[j] /= training_set_size; } std::vector sd (m_labels.size(), 0.); @@ -855,12 +868,18 @@ private: { Label_handle clabel = m_labels[j]; - for (std::size_t k = 0; k < training_sets[j].size(); ++ k) +#ifdef CLASSIFICATION_TRAINING_QUICK_ESTIMATION + std::size_t training_set_size = (std::min) (std::size_t(0.1 * training_sets[j].size()), + std::size_t(10000)); +#else + std::size_t training_set_size = training_sets[j].size(); +#endif + for (std::size_t k = 0; k < training_set_size; ++ k) { float val = normalized(feature, training_sets[j][k]); sd[j] += (val - mean[j]) * (val - mean[j]); } - sd[j] = std::sqrt (sd[j] / training_sets[j].size()); + sd[j] = std::sqrt (sd[j] / training_set_size); if (mean[j] - sd[j] > (2./3.)) set_effect (j, feature, FAVORING); else if (mean[j] + sd[j] < (1./3.)) From 345e10671b2b40c4108643a3cf90346ef287d31e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 6 Oct 2017 09:38:51 +0200 Subject: [PATCH 05/70] Better handling of OpenCV dependency in plugin + timers --- .../Classification/Classification_plugin.cpp | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index b5d924e70db..8cb21f71cfe 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -15,6 +15,7 @@ #include #include +#include #include "ui_Classification_widget.h" @@ -140,8 +141,10 @@ public: ui_widget.setupUi(dock_widget); addDockWidget(dock_widget); -#ifndef CGAL_LINKED_WITH_OPENCV - ui_widget.classifier->removeItem(1); +#ifdef CGAL_LINKED_WITH_OPENCV + ui_widget.classifier->addItem (tr("Random Forest (OpenCV %1.%2)") + .arg(CV_MAJOR_VERSION) + .arg(CV_MINOR_VERSION)); #endif color_att = QColor (75, 75, 77); @@ -515,7 +518,11 @@ public Q_SLOTS: return; } QApplication::setOverrideCursor(Qt::WaitCursor); + CGAL::Real_timer t; + t.start(); run (classif, 0); + t.stop(); + std::cerr << "Raw classification computed in " << t.time() << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); item_changed(classif->item()); } @@ -531,10 +538,11 @@ public Q_SLOTS: } QApplication::setOverrideCursor(Qt::WaitCursor); - QTime time; - time.start(); + CGAL::Real_timer t; + t.start(); run (classif, 1); - std::cerr << "Smoothed classification computed in " << time.elapsed() / 1000 << " second(s)" << std::endl; + t.stop(); + std::cerr << "Smoothed classification computed in " << t.time() << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); item_changed(classif->item()); } @@ -567,6 +575,7 @@ public Q_SLOTS: QDialogButtonBox oknotok (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); + form.addRow (&oknotok); QObject::connect (&oknotok, SIGNAL(accepted()), &dialog, SLOT(accept())); QObject::connect (&oknotok, SIGNAL(rejected()), &dialog, SLOT(reject())); @@ -575,10 +584,11 @@ public Q_SLOTS: return; QApplication::setOverrideCursor(Qt::WaitCursor); - QTime time; - time.start(); + CGAL::Real_timer t; + t.start(); run (classif, 2, std::size_t(subdivisions.value()), smoothing.value()); - std::cerr << "Graphcut classification computed in " << time.elapsed() / 1000 << " second(s)" << std::endl; + t.stop(); + std::cerr << "Graph Cut classification computed in " << t.time() << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); item_changed(classif->item()); } @@ -789,7 +799,11 @@ public Q_SLOTS: } QApplication::setOverrideCursor(Qt::WaitCursor); + CGAL::Real_timer t; + t.start(); classif->train(ui_widget.classifier->currentIndex(), nb_trials); + t.stop(); + std::cerr << "Done in " << t.time() << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); update_plugin_from_item(classif); } From f63a28063bfc1153bbcbb4242032f4085d810a9b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 6 Oct 2017 10:00:15 +0200 Subject: [PATCH 06/70] Add simple feature using simply a range and a property map --- Classification/include/CGAL/Classification.h | 1 + .../Classification/Feature/Simple_feature.h | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 Classification/include/CGAL/Classification/Feature/Simple_feature.h diff --git a/Classification/include/CGAL/Classification.h b/Classification/include/CGAL/Classification.h index fede1a2c6e4..b1e0a1fb3d4 100644 --- a/Classification/include/CGAL/Classification.h +++ b/Classification/include/CGAL/Classification.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #include diff --git a/Classification/include/CGAL/Classification/Feature/Simple_feature.h b/Classification/include/CGAL/Classification/Feature/Simple_feature.h new file mode 100644 index 00000000000..7ea43a46bf3 --- /dev/null +++ b/Classification/include/CGAL/Classification/Feature/Simple_feature.h @@ -0,0 +1,79 @@ +// Copyright (c) 2017 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Simon Giraudot + +#ifndef CGAL_CLASSIFICATION_SIMPLE_FEATURE_H +#define CGAL_CLASSIFICATION_SIMPLE_FEATURE_H + +#include + +#include + +namespace CGAL { + +namespace Classification { + +namespace Feature { + + /*! + \ingroup PkgClassificationFeatures + + %Feature based on a user-defined scalar field. + + \tparam InputRange model of `ConstRange`. Its iterator type + is `RandomAccessIterator`. + \tparam PropertyMap model of `ReadablePropertyMap` whose key + type is the value type of the iterator of `PointRange` and value type + is statically castable to `float`. + */ +template +class Simple_feature : public Feature_base +{ + const InputRange& m_input; + PropertyMap m_pmap; + +public: + /*! + \brief Constructs the feature using an input range and a property map. + + \param input point range. + \param property_map property map to access scalar field. + \param name name of the property (no default name is given). + */ + Simple_feature (const InputRange& input, + PropertyMap property_map, + const std::string& name) + : m_input (input), m_pmap (property_map) + { + this->set_name (name); + } + /// \cond SKIP_IN_MANUAL + virtual float value (std::size_t pt_index) + { + return static_cast (get (m_pmap, *(m_input.begin()+pt_index))); + } + /// \endcond +}; + +} // namespace Feature + +} // namespace Classification + +} // namespace CGAL + +#endif // CGAL_CLASSIFICATION_SIMPLE_FEATURE_H From 9285ffb6fdb07ff00e7395cb51221d294f5adc65 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 6 Oct 2017 10:01:07 +0200 Subject: [PATCH 07/70] Add all properties in point set as classification feature --- .../Point_set_item_classification.cpp | 52 +++++++++++++++++-- .../Point_set_item_classification.h | 17 +++++- 2 files changed, 64 insertions(+), 5 deletions(-) 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 e721e65d681..3308563aab9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -88,7 +88,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n int current_idx = 0; for (std::size_t i = 0; i < used_indices.size(); ++ i) { - if (las_found && i < 2) + if (las_found && (i < 2 || i == 7 || i == 18)) { used_indices[i] = -1; continue; @@ -100,7 +100,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n ++ current_idx; } - if (current_idx != used_indices.size()) // Empty indices -> reorder indices in point set + if (std::size_t(current_idx) != used_indices.size()) // Empty indices -> reorder indices in point set { for (Point_set::const_iterator it = m_points->point_set()->begin(); it != m_points->point_set()->first_selected(); ++ it) @@ -165,9 +165,9 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n } } - for (int i = 0; i < used_indices.size(); ++ i) + for (std::size_t i = 0; i < used_indices.size(); ++ i) { - if (used_indices[i] == std::size_t(-1)) + if (used_indices[i] == -1) continue; typename std::map::iterator found @@ -430,6 +430,10 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) Point_set::Property_map echo_map; bool echo; boost::tie (echo_map, echo) = m_points->point_set()->template property_map("echo"); + if (!echo) + boost::tie (echo_map, echo) = m_points->point_set()->template property_map("number_of_returns"); + + 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); @@ -464,6 +468,46 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) std::cerr << "Features = " << m_features.size() << std::endl; } + + +void Point_set_item_classification::add_remaining_point_set_properties_as_features() +{ + const std::vector& prop = m_points->point_set()->base().properties(); + + for (std::size_t i = 0; i < prop.size(); ++ i) + { + if (prop[i] == "index" || + prop[i] == "point" || + prop[i] == "normal" || + prop[i] == "echo" || + prop[i] == "number_of_returns" || + prop[i] == "training" || + prop[i] == "label" || + prop[i] == "classification" || + prop[i] == "real_color" || + prop[i] == "red" || prop[i] == "green" || prop[i] == "blue" || + prop[i] == "r" || prop[i] == "g" || prop[i] == "b") + continue; + + if (try_adding_simple_feature(prop[i])) + continue; + if (try_adding_simple_feature(prop[i])) + continue; + if (try_adding_simple_feature(prop[i])) + continue; + if (try_adding_simple_feature(prop[i])) + continue; + if (try_adding_simple_feature(prop[i])) + continue; + if (try_adding_simple_feature(prop[i])) + continue; + if (try_adding_simple_feature(prop[i])) + continue; + if (try_adding_simple_feature(prop[i])) + continue; + } +} + void Point_set_item_classification::select_random_region() { m_points->point_set()->reset_indices(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index 12450aa9e78..2320838a815 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -46,8 +46,23 @@ class Point_set_item_classification : public Item_classification_base void erase_item() { m_points = NULL; } void compute_features (std::size_t nb_scales); - + void add_remaining_point_set_properties_as_features(); + void select_random_region(); + + template + bool try_adding_simple_feature (const std::string& name) + { + typedef typename Point_set::template Property_map Pmap; + bool okay = false; + Pmap pmap; + boost::tie (pmap, okay) = m_points->point_set()->template property_map(name.c_str()); + if (okay) + m_features.template add > + (*(m_points->point_set()), pmap, name.c_str()); + + return okay; + } void add_selection_to_training_set (const char* name) { From 75d11d288e0d1ddba197330a872e104808fcb7bc Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 9 Oct 2017 11:48:03 +0200 Subject: [PATCH 08/70] Use a set of default colors for preexisting labels --- .../Point_set_item_classification.cpp | 62 +++++++++++++++---- 1 file changed, 51 insertions(+), 11 deletions(-) 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 3308563aab9..f0550c36fe8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -136,7 +136,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n label_names.insert (std::make_pair (8, std::string("reserved"))); label_names.insert (std::make_pair (9, std::string("water"))); label_names.insert (std::make_pair (10, std::string("rail"))); - label_names.insert (std::make_pair (11, std::string("road surface"))); + label_names.insert (std::make_pair (11, std::string("road_surface"))); label_names.insert (std::make_pair (12, std::string("reserved_2"))); label_names.insert (std::make_pair (13, std::string("wire_guard"))); label_names.insert (std::make_pair (14, std::string("wire_conduct"))); @@ -169,21 +169,61 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n { if (used_indices[i] == -1) continue; - + + Label_handle new_label; typename std::map::iterator found = label_names.find (i); if (found != label_names.end()) - m_labels.add(found->second.c_str()); + new_label = m_labels.add(found->second.c_str()); else { std::ostringstream oss; oss << "label_" << i; - m_labels.add(oss.str().c_str()); + new_label = m_labels.add(oss.str().c_str()); } + + QColor color (64 + rand() % 192, + 64 + rand() % 192, + 64 + rand() % 192); - m_label_colors.push_back (QColor (64 + rand() % 192, - 64 + rand() % 192, - 64 + rand() % 192)); + if (new_label->name() == "ground") + color = QColor (186, 189, 182); + else if (new_label->name() == "low_veget") + color = QColor (78, 154, 6); + else if (new_label->name() == "med_veget" + || new_label->name() == "vegetation") + color = QColor (138, 226, 52); + else if (new_label->name() == "high_veget") + color = QColor (204, 255, 201); + else if (new_label->name() == "building" + || new_label->name() == "roof") + color = QColor (245, 121, 0); + else if (new_label->name() == "noise") + color = QColor (0, 0, 0); + else if (new_label->name() == "reserved") + color = QColor (233, 185, 110); + else if (new_label->name() == "water") + color = QColor (114, 159, 207); + else if (new_label->name() == "rail") + color = QColor (136, 46, 25); + else if (new_label->name() == "road_surface") + color = QColor (56, 56, 56); + else if (new_label->name() == "reserved_2") + color = QColor (193, 138, 51); + else if (new_label->name() == "wire_guard") + color = QColor (37, 61, 136); + else if (new_label->name() == "wire_conduct") + color = QColor (173, 127, 168); + else if (new_label->name() == "trans_tower") + color = QColor (136, 138, 133); + else if (new_label->name() == "wire_connect") + color = QColor (145, 64, 236); + else if (new_label->name() == "bridge_deck") + color = QColor (213, 93, 93); + else if (new_label->name() == "high_noise") + color = QColor (255, 0, 0); + + m_label_colors.push_back (color); } } else @@ -193,10 +233,10 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n m_labels.add("roof"); m_labels.add("facade"); - m_label_colors.push_back (QColor(245, 180, 0)); - m_label_colors.push_back (QColor(0, 255, 27)); - m_label_colors.push_back (QColor(255, 0, 170)); - m_label_colors.push_back (QColor(100, 0, 255)); + m_label_colors.push_back (QColor(186, 189, 182)); + m_label_colors.push_back (QColor(138, 226, 52)); + m_label_colors.push_back (QColor(245, 121, 0)); + m_label_colors.push_back (QColor(233, 185, 110)); } update_comments_of_point_set_item(); From 075ffb8506dff4546c3c1d8a5e6ba7b2b15fe3ed Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 9 Oct 2017 17:03:52 +0200 Subject: [PATCH 09/70] Evaluation: avoid NaN in general measurements when label empty --- .../include/CGAL/Classification/Evaluation.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Classification/include/CGAL/Classification/Evaluation.h b/Classification/include/CGAL/Classification/Evaluation.h index efac04de9d1..9c69b08cd6e 100644 --- a/Classification/include/CGAL/Classification/Evaluation.h +++ b/Classification/include/CGAL/Classification/Evaluation.h @@ -106,6 +106,8 @@ public: m_mean_iou = 0.; m_mean_f1 = 0.; + + std::size_t correct_labels = 0; for (std::size_t j = 0; j < labels.size(); ++ j) { @@ -113,13 +115,17 @@ public: m_recall[j] = true_positives[j] / float(true_positives[j] + false_negatives[j]); m_iou[j] = true_positives[j] / float(true_positives[j] + false_positives[j] + false_negatives[j]); + if (std::isnan(m_iou[j])) + continue; + + ++ correct_labels; m_mean_iou += m_iou[j]; m_mean_f1 += 2.f * (m_precision[j] * m_recall[j]) / (m_precision[j] + m_recall[j]); } - m_mean_iou /= labels.size(); - m_mean_f1 /= labels.size(); + m_mean_iou /= correct_labels; + m_mean_f1 /= correct_labels; m_accuracy = sum_true_positives / float(total); } From 484798042204f89d06f53d7c78a05017188ea611 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 10 Oct 2017 14:15:58 +0200 Subject: [PATCH 10/70] remove extra typename --- .../Plugins/Classification/Point_set_item_classification.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f0550c36fe8..568e8308933 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -171,7 +171,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n continue; Label_handle new_label; - typename std::map::iterator found + std::map::iterator found = label_names.find (i); if (found != label_names.end()) new_label = m_labels.add(found->second.c_str()); From 39a779b9b4238d887d4e05a15e3d95406bcfaf03 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 12 Oct 2017 12:00:04 +0200 Subject: [PATCH 11/70] Remove random forest item from default widget --- .../Plugins/Classification/Classification_widget.ui | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui index e251fd74128..c97af373bb2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_widget.ui @@ -105,11 +105,6 @@ Sum of Weighted Features - - - Random Forest - - From c50c12a451dec01eb203880f7d4dd2556b9223b4 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 5 Oct 2017 08:49:53 +0200 Subject: [PATCH 12/70] Select random regions + interpret LAS classification property in plugin --- .../Point_set_item_classification.cpp | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) 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 568e8308933..28558670b10 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -508,7 +508,55 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) std::cerr << "Features = " << m_features.size() << std::endl; } +void Point_set_item_classification::select_random_region() +{ + m_points->point_set()->reset_indices(); + + std::size_t scale = (rand() % m_generator->number_of_scales()); + bool use_grid = (rand() % 2); + + std::vector selected; + + if (use_grid) + { + std::size_t x = (rand() % m_generator->grid(scale).width()); + std::size_t y = (rand() % m_generator->grid(scale).height()); + std::copy (m_generator->grid(scale).indices_begin(x,y), + m_generator->grid(scale).indices_end(x,y), + std::back_inserter (selected)); + } + else + { + m_generator->neighborhood(0).sphere_neighbor_query (m_generator->radius_neighbors(scale)) + (*(m_points->point_set()->points().begin() + (rand() % m_points->point_set()->size())), + std::back_inserter (selected)); + } + + if (selected.empty()) + return; + + std::sort (selected.begin(), selected.end()); + std::size_t current_idx = 0; + + std::vector unselected; + + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->end(); ++ it) + if (std::size_t(*it) == selected[current_idx]) + current_idx ++; + else + unselected.push_back (*it); + + for (std::size_t i = 0; i < unselected.size(); ++ i) + *(m_points->point_set()->begin() + i) = unselected[i]; + for (std::size_t i = 0; i < selected.size(); ++ i) + *(m_points->point_set()->begin() + (unselected.size() + i)) = selected[i]; + + m_points->point_set()->set_first_selected + (m_points->point_set()->begin() + unselected.size()); + +} void Point_set_item_classification::add_remaining_point_set_properties_as_features() { From bb03a73ffcfae3829a820629ca8932af28ffae17 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 4 Oct 2017 15:50:32 +0200 Subject: [PATCH 13/70] Better organisation of classification plugin --- .../Polyhedron/Plugins/Classification/Classification_plugin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 8cb21f71cfe..c8064cd74c8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -575,7 +575,6 @@ public Q_SLOTS: QDialogButtonBox oknotok (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); - form.addRow (&oknotok); QObject::connect (&oknotok, SIGNAL(accepted()), &dialog, SLOT(accept())); QObject::connect (&oknotok, SIGNAL(rejected()), &dialog, SLOT(reject())); From ad20e132d85b5d6e072cd349c46d201b1e5c895b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 6 Oct 2017 10:01:45 +0200 Subject: [PATCH 14/70] Include ETZH source code --- .../include/CGAL/Classification/dataview.h | 141 ++++++++ .../random-forest/common-libraries.hpp | 306 ++++++++++++++++++ .../Classification/random-forest/forest.hpp | 146 +++++++++ .../random-forest/node-gini.hpp | 81 +++++ .../Classification/random-forest/node.hpp | 221 +++++++++++++ .../Classification/random-forest/tree.hpp | 110 +++++++ 6 files changed, 1005 insertions(+) create mode 100644 Classification/include/CGAL/Classification/dataview.h create mode 100644 Classification/include/CGAL/Classification/random-forest/common-libraries.hpp create mode 100644 Classification/include/CGAL/Classification/random-forest/forest.hpp create mode 100644 Classification/include/CGAL/Classification/random-forest/node-gini.hpp create mode 100644 Classification/include/CGAL/Classification/random-forest/node.hpp create mode 100644 Classification/include/CGAL/Classification/random-forest/tree.hpp diff --git a/Classification/include/CGAL/Classification/dataview.h b/Classification/include/CGAL/Classification/dataview.h new file mode 100644 index 00000000000..e8a1ee9b3f9 --- /dev/null +++ b/Classification/include/CGAL/Classification/dataview.h @@ -0,0 +1,141 @@ +#ifndef LIBLEARNING_DATAVIEW_H +#define LIBLEARNING_DATAVIEW_H +#include +namespace liblearning { +//! \brief A view for one-dimensional data +// +// The data can be e.g. a row or column of a matrix or the elements of an +// array or a std::vector - anything with a fixed step size between pointers +template +struct DataView1D { + //! \brief Element access + // + // \param idx the index of the element + ElementType& operator()(size_t idx) const + { + return *(data + step * idx); + } + //! \brief Construct using pointer, size and (optional) step size + DataView1D(ElementType* ptr, size_t size, ptrdiff_t step_size = 1) : + data(ptr), step(step_size), num_elements(size) + { + } + //! \brief Construct view from std::vector + // + // \param vec the vector, by-ref since we don't take ownership - no + // temporaries allowed. maybe needs to change + DataView1D(std::vector& vec) : + data(&vec[0]), step(1), num_elements(vec.size()) + { + } + + //! \brief Construct empty view + DataView1D() : data(0), step(1), num_elements(0) + { + } + ElementType* data; //!< Pointer to first element + ptrdiff_t step; //!< Step size between elements - for a vector this is 1, no need to multiply by sizeof(ElementType) + size_t num_elements; //!< Number of elements in the view +}; + +template +struct DataView2D { + //! \brief Construct empty view + DataView2D() : data(0), row_step(1), col_step(1), rows(0), cols(0) + {} + //! \brief Construct view from memory using given step sizes + DataView2D(ElementType* ptr, size_t rows_, size_t cols_, ptrdiff_t row_step_, ptrdiff_t col_step_) : + data(ptr), row_step(row_step_), col_step(col_step_), rows(rows_), cols(cols_) + { + } + //! \brief Construct view from a continuous block of memory in row-major order + DataView2D(ElementType* ptr, size_t rows_, size_t cols_) : + data(ptr), row_step(cols_), col_step(1), rows(rows_), cols(cols_) + { + } + //! \brief Element access + ElementType& operator()(size_t row_idx, size_t col_idx) const + { + return *(data + row_step * row_idx + col_step * col_idx); + } + //! \brief Return a 1D view of a row + DataView1D row(size_t row_idx) + { + return DataView1D(data + row_step * row_idx, cols, col_step); + } + //! \brief Return a 1D view of a column + DataView1D col(size_t col_idx) + { + return DataView1D(data + col_step * col_idx, rows, row_step); + } + //! \brief Return a new view, using a subset of rows + DataView2D row_range(size_t start_row, size_t end_row) const + { + DataView2D ret(*this); + ret.data = data + row_step * start_row; + ret.rows = end_row - start_row; + return ret; + } + //! \brief Return a new view, using a subset of columns + DataView2D col_range(size_t start_col, size_t end_col) const + { + DataView2D ret(*this); + ret.data = data + col_step * start_col; + ret.cols = end_col - start_col; + return ret; + } + //! \brief Transpose the matrix (actually done by swapping the steps, no + // copying) + DataView2D transpose() const + { + DataView2D ret(*this); + std::swap(ret.row_step, ret.col_step); + std::swap(ret.rows, ret.cols); + return ret; + } + //! \brief Create a 2D view from a 1D one, represent as a column + static DataView2D column(DataView1D vec) + { + return DataView2D(vec.data, vec.num_elements, 1); + } + //! \brief Create a 2D view from a 1D one, represent as a row + static DataView2D row(DataView1D vec) + { + return DataView2D(vec.data, 1, vec.num_elements); + } + //! \brief Return the number of elements in this view + size_t num_elements() { return rows * cols; } + //! \brief Return true if the view is empty (no elements) + bool empty() { return num_elements() == 0; } + //! \brief Return true if rows in this view are continuous in memory + bool row_continuous() { + return col_step == 1; + } + //! \brief Return true if columns in this view are continuous in memory + bool col_continuous() { + return row_step == 1; + } + //! \brief Get pointer to row (only valid if row-continuous) + ElementType* row_pointer(size_t row_idx) { + return data + row_idx * row_step; + } + //! \brief Get pointer to column (only valid if column-continuous) + ElementType* col_pointer(size_t col_idx) { + return data + col_idx * col_step; + } + + ElementType* data; //!< Pointer to first element + ptrdiff_t row_step; //!< Pointer difference between an element and its right neighbor - 1 if row-continuous + ptrdiff_t col_step; //!< Pointer difference between an element and its bottom neighbor - 1 if column-continuous + size_t rows; //!< Number of rows in the view + size_t cols; //!< Number of columns in the view +}; + +//! \brief Determine if two 2D views have the same dimensions +template +bool equal_dims(DataView2D view_a, DataView2D view_b) +{ + return view_a.rows == view_b.rows && view_a.cols == view_b.cols; +} +} +#endif diff --git a/Classification/include/CGAL/Classification/random-forest/common-libraries.hpp b/Classification/include/CGAL/Classification/random-forest/common-libraries.hpp new file mode 100644 index 00000000000..41c2dcaefe7 --- /dev/null +++ b/Classification/include/CGAL/Classification/random-forest/common-libraries.hpp @@ -0,0 +1,306 @@ +#ifndef LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H +#define LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if BOOST_VERSION >= 104700 +# include +#else +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../dataview.h" + +namespace liblearning { +namespace RandomForest { + +typedef std::vector< std::pair > FeatureClassDataFloat; +inline void init_feature_class_data(FeatureClassDataFloat& data, int /*n_classes*/, int n_samples) +{ + data.resize(n_samples); +} +typedef boost::unordered_set FeatureSet; + +#if BOOST_VERSION >= 104700 +typedef boost::random::uniform_int_distribution<> UniformIntDist; +typedef boost::random::normal_distribution<> NormalDist; +typedef boost::random::mt19937 RandomGen; +typedef boost::random::uniform_01<> UnitDist; +#else +typedef boost::uniform_int<> UniformIntDist; +typedef boost::normal_distribution<> NormalDist; +typedef boost::uniform_01<> UnitDist; +typedef boost::mt19937 RandomGen; +#endif + +struct ForestParams { + size_t n_classes; + size_t n_features; + size_t n_samples; + size_t n_in_bag_samples; + size_t max_depth; + size_t n_trees; + size_t min_samples_per_node; + float sample_reduction; + ForestParams() : + n_classes(0), + n_features(0), + n_samples(0), + n_in_bag_samples(0), + max_depth(42), + n_trees(100), + min_samples_per_node(5), + sample_reduction(0) + {} + template + void serialize(Archive& ar, unsigned /*version*/) + { + ar & BOOST_SERIALIZATION_NVP(n_classes); + ar & BOOST_SERIALIZATION_NVP(n_features); + ar & BOOST_SERIALIZATION_NVP(n_samples); + ar & BOOST_SERIALIZATION_NVP(n_in_bag_samples); + ar & BOOST_SERIALIZATION_NVP(max_depth); + ar & BOOST_SERIALIZATION_NVP(n_trees); + ar & BOOST_SERIALIZATION_NVP(min_samples_per_node); + ar & BOOST_SERIALIZATION_NVP(sample_reduction); + } +}; + +struct QuadraticSplitter { + typedef float FeatureType; + typedef FeatureClassDataFloat FeatureClassData; + int n_features; + std::vector w; + FeatureType threshold; + QuadraticSplitter() : n_features(0) {} + QuadraticSplitter(int n_features, std::vector const& w) : + n_features(n_features), w(w) + {} + void set_threshold(FeatureType new_threshold) { + threshold = new_threshold; + } + FeatureType map_sample(FeatureType const* v) const { + double result = 0.0; + int i_feature = 0; + for (; i_feature < n_features; ++i_feature) { + result += w[i_feature] * v[i_feature]; + } + for (int i_1 = 0; i_1 < n_features; ++i_1) { + for (int i_2 = 0; i_2 < n_features; ++i_2) { + result += w[i_feature++] * v[i_1] * v[i_2]; + } + } + return result; + } + bool classify_sample(FeatureType const* v) const { + return map_sample(v) > threshold; + } + void map_points(DataView2D samples, + DataView2D labels, + int const* sample_idxes, + int n_samples, + FeatureClassData& data_points) const + { + for (int i_sample = 0; i_sample < n_samples; ++i_sample) { + int sample_idx = sample_idxes[i_sample]; + int sample_class = labels(sample_idx, 0); + FeatureType sample_fval = map_sample(samples.row_pointer(sample_idx)); + data_points[i_sample] = std::make_pair(sample_fval, sample_class); + } + } + template + void serialize(Archive& ar, unsigned /*version*/) + { + ar & BOOST_SERIALIZATION_NVP(n_features); + ar & BOOST_SERIALIZATION_NVP(w); + ar & BOOST_SERIALIZATION_NVP(threshold); + } +}; + +struct LinearSplitter { + typedef float FeatureType; + typedef FeatureClassDataFloat FeatureClassData; + std::vector w; + FeatureType threshold; + LinearSplitter() {} + LinearSplitter(std::vector const& w) : + w(w) + {} + void set_threshold(FeatureType new_threshold) { + threshold = new_threshold; + } + bool classify_sample(FeatureType const* v) const { + return std::inner_product(w.begin(), w.end(), v, 0.0f) > threshold; + } + void map_points(DataView2D samples, + DataView2D labels, + int const* sample_idxes, + int n_samples, + FeatureClassData& data_points) const + { + for (int i_sample = 0; i_sample < n_samples; ++i_sample) { + int sample_idx = sample_idxes[i_sample]; + int sample_class = labels(sample_idx, 0); + FeatureType sample_fval = std::inner_product(w.begin(), w.end(), + samples.row_pointer(sample_idx), 0.0f); + data_points[i_sample] = std::make_pair(sample_fval, sample_class); + } + } + template + void serialize(Archive& ar, unsigned /*version*/) + { + ar & BOOST_SERIALIZATION_NVP(w); + ar & BOOST_SERIALIZATION_NVP(threshold); + } +}; + +struct AxisAlignedSplitter { + typedef float FeatureType; + typedef FeatureClassDataFloat FeatureClassData; + int feature; + FeatureType threshold; + AxisAlignedSplitter() : feature(-1) {} + AxisAlignedSplitter(int feature) : + feature(feature) + {} + void set_threshold(FeatureType new_threshold) { + threshold = new_threshold; + } + bool classify_sample(FeatureType const* v) const { + return v[feature] > threshold; + } + void map_points(DataView2D samples, + DataView2D labels, + int const* sample_idxes, + int n_samples, + FeatureClassData& data_points) const + { + for (int i_sample = 0; i_sample < n_samples; ++i_sample) { + // determine index of this sample ... + int sample_idx = sample_idxes[i_sample]; + // determine class ... + int sample_class = labels(sample_idx, 0); + // determine value of the selected feature for this sample + FeatureType sample_fval = samples(sample_idx, feature); + data_points[i_sample] = std::make_pair(sample_fval, sample_class); + } + } + template + void serialize(Archive& ar, unsigned /*version*/) + { + ar & BOOST_SERIALIZATION_NVP(feature); + ar & BOOST_SERIALIZATION_NVP(threshold); + } +}; + +struct AxisAlignedRandomSplitGenerator { + typedef float FeatureType; + FeatureSet features; + FeatureSet::const_iterator it; + + void init(DataView2D samples, + DataView2D /*labels*/, + int* /*sample_idxes*/, + int /*n_samples*/, + size_t /*n_classes*/, + RandomGen& gen) + { + features.clear(); + int n_features = samples.cols; + size_t n_used_features = std::sqrt(n_features); + UniformIntDist dist(0, n_features - 1); + // insert into set until required number of unique features is found + while (features.size() < n_used_features) { + features.insert(dist(gen)); + } + it = features.begin(); + } + AxisAlignedSplitter gen_proposal(RandomGen& /*gen*/) + { + if (it == features.end()) { + it = features.begin(); + } + return AxisAlignedSplitter(*it++); + } + size_t num_proposals() const { + return features.size(); + } +}; + +struct LinearSplitGenerator { + typedef float FeatureType; + size_t n_features; + size_t n_proposals; + LinearSplitGenerator(size_t n_proposals = 5) : + n_proposals(n_proposals) + {} + void init(DataView2D samples, + DataView2D /*labels*/, + int* /*sample_idxes*/, + int /*n_samples*/, + size_t /*n_classes*/, + RandomGen& /*gen*/) + { + n_features = samples.cols; + } + size_t num_proposals() const { + return n_proposals; + } + LinearSplitter gen_proposal(RandomGen& gen) { + NormalDist dist; + std::vector weights(n_features); + for (size_t i_feature = 0; i_feature < n_features; ++i_feature) { + weights[i_feature] = dist(gen); + } + return LinearSplitter(weights); + } +}; + +struct QuadraticSplitGenerator { + typedef float FeatureType; + size_t n_features; + size_t n_proposals; + QuadraticSplitGenerator(size_t n_proposals = 5) : + n_proposals(n_proposals) + {} + void init(DataView2D samples, + DataView2D /*labels*/, + int* /*sample_idxes*/, + int /*n_samples*/, + size_t /*n_classes*/, + RandomGen& /*gen*/) + { + n_features = samples.cols; + } + size_t num_proposals() const { + return n_proposals; + } + QuadraticSplitter gen_proposal(RandomGen& gen) { + NormalDist dist; + std::vector weights(n_features + n_features*n_features); + for (size_t i_feature = 0; i_feature < weights.size(); ++i_feature) { + weights[i_feature] = dist(gen); + } + return QuadraticSplitter(n_features, weights); + } +}; + +} +} + +#endif diff --git a/Classification/include/CGAL/Classification/random-forest/forest.hpp b/Classification/include/CGAL/Classification/random-forest/forest.hpp new file mode 100644 index 00000000000..e3d68a8f91b --- /dev/null +++ b/Classification/include/CGAL/Classification/random-forest/forest.hpp @@ -0,0 +1,146 @@ +#ifndef LIBLEARNING_RANDOMFOREST_FOREST_H +#define LIBLEARNING_RANDOMFOREST_FOREST_H +#include "common-libraries.hpp" +#include "tree.hpp" +#include +#if VERBOSE_TREE_PROGRESS +#include +#endif + +namespace liblearning { +namespace RandomForest { + +template +class RandomForest { +public: + typedef typename NodeT::ParamType ParamType; + typedef typename NodeT::FeatureType FeatureType; + typedef Tree TreeType; + ParamType params; + + std::vector was_oob_data; + DataView2D was_oob; + + boost::ptr_vector< Tree > trees; + + RandomForest() {} + RandomForest(ParamType const& params) : params(params) {} + + template + void train(DataView2D samples, + DataView2D labels, + DataView2D train_sample_idxes, + SplitGenerator const& split_generator, + size_t seed_start = 1, + bool register_oob = true + ) + { + trees.clear(); + params.n_classes = *std::max_element(&labels(0,0), &labels(0,0)+labels.num_elements()) + 1; + params.n_features = samples.cols; + params.n_samples = samples.rows; + + std::vector sample_idxes; + + if (train_sample_idxes.empty()) { + // no indexes were passed, generate vector with all indexes + sample_idxes.resize(params.n_samples); + for (size_t i_sample = 0; i_sample < params.n_samples; ++i_sample) { + sample_idxes[i_sample] = i_sample; + } + } else { + // copy indexes + sample_idxes.assign(&train_sample_idxes(0,0), &train_sample_idxes(0,0)+train_sample_idxes.num_elements()); + } + + size_t n_idxes = sample_idxes.size(); + params.n_in_bag_samples = n_idxes * (1 - params.sample_reduction); + + // Random distribution over indexes + UniformIntDist dist(0, n_idxes - 1); + + // Store for each sample and each tree if sample was used for tree + if (register_oob) { + was_oob_data.assign(n_idxes*params.n_trees, 1); + was_oob = DataView2D(&was_oob_data[0], n_idxes, params.n_trees); + } + + for (size_t i_tree = 0; i_tree < params.n_trees; ++i_tree) { +#if VERBOSE_TREE_PROGRESS + std::printf("Training tree %zu/%zu, max depth %zu\n", i_tree+1, params.n_trees, params.max_depth); +#endif + // new tree + trees.push_back(new TreeType(¶ms)); + // initialize random generator with sequential seeds (one for each + // tree) + RandomGen gen(seed_start + i_tree); + // Bagging: draw random sample indexes used for this tree + std::vector in_bag_samples(params.n_in_bag_samples); + for (size_t i_sample = 0; i_sample < in_bag_samples.size(); ++i_sample) { + int random_idx = dist(gen); + in_bag_samples[i_sample] = sample_idxes[random_idx]; + if (register_oob && was_oob(random_idx, i_tree)) { + was_oob(random_idx, i_tree) = 0; + } + } +#ifdef TREE_GRAPHVIZ_STREAM + TREE_GRAPHVIZ_STREAM << "digraph Tree {" << std::endl; +#endif + // Train the tree + trees.back().train(samples, labels, &in_bag_samples[0], in_bag_samples.size(), split_generator, gen); +#ifdef TREE_GRAPHVIZ_STREAM + TREE_GRAPHVIZ_STREAM << "}" << std::endl << std::endl; +#endif + } + } + int evaluate(FeatureType const* sample, float* results) { + // initialize output probabilities to 0 + std::fill_n(results, params.n_classes, 0); + // accumulate votes of the trees + for (size_t i_tree = 0; i_tree < trees.size(); ++i_tree) { + float const* tree_result = trees[i_tree].evaluate(sample); + for (size_t i_cls = 0; i_cls < params.n_classes; ++i_cls) { + results[i_cls] += tree_result[i_cls]; + } + } + float best_val = 0.0; + int best_class = 0; + float scale = 1.0 / trees.size(); + for (size_t i_cls = 0; i_cls < params.n_classes; ++i_cls) { + // divide by number of trees to normalize probability + results[i_cls] *= scale; + // determine best class + if (results[i_cls] > best_val) { + best_val = results[i_cls]; + best_class = i_cls; + } + } + return best_class; + } +#if 0 + float similarity_endnode(float const* sample_1, float const* sample_2) { + double sum = 0.0; + for (size_t i_tree = 0; i_tree < trees.size(); ++i_tree) { + sum += trees[i_tree].similarity_endnode(sample_1, sample_2); + } + return sum/trees.size(); + } + float similarity_path(float const* sample_1, float const* sample_2) { + double sum = 0.0; + for (size_t i_tree = 0; i_tree < trees.size(); ++i_tree) { + sum += trees[i_tree].similarity_path(sample_1, sample_2); + } + return sum/trees.size(); + } +#endif + template + void serialize(Archive& ar, unsigned /* version */) + { + ar & BOOST_SERIALIZATION_NVP(params); + ar & BOOST_SERIALIZATION_NVP(trees); + } +}; + +} +} +#endif diff --git a/Classification/include/CGAL/Classification/random-forest/node-gini.hpp b/Classification/include/CGAL/Classification/random-forest/node-gini.hpp new file mode 100644 index 00000000000..96302de889f --- /dev/null +++ b/Classification/include/CGAL/Classification/random-forest/node-gini.hpp @@ -0,0 +1,81 @@ +#ifndef LIBLEARNING_RANDOMFOREST_NODE_GINI_H +#define LIBLEARNING_RANDOMFOREST_NODE_GINI_H +#include "node.hpp" +#include "common-libraries.hpp" + +namespace liblearning { +namespace RandomForest { + +/* +template +class X : Y {} +-> http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#Static_polymorphism +*/ + +template +class NodeGini : public Node< NodeGini, ForestParams, Splitter > { +public: + typedef typename Node< NodeGini, ForestParams, Splitter>::ParamType ParamType; + typedef typename Splitter::FeatureType FeatureType; + typedef typename Splitter::FeatureClassData FeatureClassData; + using Node< NodeGini, ForestParams, Splitter>::params; + NodeGini() {} + NodeGini(int depth, ParamType const* params) : + Node< NodeGini, ForestParams, Splitter>(depth, params) + { + } + + uint64_t gini_square_term(std::vector const& frequencies) const + { + return std::inner_product( frequencies.begin(), frequencies.end(), frequencies.begin(), uint64_t(0)); + } + std::pair determine_best_threshold(FeatureClassData& data_points, + std::vector& classes_l, + std::vector& classes_r, + RandomGen& gen) + { + double best_loss = std::numeric_limits::infinity(); + float best_thresh = 0; + + UnitDist fraction_dist; + classes_l.assign(params->n_classes, 0); + classes_r.assign(params->n_classes, 0); + double n_l = 0; + double n_r = 0; + for (size_t i_sample = 0; i_sample < data_points.size(); ++i_sample) { + classes_r[data_points[i_sample].second]++; + n_r += 1; + } + // sort data so thresholding is easy based on position in array + std::sort(data_points.begin(), data_points.end()); + // loop over data, update class distributions left&right + for (size_t i_point = 1; i_point < data_points.size(); ++i_point) { + int cls = data_points[i_point-1].second; + classes_l[cls]++; // sample with class cls gets moved to left ... + classes_r[cls]--; // from right + n_l += 1; + n_r -= 1; + // don't split here if values are the same + if (data_points[i_point-1].first == data_points[i_point].first) + continue; + // weighted average + double gini = n_l - gini_square_term(classes_l) * 1.0 / n_l + n_r - gini_square_term(classes_r) * 1.0 / n_r; + if (gini < best_loss) { + best_loss = gini; + double fraction = fraction_dist(gen); + best_thresh = fraction * data_points[i_point-1].first + (1-fraction) * data_points[i_point].first; + } + } + return std::make_pair(best_thresh, best_loss); + } + + template + void serialize(Archive& ar, unsigned /* version */) + { + ar & boost::serialization::make_nvp("base", boost::serialization::base_object< Node< NodeGini, ForestParams, Splitter > >(*this)); + } +}; + +} +} +#endif diff --git a/Classification/include/CGAL/Classification/random-forest/node.hpp b/Classification/include/CGAL/Classification/random-forest/node.hpp new file mode 100644 index 00000000000..9139c2eca9b --- /dev/null +++ b/Classification/include/CGAL/Classification/random-forest/node.hpp @@ -0,0 +1,221 @@ +#ifndef LIBLEARNING_RANDOMFORESTS_NODE_H +#define LIBLEARNING_RANDOMFORESTS_NODE_H +#include "../dataview.h" +#include "common-libraries.hpp" +#include +#include +#if VERBOSE_NODE_LEARNING +#include +#endif + +namespace liblearning { +namespace RandomForest { + +template +class Node { +public: + typedef typename Splitter::FeatureType FeatureType; + bool is_leaf; + size_t n_samples; + size_t depth; + typedef ParamT ParamType; + ParamType const* params; + Splitter splitter; + + boost::scoped_ptr left; + boost::scoped_ptr right; + std::vector node_dist; + + Node() : is_leaf(true), n_samples(0), depth(-1), params(0) {} + Node(size_t depth, ParamType const* params) : + is_leaf(true), n_samples(0), depth(depth), params(params) + {} + + bool pure(DataView2D labels, int* sample_idxes) const { + if (n_samples < 2) + return true; // an empty node is by definition pure + int first_sample_idx = sample_idxes[0]; + int seen_class = labels(first_sample_idx, 0); + // check if all classes are equal to the first class + for (size_t i_sample = 1; i_sample < n_samples; ++i_sample) { + int sample_idx = sample_idxes[i_sample]; + if (labels(sample_idx, 0) != seen_class) + return false; + } + return true; + } + + float const* votes() const { + return (float const*)&node_dist[0]; + } + + int partition_samples(DataView2D samples, int* sample_idxes) { + // sort samples in bag so that left-samples precede right-samples + // works like std::partition + int low = 0; + int high = n_samples; + + while (true) { + while (true) { + if (low == high) { + return low; + } else if (!splitter.classify_sample(samples.row_pointer(sample_idxes[low]))) { + ++low; + } else { + break; + } + } + --high; + while (true) { + if (low == high) { + return low; + } else if (splitter.classify_sample(samples.row_pointer(sample_idxes[high]))) { + --high; + } else { + break; + } + } + std::swap(sample_idxes[low], sample_idxes[high]); + ++low; + } + } + + Derived const* split (FeatureType const* sample) const { + if (splitter.classify_sample(sample)) { + return right.get(); + } else { + return left.get(); + } + } + + typedef std::list NodeList; + + NodeList get_all_childs() { + NodeList ret; + ret.push_back(this); + if (!is_leaf) { + NodeList left_childs = left->get_all_childs(); + ret.splice(ret.end(), left_childs); + NodeList right_childs = right->get_all_childs(); + ret.splice(ret.end(), right_childs); + } + return ret; + } + + template + void determine_best_split(DataView2D samples, + DataView2D labels, + int* sample_idxes, + SplitGenerator split_generator, + RandomGen& gen + ) + { + typename Splitter::FeatureClassData data_points; + init_feature_class_data(data_points, params->n_classes, n_samples); + float best_loss = std::numeric_limits::infinity(); + + std::vector classes_l; + std::vector classes_r; + + // pass information about data to split generator + split_generator.init(samples, + labels, + sample_idxes, + n_samples, + params->n_classes, + gen); + + size_t n_proposals = split_generator.num_proposals(); + + std::pair results; // (threshold, loss) + + for (size_t i_proposal = 0; i_proposal < n_proposals; ++i_proposal) { + // generate proposal + Splitter split = split_generator.gen_proposal(gen); + // map samples to numbers using proposal + split.map_points(samples, labels, sample_idxes, n_samples, data_points); + // check best loss using this proposal + results = static_cast(this)->determine_best_threshold(data_points, classes_l, classes_r, gen); + if (results.second < best_loss) { + // Proposal resulted into new optimum + best_loss = results.second; + split.set_threshold(results.first); + splitter = split; + } + } + } + + template + void train(DataView2D samples, + DataView2D labels, + int* sample_idxes, + size_t n_samples_, + SplitGenerator const& split_generator, + RandomGen& gen + ) + { + n_samples = n_samples_; + node_dist.resize(params->n_classes, 0.0f); + for (size_t i_sample = 0; i_sample < n_samples; ++i_sample) { + int label = labels(sample_idxes[i_sample], 0); + node_dist[label] += 1.0f/n_samples; + } + bool do_split = // Only split if ... + (n_samples >= params->min_samples_per_node) && // enough samples are available + !pure(labels, sample_idxes) && // this node is not already pure + (depth < params->max_depth); // we did not reach max depth + if (!do_split) { + splitter.threshold = 0.0; + return; + } + + is_leaf = false; + +#if VERBOSE_NODE_LEARNING + std::printf("Determining the best split at depth %zu/%zu\n", depth, params->max_depth); +#endif + determine_best_split(samples, labels, sample_idxes, split_generator, gen); + + left.reset(new Derived(depth + 1, params)); + right.reset(new Derived(depth + 1, params)); + + // sort samples in bag so that left-samples precede right-samples + int low = partition_samples(samples, sample_idxes); + int n_samples_left = low; + int n_samples_right = n_samples - low; + int offset_left = 0; + int offset_right = low; +#ifdef TREE_GRAPHVIZ_STREAM + if (depth <= TREE_GRAPHVIZ_MAX_DEPTH) { + TREE_GRAPHVIZ_STREAM << "p" << std::hex << (unsigned long)this + << " -> " + << "p" << std::hex << (unsigned long)left.get() + << std::dec << " [label=\"" << n_samples_left << "\"];" << std::endl; + TREE_GRAPHVIZ_STREAM << "p" << std::hex << (unsigned long)this + << " -> " + << "p" << std::hex << (unsigned long)right.get() + << std::dec << " [label=\"" << n_samples_right << "\"];" << std::endl; + } +#endif + // train left and right side of split + left->train (samples, labels, sample_idxes + offset_left, n_samples_left, split_generator, gen); + right->train(samples, labels, sample_idxes + offset_right, n_samples_right, split_generator, gen); + } + + template + void serialize(Archive& ar, unsigned /*version*/) + { + ar & BOOST_SERIALIZATION_NVP(is_leaf); + ar & BOOST_SERIALIZATION_NVP(n_samples); + ar & BOOST_SERIALIZATION_NVP(depth); + ar & BOOST_SERIALIZATION_NVP(params); + ar & BOOST_SERIALIZATION_NVP(splitter); + ar & BOOST_SERIALIZATION_NVP(node_dist); + ar & BOOST_SERIALIZATION_NVP(left); + ar & BOOST_SERIALIZATION_NVP(right); + } +}; + +} +} +#endif diff --git a/Classification/include/CGAL/Classification/random-forest/tree.hpp b/Classification/include/CGAL/Classification/random-forest/tree.hpp new file mode 100644 index 00000000000..50f214fd62e --- /dev/null +++ b/Classification/include/CGAL/Classification/random-forest/tree.hpp @@ -0,0 +1,110 @@ +#ifndef LIBLEARNING_RANDOMFOREST_TREE_H +#define LIBLEARNING_RANDOMFOREST_TREE_H +#include "../dataview.h" +#include "common-libraries.hpp" +#include + +namespace liblearning { +namespace RandomForest { + +template +class Tree { +public: + typedef NodeT NodeType; + typedef typename NodeType::ParamType ParamType; + typedef typename NodeType::FeatureType FeatureType; + boost::scoped_ptr root_node; + ParamType const* params; + + Tree() : params(0) {} + Tree(ParamType const* params) : + params(params) + { } + + template + void train(DataView2D samples, + DataView2D labels, + int* sample_idxes, + size_t n_samples, + SplitGenerator split_generator, + RandomGen const& gen + ) + { + // copy generator + RandomGen my_gen = gen; + // initialize root node + root_node.reset(new NodeT(0, params)); + // train root node (other notes get trained recursively) + root_node->train(samples, labels, sample_idxes, n_samples, split_generator, my_gen); + } + float const* evaluate(FeatureType const* sample) { + // start with root + NodeT const* node = root_node.get(); + // split until leaf + while (node && !node->is_leaf) { + node = node->split(sample); + } + if (!node) { + // bug if this is reached + return 0; + } else { + return node->votes(); + } + } + std::list all_nodes() { + return root_node->get_all_childs(); + } + +#if 0 + float similarity_endnode(float const* sample_1, float const* sample_2) { + NodeT const* node_1 = root_node.get(); + NodeT const* node_2 = root_node.get(); + while (!node_1->is_leaf) { + node_1 = node_1->split(sample_1); + } + while (!node_2->is_leaf) { + node_2 = node_2->split(sample_2); + } + if (node_1 == node_2) { + return 1.0; + } else { + return 0.0; + } + } + float similarity_path(float const* sample_1, float const* sample_2) { + NodeT const* node_1 = root_node.get(); + NodeT const* node_2 = root_node.get(); + int n_common = 0; + int n_1 = 1; + int n_2 = 1; + + while (node_1 == node_2) { + if (node_1->is_leaf) { + return 1; + } + n_common++; + node_1 = node_1->split(sample_1); + node_2 = node_2->split(sample_2); + } + while (!node_1->is_leaf) { + node_1 = node_1->split(sample_1); + n_1++; + } + while (!node_2->is_leaf) { + node_2 = node_2->split(sample_2); + n_2++; + } + return n_common/sqrt((n_common + n_1)*(n_common + n_2)); + } +#endif + template + void serialize(Archive& ar, unsigned /*version*/) + { + ar & BOOST_SERIALIZATION_NVP(params); + ar & BOOST_SERIALIZATION_NVP(root_node); + } +}; + +} +} +#endif From ddf85031bf85bc0f6552dc61022de32b16b89013 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 6 Oct 2017 10:01:59 +0200 Subject: [PATCH 15/70] ETHZ random forest classifier --- Classification/include/CGAL/Classification.h | 1 + .../ETHZ_random_forest_classifier.h | 179 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h diff --git a/Classification/include/CGAL/Classification.h b/Classification/include/CGAL/Classification.h index b1e0a1fb3d4..61ca972dce3 100644 --- a/Classification/include/CGAL/Classification.h +++ b/Classification/include/CGAL/Classification.h @@ -25,6 +25,7 @@ #include #include +#include #ifdef CGAL_LINKED_WITH_OPENCV #include diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h new file mode 100644 index 00000000000..c6515f23ce0 --- /dev/null +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -0,0 +1,179 @@ +// Copyright (c) 2017 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Simon Giraudot + +#ifndef CGAL_CLASSIFICATION_ETHZ_RANDOM_FOREST_CLASSIFIER_H +#define CGAL_CLASSIFICATION_ETHZ_RANDOM_FOREST_CLASSIFIER_H + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + + +namespace CGAL { + +namespace Classification { + +/*! + \ingroup PkgClassificationClassifiers + + \brief %Classifier based on the ETHZ version of random forest algorithm. + + \cgalModels `CGAL::Classification::Classifier` +*/ +class ETHZ_random_forest_classifier +{ + typedef liblearning::RandomForest::RandomForest + < liblearning::RandomForest::NodeGini + < liblearning::RandomForest::AxisAlignedSplitter> > Forest; + + const Label_set& m_labels; + const Feature_set& m_features; + Forest* m_rfc; + +public: + +/*! + \brief Instantiate the classifier using the sets of `labels` and `features`. + +*/ + ETHZ_random_forest_classifier (const Label_set& labels, + const Feature_set& features) + : m_labels (labels), m_features (features), m_rfc (NULL) + { } + + /// \cond SKIP_IN_MANUAL + ~ETHZ_random_forest_classifier () + { + if (m_rfc != NULL) + delete m_rfc; + } + /// \endcond + + /*! + \brief Runs the training algorithm. + + From the set of provided ground truth, this algorithm estimates + sets up the random trees that produce the most accurate result + with respect to this ground truth. + + \pre At least one ground truth item should be assigned to each + label. + + \param ground_truth vector of label indices. It should contain for + each input item, in the same order as the input set, the index of + the corresponding label in the `Label_set` provided in the + constructor. Input items that do not have a ground truth + information should be given the value `-1`. + */ + template + void train (const LabelIndexRange& ground_truth, + std::size_t num_trees = 25, + std::size_t max_depth = 20) + { + liblearning::RandomForest::ForestParams params; + params.n_trees = num_trees; + params.max_depth = max_depth; + + std::vector gt; + std::vector ft; + + for (std::size_t i = 0; i < ground_truth.size(); ++ i) + if (ground_truth[i] != std::size_t(-1)) + { + for (std::size_t f = 0; f < m_features.size(); ++ f) + ft.push_back(m_features[f]->value(i)); + gt.push_back(ground_truth[i]); + } + + liblearning::DataView2D label_vector (&(gt[0]), gt.size(), 1); + liblearning::DataView2D feature_vector(&(ft[0]), gt.size(), ft.size() / gt.size()); + + if (m_rfc != NULL) + delete m_rfc; + m_rfc = new Forest (params); + + liblearning::RandomForest::AxisAlignedRandomSplitGenerator generator; + + m_rfc->train(feature_vector, label_vector, liblearning::DataView2D(), generator, 0, false); + } + + /// \cond SKIP_IN_MANUAL + void operator() (std::size_t item_index, std::vector& out) const + { + out.resize (m_labels.size(), 0.); + + std::vector ft; + ft.reserve (m_features.size()); + for (std::size_t f = 0; f < m_features.size(); ++ f) + ft.push_back (m_features[f]->value(item_index)); + + std::vector prob (m_labels.size()); + + m_rfc->evaluate (ft.data(), prob.data()); + + for (std::size_t i = 0; i < out.size(); ++ i) + out[i] = - std::log (prob[i]); + } + + void save_configuration (const char* filename) + { + std::ofstream ofs(filename, std::ios_base::out | std::ios_base::binary); + boost::iostreams::filtering_ostream outs; + outs.push(boost::iostreams::gzip_compressor()); + outs.push(ofs); + boost::archive::text_oarchive oas(outs); + oas << BOOST_SERIALIZATION_NVP(*m_rfc); + } + + void load_configuration (const char* filename, + std::size_t num_trees = 25, + std::size_t max_depth = 20) + { + liblearning::RandomForest::ForestParams params; + params.n_trees = num_trees; + params.max_depth = max_depth; + if (m_rfc != NULL) + delete m_rfc; + m_rfc = new Forest (params); + + std::ifstream ifs(filename, std::ios_base::in | std::ios_base::binary); + boost::iostreams::filtering_istream ins; + ins.push(boost::iostreams::gzip_decompressor()); + ins.push(ifs); + boost::archive::text_iarchive ias(ins); + ias >> BOOST_SERIALIZATION_NVP(*m_rfc); + } + /// \endcond + +}; + +} + +} + +#endif // CGAL_CLASSIFICATION_ETHZ_RANDOM_FOREST_CLASSIFIER_H From 7bd5916fce2bfe39ee3bf3d64b489b5102c4ad91 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 6 Oct 2017 10:02:32 +0200 Subject: [PATCH 16/70] Include ETHZ random forest in plugin --- .../Plugins/Classification/CMakeLists.txt | 4 ++-- .../Classification/Classification_plugin.cpp | 2 ++ .../Classification/Item_classification_base.h | 20 ++++++++++++++++++- .../Point_set_item_classification.cpp | 14 +++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index a54a9832d13..e6b3e3cbc02 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -8,10 +8,10 @@ if(EIGEN3_FOUND) if(OpenCV_FOUND) message(STATUS "Found OpenCV ${OpenCV_VERSION}") include_directories(${OpenCV_INCLUDE_DIRS}) - target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_color_ramp ${OpenCV_LIBS}) + target_link_libraries(classification_plugin scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_color_ramp ${OpenCV_LIBS} boost_serialization boost_iostreams) target_compile_definitions(classification_plugin PUBLIC "-DCGAL_LINKED_WITH_OPENCV") else() - target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_color_ramp) + target_link_libraries(classification_plugin scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_color_ramp boost_serialization boost_iostreams) message(STATUS "NOTICE: OpenCV was not found. Random forest predicate for classification will not be available.") endif() if(TBB_FOUND) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index c8064cd74c8..346ddf7b0d9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -141,6 +141,8 @@ public: ui_widget.setupUi(dock_widget); addDockWidget(dock_widget); + ui_widget.classifier->addItem (tr("Random Forest (ETHZ)")); + #ifdef CGAL_LINKED_WITH_OPENCV ui_widget.classifier->addItem (tr("Random Forest (OpenCV %1.%2)") .arg(CV_MAJOR_VERSION) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 5d48b8137dd..8aba3111232 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef CGAL_LINKED_WITH_OPENCV #include @@ -21,6 +22,7 @@ public: typedef CGAL::Classification::Label_set Label_set; typedef CGAL::Classification::Feature_set Feature_set; typedef CGAL::Classification::Sum_of_weighted_features_classifier Sum_of_weighted_features; + typedef CGAL::Classification::ETHZ_random_forest_classifier ETHZ_random_forest; #ifdef CGAL_LINKED_WITH_OPENCV typedef CGAL::Classification::Random_forest_classifier Random_forest; @@ -67,9 +69,13 @@ public: { m_labels.add(name); m_label_colors.push_back (color); + 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); @@ -87,6 +93,9 @@ public: 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); @@ -119,6 +128,10 @@ public: std::ofstream f (filename); m_sowf->save_configuration (f); } + else if (classifier == 1) + { + m_ethz->save_configuration (filename); + } else { #ifdef CGAL_LINKED_WITH_OPENCV @@ -139,6 +152,10 @@ public: std::ifstream f (filename); m_sowf->load_configuration (f, true); } + else if (classifier == 1) + { + m_ethz->load_configuration (filename); + } else { #ifdef CGAL_LINKED_WITH_OPENCV @@ -166,6 +183,7 @@ protected: Feature_set m_features; std::vector m_label_colors; Sum_of_weighted_features* m_sowf; + ETHZ_random_forest* m_ethz; #ifdef CGAL_LINKED_WITH_OPENCV Random_forest* m_random_forest; #endif 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 28558670b10..de35d6a54c7 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -242,6 +242,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n update_comments_of_point_set_item(); m_sowf = new Sum_of_weighted_features (m_labels, m_features); + m_ethz = new ETHZ_random_forest (m_labels, m_features); #ifdef CGAL_LINKED_WITH_OPENCV m_random_forest = new Random_forest (m_labels, m_features); #endif @@ -252,6 +253,8 @@ Point_set_item_classification::~Point_set_item_classification() { if (m_sowf != NULL) delete m_sowf; + if (m_ethz != NULL) + delete m_ethz; #ifdef CGAL_LINKED_WITH_OPENCV if (m_random_forest != NULL) delete m_random_forest; @@ -501,6 +504,8 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales) 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); @@ -669,6 +674,13 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials m_labels, *m_sowf, indices); } + else if (classifier == 1) + { + m_ethz->train(training); + CGAL::Classification::classify (*(m_points->point_set()), + m_labels, *m_ethz, + indices); + } else { #ifdef CGAL_LINKED_WITH_OPENCV @@ -699,6 +711,8 @@ bool Point_set_item_classification::run (int method, int classifier, if (classifier == 0) run (method, *m_sowf, subdivisions, smoothing); + else if (classifier == 1) + run (method, *m_ethz, subdivisions, smoothing); #ifdef CGAL_LINKED_WITH_OPENCV else run (method, *m_random_forest, subdivisions, smoothing); From af4bbf37a0df5b691c746c90cebc6ca4e22fc757 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 9 Oct 2017 11:58:36 +0200 Subject: [PATCH 17/70] Move ETHZ code to auxiliary --- .../CGAL/Classification/ETHZ_random_forest_classifier.h | 4 ++-- .../CGAL/Classification/{ => internal/auxiliary}/dataview.h | 0 .../auxiliary}/random-forest/common-libraries.hpp | 0 .../{ => internal/auxiliary}/random-forest/forest.hpp | 0 .../{ => internal/auxiliary}/random-forest/node-gini.hpp | 0 .../{ => internal/auxiliary}/random-forest/node.hpp | 0 .../{ => internal/auxiliary}/random-forest/tree.hpp | 0 .../Plugins/Classification/Point_set_item_classification.cpp | 2 +- 8 files changed, 3 insertions(+), 3 deletions(-) rename Classification/include/CGAL/Classification/{ => internal/auxiliary}/dataview.h (100%) rename Classification/include/CGAL/Classification/{ => internal/auxiliary}/random-forest/common-libraries.hpp (100%) rename Classification/include/CGAL/Classification/{ => internal/auxiliary}/random-forest/forest.hpp (100%) rename Classification/include/CGAL/Classification/{ => internal/auxiliary}/random-forest/node-gini.hpp (100%) rename Classification/include/CGAL/Classification/{ => internal/auxiliary}/random-forest/node.hpp (100%) rename Classification/include/CGAL/Classification/{ => internal/auxiliary}/random-forest/tree.hpp (100%) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index c6515f23ce0..d0aa631e320 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -25,8 +25,8 @@ #include #include -#include -#include +#include +#include #include #include diff --git a/Classification/include/CGAL/Classification/dataview.h b/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h similarity index 100% rename from Classification/include/CGAL/Classification/dataview.h rename to Classification/include/CGAL/Classification/internal/auxiliary/dataview.h diff --git a/Classification/include/CGAL/Classification/random-forest/common-libraries.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp similarity index 100% rename from Classification/include/CGAL/Classification/random-forest/common-libraries.hpp rename to Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp diff --git a/Classification/include/CGAL/Classification/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp similarity index 100% rename from Classification/include/CGAL/Classification/random-forest/forest.hpp rename to Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp diff --git a/Classification/include/CGAL/Classification/random-forest/node-gini.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp similarity index 100% rename from Classification/include/CGAL/Classification/random-forest/node-gini.hpp rename to Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp diff --git a/Classification/include/CGAL/Classification/random-forest/node.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp similarity index 100% rename from Classification/include/CGAL/Classification/random-forest/node.hpp rename to Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp diff --git a/Classification/include/CGAL/Classification/random-forest/tree.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp similarity index 100% rename from Classification/include/CGAL/Classification/random-forest/tree.hpp rename to Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp 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 de35d6a54c7..20ea9bcf106 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -88,7 +88,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n int current_idx = 0; for (std::size_t i = 0; i < used_indices.size(); ++ i) { - if (las_found && (i < 2 || i == 7 || i == 18)) + if (las_found && (i < 2)) { used_indices[i] = -1; continue; From c69ac52b93172f6926cde218aff035f5641b7a6a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 9 Oct 2017 16:37:46 +0200 Subject: [PATCH 18/70] Add option to not reset trees on ETHZ random forest --- .../ETHZ_random_forest_classifier.h | 16 +++++++++++++--- .../internal/auxiliary/random-forest/forest.hpp | 12 ++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index d0aa631e320..fa0e38febc3 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -25,6 +25,10 @@ #include #include +#ifdef CGAL_CLASSIFICATION_VERBOSE +#define VERBOSE_TREE_PROGRESS true +#endif + #include #include @@ -92,6 +96,7 @@ public: */ template void train (const LabelIndexRange& ground_truth, + bool reset_trees = true, std::size_t num_trees = 25, std::size_t max_depth = 20) { @@ -113,13 +118,18 @@ public: liblearning::DataView2D label_vector (&(gt[0]), gt.size(), 1); liblearning::DataView2D feature_vector(&(ft[0]), gt.size(), ft.size() / gt.size()); - if (m_rfc != NULL) + if (m_rfc != NULL && reset_trees) + { delete m_rfc; - m_rfc = new Forest (params); + m_rfc = NULL; + } + + if (m_rfc == NULL) + m_rfc = new Forest (params); liblearning::RandomForest::AxisAlignedRandomSplitGenerator generator; - m_rfc->train(feature_vector, label_vector, liblearning::DataView2D(), generator, 0, false); + m_rfc->train(feature_vector, label_vector, liblearning::DataView2D(), generator, 0, false, reset_trees); } /// \cond SKIP_IN_MANUAL diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp index e3d68a8f91b..774baf53134 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp @@ -32,10 +32,13 @@ public: DataView2D train_sample_idxes, SplitGenerator const& split_generator, size_t seed_start = 1, - bool register_oob = true + bool register_oob = true, + bool reset_trees = true ) { - trees.clear(); + if (reset_trees) + trees.clear(); + params.n_classes = *std::max_element(&labels(0,0), &labels(0,0)+labels.num_elements()) + 1; params.n_features = samples.cols; params.n_samples = samples.rows; @@ -65,9 +68,10 @@ public: was_oob = DataView2D(&was_oob_data[0], n_idxes, params.n_trees); } - for (size_t i_tree = 0; i_tree < params.n_trees; ++i_tree) { + std::size_t nb_trees = trees.size(); + for (size_t i_tree = nb_trees; i_tree < nb_trees + params.n_trees; ++i_tree) { #if VERBOSE_TREE_PROGRESS - std::printf("Training tree %zu/%zu, max depth %zu\n", i_tree+1, params.n_trees, params.max_depth); + std::printf("Training tree %zu/%zu, max depth %zu\n", i_tree+1, nb_trees + params.n_trees, params.max_depth); #endif // new tree trees.push_back(new TreeType(¶ms)); From f709cc18047fef7be09bd2b1f4fb6ded76269e10 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 11 Oct 2017 16:04:09 +0200 Subject: [PATCH 19/70] Better load/save windows for classif config --- .../Classification/Classification_plugin.cpp | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 346ddf7b0d9..66a682c4ec9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -453,10 +453,31 @@ public Q_SLOTS: return; } - QString filename = QFileDialog::getSaveFileName(mw, - tr("Save classification configuration"), - QString("config.xml"), - "Config file (*.xml);;"); + QString filename; + + if (ui_widget.classifier->currentIndex() == 0) + filename = QFileDialog::getSaveFileName(mw, + tr("Save classification configuration"), + tr("%1 (CGAL classif config).xml").arg(classif->item()->name()), + "CGAL classification configuration (*.xml);"); + else if (ui_widget.classifier->currentIndex() == 1) + filename = QFileDialog::getSaveFileName(mw, + tr("Save classification configuration"), + tr("%1 (ETHZ random forest config).gz").arg(classif->item()->name()), + "Compressed ETHZ random forest configuration (*.gz);"); +#ifdef CGAL_LINKED_WITH_OPENCV + else if (ui_widget.classifier->currentIndex() == 2) + filename = QFileDialog::getSaveFileName(mw, + tr("Save classification configuration"), + tr("%1 (OpenCV %2.%3 random forest config).xml") + .arg(classif->item()->name()) + .arg(CV_MAJOR_VERSION) + .arg(CV_MINOR_VERSION), + tr("OpenCV %2.%3 random forest configuration (*.xml);") + .arg(CV_MAJOR_VERSION) + .arg(CV_MINOR_VERSION)); +#endif + if (filename == QString()) return; @@ -479,10 +500,29 @@ public Q_SLOTS: print_message("Error: there is no point set classification item!"); return; } - QString filename = QFileDialog::getOpenFileName(mw, - tr("Open classification configuration"), - ".", - "Config file (*.xml);;All Files (*)"); + QString filename; + + if (ui_widget.classifier->currentIndex() == 0) + filename = QFileDialog::getOpenFileName(mw, + tr("Open CGAL classification configuration"), + ".", + "CGAL classification configuration (*.xml);;All Files (*)"); + else if (ui_widget.classifier->currentIndex() == 1) + filename = QFileDialog::getOpenFileName(mw, + tr("Open ETHZ random forest configuration"), + ".", + "Compressed ETHZ random forest configuration (*.gz);;All Files (*)"); +#ifdef CGAL_LINKED_WITH_OPENCV + else if (ui_widget.classifier->currentIndex() == 2) + filename = QFileDialog::getOpenFileName(mw, + tr("Open OpenCV %2.%3 random forest configuration") + .arg(CV_MAJOR_VERSION) + .arg(CV_MINOR_VERSION), + ".", + tr("OpenCV %2.%3 random forest configuration (*.xml);;All Files (*)") + .arg(CV_MAJOR_VERSION) + .arg(CV_MINOR_VERSION)); +#endif if (filename == QString()) return; From 1a2dc57fcdd99f7dedf8dc658befcbe1a82c1588 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 12 Oct 2017 10:23:22 +0200 Subject: [PATCH 20/70] Fix saving dialog --- .../Plugins/Classification/Classification_plugin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 66a682c4ec9..4d7a40dab60 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -459,12 +459,12 @@ public Q_SLOTS: filename = QFileDialog::getSaveFileName(mw, tr("Save classification configuration"), tr("%1 (CGAL classif config).xml").arg(classif->item()->name()), - "CGAL classification configuration (*.xml);"); + "CGAL classification configuration (*.xml);;"); else if (ui_widget.classifier->currentIndex() == 1) filename = QFileDialog::getSaveFileName(mw, tr("Save classification configuration"), tr("%1 (ETHZ random forest config).gz").arg(classif->item()->name()), - "Compressed ETHZ random forest configuration (*.gz);"); + "Compressed ETHZ random forest configuration (*.gz);;"); #ifdef CGAL_LINKED_WITH_OPENCV else if (ui_widget.classifier->currentIndex() == 2) filename = QFileDialog::getSaveFileName(mw, @@ -473,7 +473,7 @@ public Q_SLOTS: .arg(classif->item()->name()) .arg(CV_MAJOR_VERSION) .arg(CV_MINOR_VERSION), - tr("OpenCV %2.%3 random forest configuration (*.xml);") + tr("OpenCV %2.%3 random forest configuration (*.xml);;") .arg(CV_MAJOR_VERSION) .arg(CV_MINOR_VERSION)); #endif From 2a662cf0df1427a4e38fd4d2f4cf1e8f8f3111fb Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 10 Oct 2017 14:17:47 +0200 Subject: [PATCH 21/70] fix compilation error C1710 on msvc see https://msdn.microsoft.com/fr-fr/library/h5sh3k99.aspx --- .../include/CGAL/Classification/ETHZ_random_forest_classifier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index fa0e38febc3..3283dd277e5 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -26,7 +26,7 @@ #include #ifdef CGAL_CLASSIFICATION_VERBOSE -#define VERBOSE_TREE_PROGRESS true +#define VERBOSE_TREE_PROGRESS 1 #endif #include From 63beb82029230de6d37a8fc8c627d001b094597f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 10 Oct 2017 15:37:48 +0200 Subject: [PATCH 22/70] add libraries that the classification_plugin needs to link to --- .../Plugins/Classification/CMakeLists.txt | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index e6b3e3cbc02..7d20ff26feb 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -4,21 +4,47 @@ if(EIGEN3_FOUND) qt5_wrap_ui( classificationUI_FILES Classification_widget.ui) polyhedron_demo_plugin(classification_plugin Classification_plugin Point_set_item_classification ${classificationUI_FILES}) - find_package(OpenCV QUIET) - if(OpenCV_FOUND) - message(STATUS "Found OpenCV ${OpenCV_VERSION}") - include_directories(${OpenCV_INCLUDE_DIRS}) - target_link_libraries(classification_plugin scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_color_ramp ${OpenCV_LIBS} boost_serialization boost_iostreams) - target_compile_definitions(classification_plugin PUBLIC "-DCGAL_LINKED_WITH_OPENCV") - else() - target_link_libraries(classification_plugin scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_color_ramp boost_serialization boost_iostreams) - message(STATUS "NOTICE: OpenCV was not found. Random forest predicate for classification will not be available.") - endif() - if(TBB_FOUND) - CGAL_target_use_TBB(classification_plugin) - endif() - + + find_package(Boost COMPONENTS serialization iostreams) + + if (Boost_SERIALIZATION_FOUND) + if (Boost_IOSTREAMS_FOUND) + if (LASLIB_FOUND) + + find_package(OpenCV QUIET) + if (OpenCV_FOUND) + + message(STATUS "Found OpenCV ${OpenCV_VERSION}") + include_directories(${OpenCV_INCLUDE_DIRS}) + target_link_libraries(classification_plugin scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_color_ramp ${OpenCV_LIBS} + ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY} + ${LASLIB_LIBRARIES}) + + target_compile_definitions(classification_plugin PUBLIC "-DCGAL_LINKED_WITH_OPENCV") + + else(OpenCV_FOUND) + target_link_libraries(classification_plugin scene_points_with_normal_item + scene_polylines_item scene_polygon_soup_item scene_color_ramp + ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY} + ${LASLIB_LIBRARIES}) + + message(STATUS "NOTICE: OpenCV was not found. Random forest predicate for classification will not be available.") + endif(OpenCV_FOUND) + + else(LASLIB_FOUND) + message(STATUS "NOTICE: LAS was not found. Classification plugin will not be available.") + endif(LASLIB_FOUND) + + else(Boost_IOSTREAMS_FOUND) + message(STATUS "NOTICE: Boost_iostreams was not found. Classification plugin will not be available.") + endif(Boost_IOSTREAMS_FOUND) + + else(Boost_SERIALIZATION_FOUND) + message(STATUS "NOTICE: Boost_serialization was not found. Classification plugin will not be available.") + endif(Boost_SERIALIZATION_FOUND) + else(EIGEN3_FOUND) message(STATUS "NOTICE: Eigen 3.1 (or greater) was not found. Classification plugin will not be available.") endif() + From c2a1804c0be3a778b20f30265f65974efff3a857 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 10 Oct 2017 16:15:22 +0200 Subject: [PATCH 23/70] re-indent CMakeLists.txt --- .../demo/Polyhedron/Plugins/Classification/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index 7d20ff26feb..caedb5fb77c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -16,9 +16,10 @@ if(EIGEN3_FOUND) message(STATUS "Found OpenCV ${OpenCV_VERSION}") include_directories(${OpenCV_INCLUDE_DIRS}) - target_link_libraries(classification_plugin scene_points_with_normal_item scene_polylines_item scene_polygon_soup_item scene_color_ramp ${OpenCV_LIBS} - ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY} - ${LASLIB_LIBRARIES}) + target_link_libraries(classification_plugin scene_points_with_normal_item + scene_polylines_item scene_polygon_soup_item scene_color_ramp ${OpenCV_LIBS} + ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY} + ${LASLIB_LIBRARIES}) target_compile_definitions(classification_plugin PUBLIC "-DCGAL_LINKED_WITH_OPENCV") From 9acd8bbe3c153d00db403f18e821c0737ee9afac Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 12 Oct 2017 11:56:10 +0200 Subject: [PATCH 24/70] Fix duplicate code --- .../Point_set_item_classification.cpp | 50 ------------------- 1 file changed, 50 deletions(-) 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 20ea9bcf106..be2b03e19e6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -601,56 +601,6 @@ void Point_set_item_classification::add_remaining_point_set_properties_as_featur } } -void Point_set_item_classification::select_random_region() -{ - m_points->point_set()->reset_indices(); - - std::size_t scale = (rand() % m_generator->number_of_scales()); - - bool use_grid = (rand() % 2); - - std::vector selected; - - if (use_grid) - { - std::size_t x = (rand() % m_generator->grid(scale).width()); - std::size_t y = (rand() % m_generator->grid(scale).height()); - std::copy (m_generator->grid(scale).indices_begin(x,y), - m_generator->grid(scale).indices_end(x,y), - std::back_inserter (selected)); - } - else - { - m_generator->neighborhood(0).sphere_neighbor_query (m_generator->radius_neighbors(scale)) - (*(m_points->point_set()->points().begin() + (rand() % m_points->point_set()->size())), - std::back_inserter (selected)); - } - - if (selected.empty()) - return; - - std::sort (selected.begin(), selected.end()); - std::size_t current_idx = 0; - - std::vector unselected; - - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->end(); ++ it) - if (std::size_t(*it) == selected[current_idx]) - current_idx ++; - else - unselected.push_back (*it); - - for (std::size_t i = 0; i < unselected.size(); ++ i) - *(m_points->point_set()->begin() + i) = unselected[i]; - for (std::size_t i = 0; i < selected.size(); ++ i) - *(m_points->point_set()->begin() + (unselected.size() + i)) = selected[i]; - - m_points->point_set()->set_first_selected - (m_points->point_set()->begin() + unselected.size()); - -} - void Point_set_item_classification::train(int classifier, unsigned int nb_trials) { if (m_features.size() == 0) From 13decf854d274992ec11bd19b9e5f7a062a25e4c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 18 Oct 2017 14:04:29 +0200 Subject: [PATCH 25/70] Add a simple way to create a multiple input dialog --- .../Polyhedron/include/QMultipleInputDialog.h | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h diff --git a/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h b/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h new file mode 100644 index 00000000000..17147651f29 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/include/QMultipleInputDialog.h @@ -0,0 +1,53 @@ +// Note: this structure is inspired from the QInputDialog that allows +// the user to easily create a dialog to get one value (integer, +// double or string). This structure allows the user to easily create +// a form inside a QDialog to get as manu values as needed. + +#ifndef CGAL_QMULTIPLEINPUTDIALOG_H +#define CGAL_QMULTIPLEINPUTDIALOG_H + +#include +#include +#include + +class QMultipleInputDialog +{ + QDialog* dialog; + QFormLayout* form; +public: + QMultipleInputDialog (const char* name, QWidget* parent) + { + dialog = new QDialog (parent); + dialog->setWindowTitle (name); + form = new QFormLayout(dialog); + } + ~QMultipleInputDialog () + { + delete dialog; + } + + template + QObjectType* add (const char* name) + { + QObjectType* out = new QObjectType (dialog); + form->addRow (QString(name), out); + return out; + } + + int exec() + { + QDialogButtonBox* oknotok = new QDialogButtonBox + (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, + Qt::Horizontal, dialog); + + form->addRow (oknotok); + QObject::connect (oknotok, SIGNAL(accepted()), dialog, SLOT(accept())); + QObject::connect (oknotok, SIGNAL(rejected()), dialog, SLOT(reject())); + + return dialog->exec(); + } +}; + + + +#endif // CGAL_QMULTIPLEINPUTDIALOG_H From 40e497a6da11b71da7cc216ca2bacb7c19bf9a88 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 18 Oct 2017 14:04:46 +0200 Subject: [PATCH 26/70] Use newly added QMultipleInputDialog --- .../Classification/Classification_plugin.cpp | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 4d7a40dab60..431a9a56a84 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -17,6 +17,8 @@ #include #include +#include + #include "ui_Classification_widget.h" #include @@ -25,10 +27,8 @@ #include #include #include -#include #include #include -#include #include #include @@ -599,27 +599,15 @@ public Q_SLOTS: return; } - QDialog dialog(mw); - dialog.setWindowTitle ("Classify with Graph Cut"); - QFormLayout form (&dialog); - QString label_sub = QString("Number of subdivisions: "); - QSpinBox subdivisions (&dialog); - subdivisions.setRange (1, 9999); - subdivisions.setValue (16); - form.addRow(label_sub, &subdivisions); + QMultipleInputDialog dialog ("Classify with Graph Cut", mw); + QSpinBox* subdivisions = dialog.add ("Number of subdivisons: "); + subdivisions->setRange (1, 9999); + subdivisions->setValue (16); - QString label_smooth = QString("Regularization weight: "); - QDoubleSpinBox smoothing (&dialog); - smoothing.setRange (0.0, 100.0); - smoothing.setValue (0.5); - smoothing.setSingleStep (0.1); - form.addRow(label_smooth, &smoothing); - - QDialogButtonBox oknotok (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, - Qt::Horizontal, &dialog); - form.addRow (&oknotok); - QObject::connect (&oknotok, SIGNAL(accepted()), &dialog, SLOT(accept())); - QObject::connect (&oknotok, SIGNAL(rejected()), &dialog, SLOT(reject())); + QDoubleSpinBox* smoothing = dialog.add ("Regularization weight: "); + smoothing->setRange (0.0, 100.0); + smoothing->setValue (0.5); + smoothing->setSingleStep (0.1); if (dialog.exec() != QDialog::Accepted) return; @@ -627,7 +615,7 @@ public Q_SLOTS: QApplication::setOverrideCursor(Qt::WaitCursor); CGAL::Real_timer t; t.start(); - run (classif, 2, std::size_t(subdivisions.value()), smoothing.value()); + run (classif, 2, std::size_t(subdivisions->value()), smoothing->value()); t.stop(); std::cerr << "Graph Cut classification computed in " << t.time() << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); From 34bc6f18e82e1772d79d602790deebbbc3512a57 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 20 Oct 2017 15:16:03 +0200 Subject: [PATCH 27/70] Bugfix: prevent classification cost from going negative --- .../CGAL/Classification/ETHZ_random_forest_classifier.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 3283dd277e5..c9cb3ac5d88 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -147,7 +147,11 @@ public: m_rfc->evaluate (ft.data(), prob.data()); for (std::size_t i = 0; i < out.size(); ++ i) + { out[i] = - std::log (prob[i]); + if (out[i] < 0.f) + out[i] = -out[i]; + } } void save_configuration (const char* filename) From 55600b9b1493a785dbaa76a0e0387d79e4d7c3b5 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 23 Oct 2017 10:01:32 +0200 Subject: [PATCH 28/70] Bugfix: prevent node votes to go over 1.0f --- .../internal/auxiliary/random-forest/node.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp index 9139c2eca9b..7b869c85a12 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp @@ -158,8 +158,12 @@ public: node_dist.resize(params->n_classes, 0.0f); for (size_t i_sample = 0; i_sample < n_samples; ++i_sample) { int label = labels(sample_idxes[i_sample], 0); - node_dist[label] += 1.0f/n_samples; + node_dist[label] += 1.0f; } + + for (std::size_t i = 0; i < node_dist.size(); ++ i) + node_dist[i] /= n_samples; + bool do_split = // Only split if ... (n_samples >= params->min_samples_per_node) && // enough samples are available !pure(labels, sample_idxes) && // this node is not already pure From 54ec66b1e76665c14aa56898da565cfb5b8f025b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 23 Oct 2017 10:02:34 +0200 Subject: [PATCH 29/70] Random forest parameters settable from plugin --- .../Classification/Classification_plugin.cpp | 20 ++++++++++++++++++- .../Classification/Item_classification_base.h | 3 ++- .../Point_set_item_classification.cpp | 10 ++++++++-- .../Point_set_item_classification.h | 3 ++- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 431a9a56a84..cbbc1d13682 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -815,6 +815,8 @@ public Q_SLOTS: } int nb_trials = 0; + int num_trees = 0; + int max_depth = 0; if (ui_widget.classifier->currentIndex() == 0) { @@ -826,11 +828,27 @@ public Q_SLOTS: if (!ok) return; } + else + { + QMultipleInputDialog dialog ("Train Random Forest Classifier", mw); + QSpinBox* trees = dialog.add ("Number of trees: "); + trees->setRange (1, 9999); + trees->setValue (25); + QSpinBox* depth = dialog.add ("Maximum depth of tree: "); + depth->setRange (1, 9999); + depth->setValue (20); + + if (dialog.exec() != QDialog::Accepted) + return; + num_trees = trees->value(); + max_depth = depth->value(); + } QApplication::setOverrideCursor(Qt::WaitCursor); CGAL::Real_timer t; t.start(); - classif->train(ui_widget.classifier->currentIndex(), nb_trials); + classif->train(ui_widget.classifier->currentIndex(), nb_trials, + num_trees, max_depth); t.stop(); std::cerr << "Done in " << t.time() << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 8aba3111232..db14b856420 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -44,7 +44,8 @@ public: virtual void select_random_region() = 0; virtual void validate_selection () = 0; - virtual void train(int classifier, unsigned int nb_trials) = 0; + virtual void train(int classifier, unsigned int nb_trials, + std::size_t num_trees, std::size_t max_depth) = 0; virtual bool run (int method, int classifier, std::size_t subdivisions, double smoothing) = 0; virtual void update_color () = 0; 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 be2b03e19e6..a7ea0c3dc2e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -601,7 +601,8 @@ void Point_set_item_classification::add_remaining_point_set_properties_as_featur } } -void Point_set_item_classification::train(int classifier, unsigned int nb_trials) +void Point_set_item_classification::train(int classifier, unsigned int nb_trials, + std::size_t num_trees, std::size_t max_depth) { if (m_features.size() == 0) { @@ -626,7 +627,7 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials } else if (classifier == 1) { - m_ethz->train(training); + m_ethz->train(training, true, num_trees, max_depth); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_ethz, indices); @@ -634,6 +635,11 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials else { #ifdef CGAL_LINKED_WITH_OPENCV + if (m_random_forest != NULL) + delete m_random_forest; + m_random_forest = new Random_forest (m_labels, m_features, + max_depth, 5, 15, + num_trees); m_random_forest->train (training); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_random_forest, diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h index 2320838a815..b6df02cef41 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -108,7 +108,8 @@ class Point_set_item_classification : public Item_classification_base if (m_index_color == 1 || m_index_color == 2) change_color (m_index_color); } - void train(int classifier, unsigned int nb_trials); + void train(int classifier, unsigned int nb_trials, + std::size_t num_trees, std::size_t max_depth); bool run (int method, int classifier, std::size_t subdivisions, double smoothing); void update_color () { change_color (m_index_color); } From 53f4f21d2dfa8a0d3245b82ed2f0b77baca16ac6 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 23 Oct 2017 11:11:16 +0200 Subject: [PATCH 30/70] Unify names of random forest classifiers --- .../Classification/example_random_forest.cpp | 3 +-- Classification/include/CGAL/Classification.h | 2 +- .../ETHZ_random_forest_classifier.h | 14 +++------- ...er.h => OpenCV_random_forest_classifier.h} | 26 +++++++++---------- 4 files changed, 19 insertions(+), 26 deletions(-) rename Classification/include/CGAL/Classification/{Random_forest_classifier.h => OpenCV_random_forest_classifier.h} (91%) diff --git a/Classification/examples/Classification/example_random_forest.cpp b/Classification/examples/Classification/example_random_forest.cpp index 768350c7448..5cc934f4208 100644 --- a/Classification/examples/Classification/example_random_forest.cpp +++ b/Classification/examples/Classification/example_random_forest.cpp @@ -10,7 +10,6 @@ #include #include -#include #include #include @@ -32,7 +31,7 @@ typedef Classification::Feature_handle typedef Classification::Label_set Label_set; typedef Classification::Feature_set Feature_set; -typedef Classification::Random_forest_classifier Classifier; +typedef Classification::OpenCV_random_forest_classifier Classifier; typedef Classification::Point_set_feature_generator Feature_generator; diff --git a/Classification/include/CGAL/Classification.h b/Classification/include/CGAL/Classification.h index 61ca972dce3..08ee533d06f 100644 --- a/Classification/include/CGAL/Classification.h +++ b/Classification/include/CGAL/Classification.h @@ -28,7 +28,7 @@ #include #ifdef CGAL_LINKED_WITH_OPENCV -#include +#include #endif #include diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index c9cb3ac5d88..889ed5c3df6 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -154,31 +154,25 @@ public: } } - void save_configuration (const char* filename) + void save_configuration (std::ostream& output) { - std::ofstream ofs(filename, std::ios_base::out | std::ios_base::binary); boost::iostreams::filtering_ostream outs; outs.push(boost::iostreams::gzip_compressor()); - outs.push(ofs); + outs.push(output); boost::archive::text_oarchive oas(outs); oas << BOOST_SERIALIZATION_NVP(*m_rfc); } - void load_configuration (const char* filename, - std::size_t num_trees = 25, - std::size_t max_depth = 20) + void load_configuration (std::istream& input) { liblearning::RandomForest::ForestParams params; - params.n_trees = num_trees; - params.max_depth = max_depth; if (m_rfc != NULL) delete m_rfc; m_rfc = new Forest (params); - std::ifstream ifs(filename, std::ios_base::in | std::ios_base::binary); boost::iostreams::filtering_istream ins; ins.push(boost::iostreams::gzip_decompressor()); - ins.push(ifs); + ins.push(input); boost::archive::text_iarchive ias(ins); ias >> BOOST_SERIALIZATION_NVP(*m_rfc); } diff --git a/Classification/include/CGAL/Classification/Random_forest_classifier.h b/Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h similarity index 91% rename from Classification/include/CGAL/Classification/Random_forest_classifier.h rename to Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h index 102112d2d6b..17fe563034d 100644 --- a/Classification/include/CGAL/Classification/Random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h @@ -18,8 +18,8 @@ // // Author(s) : Simon Giraudot -#ifndef CGAL_CLASSIFICATION_RANDOM_FOREST_CLASSIFIER_H -#define CGAL_CLASSIFICATION_RANDOM_FOREST_CLASSIFIER_H +#ifndef CGAL_CLASSIFICATION_OPENCV_RANDOM_FOREST_CLASSIFIER_H +#define CGAL_CLASSIFICATION_OPENCV_RANDOM_FOREST_CLASSIFIER_H #include @@ -36,13 +36,13 @@ namespace Classification { /*! \ingroup PkgClassificationClassifiers - \brief %Classifier based on a random forest algorithm. + \brief %Classifier based on the OpenCV version of random forest algorithm. \note This class requires the \ref thirdpartyOpenCV library. \cgalModels `CGAL::Classification::Classifier` */ -class Random_forest_classifier +class OpenCV_random_forest_classifier { const Label_set& m_labels; const Feature_set& m_features; @@ -73,13 +73,13 @@ public: \param max_number_of_trees_in_the_forest The maximum number of trees in the forest (surprise, surprise). Typically the more trees you have the better the accuracy. However, the improvement in accuracy generally diminishes and asymptotes pass a certain number of trees. Also to keep in mind, the number of tree increases the prediction time linearly. \param forest_accuracy Sufficient accuracy (OOB error). */ - Random_forest_classifier (const Label_set& labels, - const Feature_set& features, - int max_depth = 20, - int min_sample_count = 5, - int max_categories = 15, - int max_number_of_trees_in_the_forest = 100, - float forest_accuracy = 0.01f) + OpenCV_random_forest_classifier (const Label_set& labels, + const Feature_set& features, + int max_depth = 20, + int min_sample_count = 5, + int max_categories = 15, + int max_number_of_trees_in_the_forest = 100, + float forest_accuracy = 0.01f) : m_labels (labels), m_features (features), m_max_depth (max_depth), m_min_sample_count (min_sample_count), m_max_categories (max_categories), @@ -91,7 +91,7 @@ public: { } /// \cond SKIP_IN_MANUAL - ~Random_forest_classifier () + ~OpenCV_random_forest_classifier () { #if (CV_MAJOR_VERSION < 3) if (rtree != NULL) @@ -257,4 +257,4 @@ public: } -#endif // CGAL_CLASSIFICATION_RANDOM_FOREST_CLASSIFIER_H +#endif // CGAL_CLASSIFICATION_OPENCV_RANDOM_FOREST_CLASSIFIER_H From 1b455ff6ecd4d88236695ecf7454808047bcd8a3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 23 Oct 2017 14:55:47 +0200 Subject: [PATCH 31/70] Fix useless copies of Image (very costly with large scenes) --- .../include/CGAL/Classification/Image.h | 47 +++++-------------- 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/Classification/include/CGAL/Classification/Image.h b/Classification/include/CGAL/Classification/Image.h index ae51ce3aa1d..3794b9b755a 100644 --- a/Classification/include/CGAL/Classification/Image.h +++ b/Classification/include/CGAL/Classification/Image.h @@ -23,6 +23,8 @@ #include +#include + namespace CGAL { namespace Classification { @@ -33,9 +35,13 @@ class Image { std::size_t m_width; std::size_t m_height; - Type* m_raw; - + boost::shared_ptr > m_raw; + // Forbid using copy constructor + Image (const Image&) + { + } + public: Image () : m_width(0), m_height(0), m_raw (NULL) @@ -47,50 +53,23 @@ public: m_height (height) { if (m_width * m_height > 0) - m_raw = new Type[width * height](); - else - m_raw = NULL; + m_raw = boost::shared_ptr > (new std::vector(m_width * m_height)); } ~Image () { - free(); } void free() { - if (m_raw != NULL) - delete[] m_raw; - m_raw = NULL; + m_raw = boost::shared_ptr >(); } - Image (const Image& other) - : m_width (other.width()), - m_height (other.height()) - - { - if (m_width * m_height > 0) - { - m_raw = new Type[m_width * m_height]; - std::copy (other.m_raw, other.m_raw + (m_width * m_height), this->m_raw); - } - else - m_raw = NULL; - } Image& operator= (const Image& other) { - if (m_raw != NULL) - delete[] m_raw; - - m_raw = NULL; + m_raw = other.m_raw; m_width = other.width(); m_height = other.height(); - if (m_width * m_height > 0) - { - m_raw = new Type[m_width * m_height]; - std::copy (other.m_raw, other.m_raw + (m_width * m_height), this->m_raw); - } - return *this; } @@ -100,12 +79,12 @@ public: Type& operator() (const std::size_t& x, const std::size_t& y) { // return m_raw[y * m_width + x]; - return m_raw[x * m_height + y]; + return (*m_raw)[x * m_height + y]; } const Type& operator() (const std::size_t& x, const std::size_t& y) const { // return m_raw[y * m_width + x]; - return m_raw[x * m_height + y]; + return (*m_raw)[x * m_height + y]; } From c63df7a3046826616ab0a104c8b755b6e6fd5fc5 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 24 Oct 2017 10:41:06 +0200 Subject: [PATCH 32/70] Fallback mode using map if vector is too large (useful for sparse scenes) --- .../Classification/Feature/Echo_scatter.h | 17 ++-- .../CGAL/Classification/Feature/Elevation.h | 83 +++++++++---------- .../Feature/Vertical_dispersion.h | 3 +- .../include/CGAL/Classification/Image.h | 36 ++++++-- 4 files changed, 81 insertions(+), 58 deletions(-) diff --git a/Classification/include/CGAL/Classification/Feature/Echo_scatter.h b/Classification/include/CGAL/Classification/Feature/Echo_scatter.h index 98e0986d834..62425abfe75 100644 --- a/Classification/include/CGAL/Classification/Feature/Echo_scatter.h +++ b/Classification/include/CGAL/Classification/Feature/Echo_scatter.h @@ -81,14 +81,15 @@ public: Image_float Scatter(grid.width(), grid.height()); for (std::size_t j = 0; j < grid.height(); j++) for (std::size_t i = 0; i < grid.width(); i++) - Scatter(i,j)=0; + if (grid.has_points(i,j)) + Scatter(i,j)=0; std::size_t square = (std::size_t)(0.5 * radius_neighbors / grid.resolution()) + 1; - for (std::size_t j = 0; j < grid.height(); j++){ - for (std::size_t i = 0; i < grid.width(); i++){ - - if(grid.has_points(i,j)){ + for (std::size_t j = 0; j < grid.height(); j++) + for (std::size_t i = 0; i < grid.width(); i++) + if(grid.has_points(i,j)) + { std::size_t squareXmin = (i < square ? 0 : i - square); std::size_t squareXmax = (std::min) (grid.width()-1, i + square); @@ -121,12 +122,8 @@ public: } Scatter(i,j)=(float)NB_echo_sup/NB_echo_total; - } - - } - - } + for(std::size_t i = 0; i < input.size(); i++){ std::size_t I= grid.x(i); std::size_t J= grid.y(i); diff --git a/Classification/include/CGAL/Classification/Feature/Elevation.h b/Classification/include/CGAL/Classification/Feature/Elevation.h index b5d9784f620..7b1727203c3 100644 --- a/Classification/include/CGAL/Classification/Feature/Elevation.h +++ b/Classification/include/CGAL/Classification/Feature/Elevation.h @@ -99,43 +99,43 @@ public: for (std::size_t j = 0; j < grid.height(); ++ j) for (std::size_t i = 0; i < grid.width(); ++ i) - { - float mean = 0.; - std::size_t nb = 0; - typename Grid::iterator end = grid.indices_end(i,j); - for (typename Grid::iterator it = grid.indices_begin(i,j); it != end; ++ it) + if (grid.has_points(i,j)) { - mean += float(get(point_map, *(input.begin()+(*it))).z()); - ++ nb; + float mean = 0.; + std::size_t nb = 0; + typename Grid::iterator end = grid.indices_end(i,j); + for (typename Grid::iterator it = grid.indices_begin(i,j); it != end; ++ it) + { + mean += float(get(point_map, *(input.begin()+(*it))).z()); + ++ nb; + } + if (nb == 0) + continue; + mean /= nb; + dem(i,j) = mean; } - if (nb == 0) - continue; - mean /= nb; - dem(i,j) = mean; - } std::size_t square = (std::size_t)(0.5 * radius_dtm / grid.resolution()) + 1; Image_float dtm_x(grid.width(),grid.height()); for (std::size_t j = 0; j < grid.height(); ++ j) - { for (std::size_t i = 0; i < grid.width(); ++ i) - { - std::size_t squareXmin = (i < square ? 0 : i - square); - std::size_t squareXmax = (std::min)(grid.width() - 1, i + square); + if (grid.has_points(i,j)) + { + std::size_t squareXmin = (i < square ? 0 : i - square); + std::size_t squareXmax = (std::min)(grid.width() - 1, i + square); - std::vector z; - z.reserve(squareXmax - squareXmin +1 ); - for(std::size_t k = squareXmin; k <= squareXmax; k++) - if (dem(k,j) != 0.) - z.push_back (dem(k,j)); - if (z.empty()) - continue; - std::nth_element (z.begin(), z.begin() + (z.size() / 10), z.end()); - dtm_x(i,j) = z[z.size() / 10]; - } - } + std::vector z; + z.reserve(squareXmax - squareXmin +1 ); + for(std::size_t k = squareXmin; k <= squareXmax; k++) + if (dem(k,j) != 0.) + z.push_back (dem(k,j)); + if (z.empty()) + continue; + std::nth_element (z.begin(), z.begin() + (z.size() / 10), z.end()); + dtm_x(i,j) = z[z.size() / 10]; + } dem.free(); #ifdef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES @@ -145,22 +145,21 @@ public: #endif for (std::size_t i = 0; i < grid.width(); ++ i) - { for (std::size_t j = 0; j < grid.height(); ++ j) - { - std::size_t squareYmin = (j < square ? 0 : j - square); - std::size_t squareYmax = (std::min)(grid.height() - 1, j + square); - std::vector z; - z.reserve(squareYmax - squareYmin +1 ); - for(std::size_t l = squareYmin; l <= squareYmax; l++) - if (dtm_x(i,l) != 0.) - z.push_back (dtm_x(i,l)); - if (z.empty()) - continue; - std::nth_element (z.begin(), z.begin() + (z.size() / 10), z.end()); - dtm(i,j) = z[z.size() / 10]; - } - } + if (grid.has_points(i,j)) + { + std::size_t squareYmin = (j < square ? 0 : j - square); + std::size_t squareYmax = (std::min)(grid.height() - 1, j + square); + std::vector z; + z.reserve(squareYmax - squareYmin +1 ); + for(std::size_t l = squareYmin; l <= squareYmax; l++) + if (dtm_x(i,l) != 0.) + z.push_back (dtm_x(i,l)); + if (z.empty()) + continue; + std::nth_element (z.begin(), z.begin() + (z.size() / 10), z.end()); + dtm(i,j) = z[z.size() / 10]; + } dtm_x.free(); #ifdef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES diff --git a/Classification/include/CGAL/Classification/Feature/Vertical_dispersion.h b/Classification/include/CGAL/Classification/Feature/Vertical_dispersion.h index 8e84aaa7ef8..6a68424ec9e 100644 --- a/Classification/include/CGAL/Classification/Feature/Vertical_dispersion.h +++ b/Classification/include/CGAL/Classification/Feature/Vertical_dispersion.h @@ -99,7 +99,8 @@ public: for (std::size_t j = 0; j < grid.height(); j++) for (std::size_t i = 0; i < grid.width(); i++) - Dispersion(i,j)=0; + if (grid.has_points(i,j)) + Dispersion(i,j)=0; std::size_t square = (std::size_t)(0.5 * radius_neighbors / grid.resolution()) + 1; typename GeomTraits::Vector_3 verti (0., 0., 1.); diff --git a/Classification/include/CGAL/Classification/Image.h b/Classification/include/CGAL/Classification/Image.h index 3794b9b755a..2c3aeecff9a 100644 --- a/Classification/include/CGAL/Classification/Image.h +++ b/Classification/include/CGAL/Classification/Image.h @@ -25,6 +25,8 @@ #include +#define CGAL_CLASSIFICATION_IMAGE_SIZE_LIMIT 10000000 + namespace CGAL { namespace Classification { @@ -33,9 +35,14 @@ namespace Classification { template class Image { + typedef std::vector Vector; + typedef std::map Map; + std::size_t m_width; std::size_t m_height; - boost::shared_ptr > m_raw; + boost::shared_ptr m_raw; + boost::shared_ptr m_sparse; + Type m_default; // Forbid using copy constructor Image (const Image&) @@ -53,7 +60,12 @@ public: m_height (height) { if (m_width * m_height > 0) - m_raw = boost::shared_ptr > (new std::vector(m_width * m_height)); + { + if (m_width * m_height < CGAL_CLASSIFICATION_IMAGE_SIZE_LIMIT) + m_raw = boost::shared_ptr (new Vector(m_width * m_height)); + else + m_sparse = boost::shared_ptr (new Map()); + } } ~Image () @@ -62,12 +74,14 @@ public: void free() { - m_raw = boost::shared_ptr >(); + m_raw = boost::shared_ptr(); + m_sparse = boost::shared_ptr(); } Image& operator= (const Image& other) { m_raw = other.m_raw; + m_sparse = other.m_sparse; m_width = other.width(); m_height = other.height(); return *this; @@ -78,12 +92,24 @@ public: Type& operator() (const std::size_t& x, const std::size_t& y) { - // return m_raw[y * m_width + x]; + if (m_raw == boost::shared_ptr()) // sparse case + { + typename Map::iterator inserted = m_sparse->insert (std::make_pair (x * m_height + y, Type())).first; + return inserted->second; + } + return (*m_raw)[x * m_height + y]; } const Type& operator() (const std::size_t& x, const std::size_t& y) const { - // return m_raw[y * m_width + x]; + if (m_raw == boost::shared_ptr()) // sparse case + { + typename Map::iterator found = m_sparse->find (x * m_height + y); + if (found != m_sparse->end()) + return found->second; + return m_default; + } + return (*m_raw)[x * m_height + y]; } From d65cdbd8d9a3047833ff7f7d74321236fc2c1da7 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 24 Oct 2017 11:11:39 +0200 Subject: [PATCH 33/70] Update plugin with Random forest name change --- .../Plugins/Classification/Item_classification_base.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index db14b856420..9ed94dfd2a2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -11,7 +11,7 @@ #include #ifdef CGAL_LINKED_WITH_OPENCV -#include +#include #endif class Item_classification_base @@ -25,7 +25,7 @@ public: typedef CGAL::Classification::ETHZ_random_forest_classifier ETHZ_random_forest; #ifdef CGAL_LINKED_WITH_OPENCV - typedef CGAL::Classification::Random_forest_classifier Random_forest; + typedef CGAL::Classification::OpenCV_random_forest_classifier Random_forest; #endif public: @@ -131,7 +131,8 @@ public: } else if (classifier == 1) { - m_ethz->save_configuration (filename); + std::ofstream f (filename, std::ios_base::binary); + m_ethz->save_configuration (f); } else { @@ -155,7 +156,8 @@ public: } else if (classifier == 1) { - m_ethz->load_configuration (filename); + std::ifstream f (filename, std::ios_base::binary); + m_ethz->load_configuration (f); } else { From b019c5a4f0c129c1e71fbae979e63a8c51085a1d Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 24 Oct 2017 14:26:01 +0200 Subject: [PATCH 34/70] Bugfix: prevent division by 0 --- .../Classification/internal/auxiliary/random-forest/node.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp index 7b869c85a12..13458e90fb3 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp @@ -161,8 +161,9 @@ public: node_dist[label] += 1.0f; } - for (std::size_t i = 0; i < node_dist.size(); ++ i) - node_dist[i] /= n_samples; + if (n_samples != 0) + for (std::size_t i = 0; i < node_dist.size(); ++ i) + node_dist[i] /= n_samples; bool do_split = // Only split if ... (n_samples >= params->min_samples_per_node) && // enough samples are available From 73d2b5d68ab6c6097763f140509082cf4e6a237f Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 24 Oct 2017 14:54:07 +0200 Subject: [PATCH 35/70] Fix IO methods for ETHZ RF config --- .../Plugins/Classification/Item_classification_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h index 9ed94dfd2a2..296918e38c3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -131,7 +131,7 @@ public: } else if (classifier == 1) { - std::ofstream f (filename, std::ios_base::binary); + std::ofstream f (filename, std::ios_base::out | std::ios_base::binary); m_ethz->save_configuration (f); } else @@ -156,7 +156,7 @@ public: } else if (classifier == 1) { - std::ifstream f (filename, std::ios_base::binary); + std::ifstream f (filename, std::ios_base::in | std::ios_base::binary); m_ethz->load_configuration (f); } else From 1b25f47f957ddc56ed049ff037443caaf0cb4171 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 24 Oct 2017 14:54:43 +0200 Subject: [PATCH 36/70] Small bugfix (stop criteria if flow goes to 0) --- .../Surface_mesh_segmentation/Alpha_expansion_graph_cut.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Alpha_expansion_graph_cut.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Alpha_expansion_graph_cut.h index 0297df79608..17b8a2c53c8 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Alpha_expansion_graph_cut.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Alpha_expansion_graph_cut.h @@ -296,7 +296,7 @@ public: cut_time += timer.time(); #endif - if(min_cut - flow < flow * tolerance) { + if(min_cut - flow <= flow * tolerance) { continue; } min_cut = flow; @@ -534,7 +534,7 @@ public: cut_time += timer.time(); #endif - if(min_cut - flow < flow * tolerance) { + if(min_cut - flow <= flow * tolerance) { continue; } min_cut = flow; @@ -664,7 +664,7 @@ public: cut_time += timer.time(); #endif - if(min_cut - flow < flow * tolerance) { + if(min_cut - flow <= flow * tolerance) { continue; } From 4bf23d62f111d40658681cf5bc7909809b3d567a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 27 Nov 2017 14:31:51 +0100 Subject: [PATCH 37/70] Increase limit of dense images --- Classification/include/CGAL/Classification/Image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classification/include/CGAL/Classification/Image.h b/Classification/include/CGAL/Classification/Image.h index 2c3aeecff9a..27f693ba3aa 100644 --- a/Classification/include/CGAL/Classification/Image.h +++ b/Classification/include/CGAL/Classification/Image.h @@ -25,7 +25,7 @@ #include -#define CGAL_CLASSIFICATION_IMAGE_SIZE_LIMIT 10000000 +#define CGAL_CLASSIFICATION_IMAGE_SIZE_LIMIT 100000000 namespace CGAL { namespace Classification { From 96cab8be236aef22dc9c2156566792a70af0387e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 27 Nov 2017 16:44:38 +0100 Subject: [PATCH 38/70] Add ETH Zurich repository in biblio --- Documentation/doc/biblio/cgal_manual.bib | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/doc/biblio/cgal_manual.bib b/Documentation/doc/biblio/cgal_manual.bib index 0beb61629ed..7cddb0fbad8 100644 --- a/Documentation/doc/biblio/cgal_manual.bib +++ b/Documentation/doc/biblio/cgal_manual.bib @@ -2125,6 +2125,16 @@ location = {Salt Lake City, Utah, USA} ,update = "97.04 kettner" } +@Misc{ cgal:w-erftl-14, + key = {ETHZRandomForest}, + title = {{ETH Zurich Random Forest Template Library}}, + howpublished = {Stefan Walk (ETH Zurich, Department of Civil, + Environmental and Geomatic Engineering, Institute of + Geodesy and Photogrammetry)}, + url = {http://www.prs.igp.ethz.ch/research/Source_code_and_datasets.html}, + year = 2014 +} + @book{cgal:ww-smgd-02 ,author = "Joe Warren and Henrik Weimer" ,title = "Subdivision Methods for Geometric Design" From b9f52f7e2b5a7f9fa81997fbabce3236e2fc9803 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 27 Nov 2017 16:49:02 +0100 Subject: [PATCH 39/70] Update reference manual of Classification --- .../doc/Classification/Concepts/Classifier.h | 3 +- .../doc/Classification/PackageDescription.txt | 4 +- .../ETHZ_random_forest_classifier.h | 58 +++++++++++++++++-- .../Classification/Feature/Simple_feature.h | 1 + .../OpenCV_random_forest_classifier.h | 55 +++++++++++++++--- 5 files changed, 106 insertions(+), 15 deletions(-) diff --git a/Classification/doc/Classification/Concepts/Classifier.h b/Classification/doc/Classification/Concepts/Classifier.h index 415672e5046..ce52dcf9f38 100644 --- a/Classification/doc/Classification/Concepts/Classifier.h +++ b/Classification/doc/Classification/Concepts/Classifier.h @@ -13,7 +13,8 @@ Concept describing a classifier used by classification functions (see `CGAL::Classification::classify_with_graphcut()`). \cgalHasModel `CGAL::Classification::Sum_of_weighted_features_classifier` -\cgalHasModel `CGAL::Classification::Random_forest_classifier` +\cgalHasModel `CGAL::Classification::ETHZ_random_forest_classifier` +\cgalHasModel `CGAL::Classification::OpenCV_random_forest_classifier` */ class Classifier diff --git a/Classification/doc/Classification/PackageDescription.txt b/Classification/doc/Classification/PackageDescription.txt index 19f53706960..19746739b6d 100644 --- a/Classification/doc/Classification/PackageDescription.txt +++ b/Classification/doc/Classification/PackageDescription.txt @@ -70,7 +70,8 @@ Features are defined as scalar fields that associates each input item with a spe ## Classifiers ## - `CGAL::Classification::Sum_of_weighted_features_classifier` -- `CGAL::Classification::Random_forest_classifier` +- `CGAL::Classification::ETHZ_random_forest_classifier` +- `CGAL::Classification::OpenCV_random_forest_classifier` ## Data Structures ## @@ -103,6 +104,7 @@ Features are defined as scalar fields that associates each input item with a spe - `CGAL::Classification::Feature::Linearity` - `CGAL::Classification::Feature::Omnivariance` - `CGAL::Classification::Feature::Planarity` +- `CGAL::Classification::Feature::Simple_feature` - `CGAL::Classification::Feature::Sphericity` - `CGAL::Classification::Feature::Sum_eigenvalues` - `CGAL::Classification::Feature::Surface_variation` diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 889ed5c3df6..b82f7babbc9 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -14,6 +14,7 @@ // // $URL$ // $Id$ +// SPDX-License-Identifier: GPL-3.0+ // // Author(s) : Simon Giraudot @@ -45,7 +46,7 @@ namespace Classification { /*! \ingroup PkgClassificationClassifiers - \brief %Classifier based on the ETHZ version of random forest algorithm. + \brief %Classifier based on the ETH Zurich version of random forest algorithm \cgalCite{cgal:w-erftl-14}. \cgalModels `CGAL::Classification::Classifier` */ @@ -61,10 +62,13 @@ class ETHZ_random_forest_classifier public: -/*! - \brief Instantiate the classifier using the sets of `labels` and `features`. + /// \name Constructor + /// @{ + + /*! + \brief Instantiate the classifier using the sets of `labels` and `features`. -*/ + */ ETHZ_random_forest_classifier (const Label_set& labels, const Feature_set& features) : m_labels (labels), m_features (features), m_rfc (NULL) @@ -78,6 +82,11 @@ public: } /// \endcond + /// @} + + /// \name Training + + /// @{ /*! \brief Runs the training algorithm. @@ -93,6 +102,21 @@ public: the corresponding label in the `Label_set` provided in the constructor. Input items that do not have a ground truth information should be given the value `-1`. + + \param reset_trees should be set to `false` if the users wants to + _add_ new trees to the existing forest, and kept to `true` if the + training should be recomputing from scratch (discarding the + current forest). + + \param num_trees number of trees generated by the training + algorithm. Higher values may improve result at the cost of higher + computation times (in general, using a few dozens of trees is + enough). + + \param max_depth maximum depth of the trees. Higher values will + improve how the forest fits the training set. A overly low value + will underfit the test data and conversely an overly high value + will likely overfit. */ template void train (const LabelIndexRange& ground_truth, @@ -153,7 +177,22 @@ public: out[i] = -out[i]; } } + /// \endcond + + /// @} + /// \name Input/Output + /// @{ + + /*! + \brief Saves the current configuration in the stream `output`. + + This allows to easily save and recover a specific classification + configuration. + + The output file is written in an GZIP container that is readable + by the `load_configuration()` method. + */ void save_configuration (std::ostream& output) { boost::iostreams::filtering_ostream outs; @@ -163,6 +202,15 @@ public: oas << BOOST_SERIALIZATION_NVP(*m_rfc); } + /*! + \brief Loads a configuration from the stream `input`. + + The input file should be a GZIP container written by the + `save_configuration()` method. The feature set of the classifier + should contain the exact same features in the exact same order as + the ones present when the file was generated using + `save_configuration()`. + */ void load_configuration (std::istream& input) { liblearning::RandomForest::ForestParams params; @@ -176,7 +224,7 @@ public: boost::archive::text_iarchive ias(ins); ias >> BOOST_SERIALIZATION_NVP(*m_rfc); } - /// \endcond + }; diff --git a/Classification/include/CGAL/Classification/Feature/Simple_feature.h b/Classification/include/CGAL/Classification/Feature/Simple_feature.h index 7ea43a46bf3..828f7e20f3c 100644 --- a/Classification/include/CGAL/Classification/Feature/Simple_feature.h +++ b/Classification/include/CGAL/Classification/Feature/Simple_feature.h @@ -14,6 +14,7 @@ // // $URL$ // $Id$ +// SPDX-License-Identifier: GPL-3.0+ // // Author(s) : Simon Giraudot diff --git a/Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h b/Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h index 17fe563034d..ffe6a08933a 100644 --- a/Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/OpenCV_random_forest_classifier.h @@ -60,6 +60,9 @@ class OpenCV_random_forest_classifier public: + /// \name Constructor + /// @{ + /*! \brief Instantiate the classifier using the sets of `labels` and `features`. @@ -100,6 +103,24 @@ public: } /// \endcond + /// @} + + /// \name Parameters + /// @{ + + void set_max_depth (int max_depth) { m_max_depth = max_depth; } + void set_min_sample_count (int min_sample_count) { m_min_sample_count = min_sample_count; } + void set_max_categories (int max_categories) { m_max_categories = max_categories; } + void set_max_number_of_trees_in_the_forest (int max_number_of_trees_in_the_forest) + { m_max_number_of_trees_in_the_forest = max_number_of_trees_in_the_forest; } + void set_forest_accuracy (float forest_accuracy) { m_forest_accuracy = forest_accuracy; } + + + /// @} + + /// \name Training + /// @{ + /*! \brief Runs the training algorithm. @@ -191,13 +212,8 @@ public: } - void set_max_depth (int max_depth) { m_max_depth = max_depth; } - void set_min_sample_count (int min_sample_count) { m_min_sample_count = min_sample_count; } - void set_max_categories (int max_categories) { m_max_categories = max_categories; } - void set_max_number_of_trees_in_the_forest (int max_number_of_trees_in_the_forest) - { m_max_number_of_trees_in_the_forest = max_number_of_trees_in_the_forest; } - void set_forest_accuracy (float forest_accuracy) { m_forest_accuracy = forest_accuracy; } - + /// @} + /// \cond SKIP_IN_MANUAL void operator() (std::size_t item_index, std::vector& out) const { @@ -232,12 +248,35 @@ public: #endif } + /// \endcond + /// \name Input/Output + /// @{ + + + /*! + \brief Saves the current configuration in the file named `filename`. + + This allows to easily save and recover a specific classification + configuration. + + The output file is written in an XML format that is readable by + the `load_configuration()` method. + */ void save_configuration (const char* filename) { rtree->save(filename); } + /*! + \brief Loads a configuration from the file named `filename`. + + The input file should be in the XML format written by the + `save_configuration()` method. The feature set of the classifier + should contain the exact same features in the exact same order as + the ones present when the file was generated using + `save_configuration()`. + */ void load_configuration (const char* filename) { #if (CV_MAJOR_VERSION < 3) @@ -249,7 +288,7 @@ public: rtree = cv::ml::StatModel::load (filename); #endif } - /// \endcond + }; From e96dac10b499033d284155adb19b641b4b3ecd51 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 28 Nov 2017 14:39:42 +0100 Subject: [PATCH 40/70] Fix conversion warning --- .../include/CGAL/Classification/ETHZ_random_forest_classifier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index b82f7babbc9..aec68d172d6 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -132,7 +132,7 @@ public: std::vector ft; for (std::size_t i = 0; i < ground_truth.size(); ++ i) - if (ground_truth[i] != std::size_t(-1)) + if (ground_truth[i] != -1) { for (std::size_t f = 0; f < m_features.size(); ++ f) ft.push_back(m_features[f]->value(i)); From 497066d68d3e49297d363c5dd57cdd61793b159f Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 28 Nov 2017 14:41:14 +0100 Subject: [PATCH 41/70] Update example with random forest --- .../examples/Classification/CMakeLists.txt | 20 +++-- .../Classification/example_random_forest.cmd | 2 + .../Classification/example_random_forest.cpp | 86 +++++++++++++++---- 3 files changed, 82 insertions(+), 26 deletions(-) create mode 100644 Classification/examples/Classification/example_random_forest.cmd diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 80a80c42062..ec830b242dd 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -21,7 +21,7 @@ include( ${CGAL_USE_FILE} ) # Boost and its components -find_package( Boost REQUIRED ) +find_package( Boost REQUIRED COMPONENTS serialization iostreams) if ( NOT Boost_FOUND ) @@ -55,11 +55,17 @@ endif() create_single_source_cgal_program( "example_generation_and_training.cpp" CXX_FEATURES ${needed_cxx_features} ) create_single_source_cgal_program( "example_feature.cpp" CXX_FEATURES ${needed_cxx_features} ) -if( OpenCV_FOUND ) - include_directories( ${OpenCV_INCLUDE_DIRS} ) - create_single_source_cgal_program( "example_random_forest.cpp" CXX_FEATURES ${needed_cxx_features} ) - target_link_libraries( example_random_forest PRIVATE ${OpenCV_LIBS} ) -else() - message(STATUS "OpenCV not found, random forest example won't be compiled.") +if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) + if( OpenCV_FOUND ) + message(STATUS "Found OpenCV ${OpenCV_VERSION}") + include_directories( ${OpenCV_INCLUDE_DIRS} ) + create_single_source_cgal_program( "example_random_forest.cpp" CXX_FEATURES ${needed_cxx_features} ) + target_link_libraries( example_random_forest ${OpenCV_LIBS} ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) + target_compile_definitions(example_random_forest PUBLIC "-DCGAL_LINKED_WITH_OPENCV") + else() + create_single_source_cgal_program( "example_random_forest.cpp" CXX_FEATURES ${needed_cxx_features} ) + target_link_libraries( example_random_forest ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) + message(STATUS "OpenCV not found, random forest example won't have OpenCV classifier.") + endif() endif() diff --git a/Classification/examples/Classification/example_random_forest.cmd b/Classification/examples/Classification/example_random_forest.cmd new file mode 100644 index 00000000000..3c5cdf03236 --- /dev/null +++ b/Classification/examples/Classification/example_random_forest.cmd @@ -0,0 +1,2 @@ +data/b9_training.ply +-cv data/b9_training.ply diff --git a/Classification/examples/Classification/example_random_forest.cpp b/Classification/examples/Classification/example_random_forest.cpp index 5cc934f4208..f9ba4302531 100644 --- a/Classification/examples/Classification/example_random_forest.cpp +++ b/Classification/examples/Classification/example_random_forest.cpp @@ -31,14 +31,34 @@ typedef Classification::Feature_handle typedef Classification::Label_set Label_set; typedef Classification::Feature_set Feature_set; -typedef Classification::OpenCV_random_forest_classifier Classifier; - typedef Classification::Point_set_feature_generator Feature_generator; int main (int argc, char** argv) { - std::string filename (argc > 1 ? argv[1] : "data/b9_training.ply"); + std::string filename = "data/b9_training.ply"; + bool use_opencv = false; + + if (argc > 1) + { + if (std::string(argv[1]) == "-cv") + { + use_opencv = true; + if (argc > 2) + filename = argv[2]; + } + else + filename = argv[1]; + } + +#ifndef CGAL_LINKED_WITH_OPENCV + if (use_opencv) + { + std::cerr << "OpenCV not available, exiting." << std::endl; + return EXIT_SUCCESS; + } +#endif + std::ifstream in (filename.c_str(), std::ios::binary); Point_set pts; @@ -75,23 +95,51 @@ int main (int argc, char** argv) Label_handle vegetation = labels.add ("vegetation"); Label_handle roof = labels.add ("roof"); - Classifier classifier (labels, features); - - std::cerr << "Training" << std::endl; - t.reset(); - t.start(); - classifier.train (ground_truth); - t.stop(); - std::cerr << "Done in " << t.time() << " second(s)" << std::endl; - - t.reset(); - t.start(); std::vector label_indices(pts.size(), -1); - Classification::classify_with_graphcut - (pts, pts.point_map(), labels, classifier, - generator.neighborhood().k_neighbor_query(12), - 0.2f, 1, label_indices); - t.stop(); + +#ifdef CGAL_LINKED_WITH_OPENCV + if (use_opencv) + { + std::cerr << "Using OpenCV Random Forest Classifier" << std::endl; + Classification::OpenCV_random_forest_classifier classifier (labels, features); + + std::cerr << "Training" << std::endl; + t.reset(); + t.start(); + classifier.train (ground_truth); + t.stop(); + std::cerr << "Done in " << t.time() << " second(s)" << std::endl; + + t.reset(); + t.start(); + Classification::classify_with_graphcut + (pts, pts.point_map(), labels, classifier, + generator.neighborhood().k_neighbor_query(12), + 0.2f, 1, label_indices); + t.stop(); + } + else +#endif + { + std::cerr << "Using ETHZ Random Forest Classifier" << std::endl; + Classification::ETHZ_random_forest_classifier classifier (labels, features); + + std::cerr << "Training" << std::endl; + t.reset(); + t.start(); + classifier.train (ground_truth); + t.stop(); + std::cerr << "Done in " << t.time() << " second(s)" << std::endl; + + t.reset(); + t.start(); + Classification::classify_with_graphcut + (pts, pts.point_map(), labels, classifier, + generator.neighborhood().k_neighbor_query(12), + 0.2f, 1, label_indices); + t.stop(); + } + std::cerr << "Classification with graphcut done in " << t.time() << " second(s)" << std::endl; std::cerr << "Precision, recall, F1 scores and IoU:" << std::endl; From d78ff28d53efb130e7241626f17f9178c772c460 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 28 Nov 2017 14:41:27 +0100 Subject: [PATCH 42/70] Update user manual of classification --- .../doc/Classification/Classification.txt | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/Classification/doc/Classification/Classification.txt b/Classification/doc/Classification/Classification.txt index 85090025312..e2487567760 100644 --- a/Classification/doc/Classification/Classification.txt +++ b/Classification/doc/Classification/Classification.txt @@ -80,7 +80,9 @@ For more details about how these different features can help to identify one lab Finally, if the input data set has additional properties, these can also be used as features. For example, \cgal provides the following features: - [Echo_scatter](@ref CGAL::Classification::Feature::Echo_scatter) uses the number of returns (echo) provided by most LIDAR scanners if available; -- [Hsv](@ref CGAL::Classification::Feature::Hsv) uses input color information if available. +- [Hsv](@ref CGAL::Classification::Feature::Hsv) uses input color information if available; +- [Simple_feature](@ref CGAL::Classification::Feature::Simple_feature) uses any property map applicable to the input range and whose value type is castable to `float` (useful if an additional property of the input set should be used as is, for example and `intensity` measurement). + In the following code snippet, a subset of these features are instantiated. Note that all the predefined features can also be automatically generated in multiple scales (see \ref Classification_feature_generator). @@ -117,7 +119,7 @@ The following snippet shows how to use the feature generator: %Classification relies on a classifier: this classifier is an object that, from the set of values taken by the features at an input item, computes the energy that measures the likelihood of an input item to belong to one label or another. A model of the concept `CGAL::Classification::Classifier` must take the index of an input item and store the energies associated to each label in a vector. If a classifier returns the value 0 for a pair of label and input item, it means that this item belongs to this label with certainty; large values mean that this item is not likely to belong to this label. -\cgal provides two models for this concept, [Sum_of_weighted_features_classifier](@ref CGAL::Classification::Sum_of_weighted_features_classifier) and [Random_forest_classifier](@ref CGAL::Classification::Random_forest_classifier). +\cgal provides three models for this concept, [Sum_of_weighted_features_classifier](@ref CGAL::Classification::Sum_of_weighted_features_classifier), [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier) and [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier). To perform classification based on these classifiers, please refer to \ref Classification_classification_functions. @@ -194,22 +196,43 @@ Figure \cgalFigureRef{Classification_sowf_result_fig} shows an example of output Example of classification on a point set with medium noise and outliers (left: input, right: output). _Ground_ is orange, _roofs_ are pink, _vegetation_ is green. Outliers are classified with an additional label _outlier_ in black. \cgalFigureEnd +\subsection Classification_ETHZ_random_forest ETHZ Random Forest -\subsection Classification_random_forest Random Forest - -This second classifier is [Random_forest_classifier](@ref CGAL::Classification::Random_forest_classifier). -It uses the \ref thirdpartyOpenCV library, more specifically the -[Random Trees](http://docs.opencv.org/2.4/modules/ml/doc/random_trees.html) -package. This classifier uses a ground truth training set to construct several -decision trees that are then used to assign a label to each input -item. +\cgal provides [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier), +a classifier based on the Random Forest Template Library developed by +Stefan Walk at ETH Zurich \cgalCite{cgal:w-erftl-14}. This classifier +uses a ground truth training set to construct several decision trees +that are then used to assign a label to each input item. This classifier cannot be set up by hand and requires a ground truth -training set. The training algorithm is faster but usually requires a -higher number of inliers than the previous classifier. +training set. The training algorithm is significantly faster but +usually requires a higher number of inliers than the previous +classifier. The training algorithm uses more memory at runtime and the +configuration files are larger than those produced by +[Sum_of_weighted_features_classifier](@ref CGAL::Classification::Sum_of_weighted_features_classifier), +but the output quality is usually significantly better, especially in +the cases where many labels are used (more than five). An [example](\ref Classification_example_random_forest) shows how to -use this classifier. For more details about the method, please refer +use this classifier. For more details about the algorithm, please refer +to README provided in the [ETH Zurich's code archive](https://www.ethz.ch/content/dam/ethz/special-interest/baug/igp/photogrammetry-remote-sensing-dam/documents/sourcecode-and-datasets/Random%20Forest/rforest.zip). + +\subsection Classification_OpenCV_random_forest OpenCV Random Forest + +This last classifier is [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier). +It uses the \ref thirdpartyOpenCV library, more specifically the +[Random Trees](http://docs.opencv.org/2.4/modules/ml/doc/random_trees.html) +package. + +Note that this classifier usually produces results with a lower +quality than [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier). + +It is provided for the sake of completeness and for testing purposes, +but if you are not sure what to use, we advise using the ETHZ Random +Forest instead. + +An [example](\ref Classification_example_random_forest) shows how to +use this classifier. For more details about the algorithm, please refer to [the official documentation](http://docs.opencv.org/2.4/modules/ml/doc/random_trees.html) of OpenCV. @@ -375,7 +398,7 @@ The following example: \subsection Classification_example_random_forest Random Forest -The following example shows how to use the classifier [Random_forest_classifier](@ref CGAL::Classification::Random_forest_classifier) using an input training set. +The following example shows how to use classifiers [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier) using an input training set. \cgalExample{Classification/example_random_forest.cpp} From ce4c967f12b260e660dd55c37f104f57c62df3da Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 19 Dec 2017 10:26:29 +0100 Subject: [PATCH 43/70] Separate random forest examples --- .../doc/Classification/Classification.txt | 24 ++- .../doc/Classification/examples.txt | 3 +- .../examples/Classification/CMakeLists.txt | 33 ++-- .../example_ethz_random_forest.cpp | 156 ++++++++++++++++++ ...t.cpp => example_opencv_random_forest.cpp} | 68 ++------ .../Classification/example_random_forest.cmd | 2 - .../ETHZ_random_forest_classifier.h | 18 ++ 7 files changed, 223 insertions(+), 81 deletions(-) create mode 100644 Classification/examples/Classification/example_ethz_random_forest.cpp rename Classification/examples/Classification/{example_random_forest.cpp => example_opencv_random_forest.cpp} (72%) delete mode 100644 Classification/examples/Classification/example_random_forest.cmd diff --git a/Classification/doc/Classification/Classification.txt b/Classification/doc/Classification/Classification.txt index e2487567760..700ec6e93ce 100644 --- a/Classification/doc/Classification/Classification.txt +++ b/Classification/doc/Classification/Classification.txt @@ -200,9 +200,11 @@ Example of classification on a point set with medium noise and outliers (left: i \cgal provides [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier), a classifier based on the Random Forest Template Library developed by -Stefan Walk at ETH Zurich \cgalCite{cgal:w-erftl-14}. This classifier -uses a ground truth training set to construct several decision trees -that are then used to assign a label to each input item. +Stefan Walk at ETH Zurich \cgalCite{cgal:w-erftl-14} (the library is +included with the \cgal release, the user does not have to install +anything more). This classifier uses a ground truth training set to +construct several decision trees that are then used to assign a label +to each input item. This classifier cannot be set up by hand and requires a ground truth training set. The training algorithm is significantly faster but @@ -213,7 +215,7 @@ configuration files are larger than those produced by but the output quality is usually significantly better, especially in the cases where many labels are used (more than five). -An [example](\ref Classification_example_random_forest) shows how to +An [example](\ref Classification_example_ethz_random_forest) shows how to use this classifier. For more details about the algorithm, please refer to README provided in the [ETH Zurich's code archive](https://www.ethz.ch/content/dam/ethz/special-interest/baug/igp/photogrammetry-remote-sensing-dam/documents/sourcecode-and-datasets/Random%20Forest/rforest.zip). @@ -231,7 +233,7 @@ It is provided for the sake of completeness and for testing purposes, but if you are not sure what to use, we advise using the ETHZ Random Forest instead. -An [example](\ref Classification_example_random_forest) shows how to +An [example](\ref Classification_example_opencv_random_forest) shows how to use this classifier. For more details about the algorithm, please refer to [the official documentation](http://docs.opencv.org/2.4/modules/ml/doc/random_trees.html) of OpenCV. @@ -396,11 +398,17 @@ The following example: \cgalExample{Classification/example_generation_and_training.cpp} -\subsection Classification_example_random_forest Random Forest +\subsection Classification_example_ethz_random_forest ETHZ Random Forest -The following example shows how to use classifiers [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier) using an input training set. +The following example shows how to use the classifier [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier) using an input training set. -\cgalExample{Classification/example_random_forest.cpp} +\cgalExample{Classification/example_ethz_random_forest.cpp} + +\subsection Classification_example_opencv_random_forest OpenCV Random Forest + +The following example shows how to use the classifier [OpenCV_random_forest_classifier](@ref CGAL::Classification::OpenCV_random_forest_classifier) using an input training set. + +\cgalExample{Classification/example_opencv_random_forest.cpp} \section Classification_history History diff --git a/Classification/doc/Classification/examples.txt b/Classification/doc/Classification/examples.txt index 2ef96507c17..b0f9daf619e 100644 --- a/Classification/doc/Classification/examples.txt +++ b/Classification/doc/Classification/examples.txt @@ -2,5 +2,6 @@ \example Classification/example_classification.cpp \example Classification/example_feature.cpp \example Classification/example_generation_and_training.cpp -\example Classification/example_random_forest.cpp +\example Classification/example_ethz_random_forest.cpp +\example Classification/example_opencv_random_forest.cpp */ diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index ec830b242dd..adedc2e73fd 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -10,10 +10,8 @@ cmake_minimum_required(VERSION 2.8.11) find_package( CGAL QUIET COMPONENTS ) if ( NOT CGAL_FOUND ) - message(STATUS "This project requires the CGAL library, and will not be compiled.") return() - endif() # include helper file @@ -24,11 +22,8 @@ include( ${CGAL_USE_FILE} ) find_package( Boost REQUIRED COMPONENTS serialization iostreams) if ( NOT Boost_FOUND ) - message(STATUS "This project requires the Boost library, and will not be compiled.") - return() - endif() find_package( TBB ) @@ -55,17 +50,21 @@ endif() create_single_source_cgal_program( "example_generation_and_training.cpp" CXX_FEATURES ${needed_cxx_features} ) create_single_source_cgal_program( "example_feature.cpp" CXX_FEATURES ${needed_cxx_features} ) -if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) - if( OpenCV_FOUND ) - message(STATUS "Found OpenCV ${OpenCV_VERSION}") - include_directories( ${OpenCV_INCLUDE_DIRS} ) - create_single_source_cgal_program( "example_random_forest.cpp" CXX_FEATURES ${needed_cxx_features} ) - target_link_libraries( example_random_forest ${OpenCV_LIBS} ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) - target_compile_definitions(example_random_forest PUBLIC "-DCGAL_LINKED_WITH_OPENCV") - else() - create_single_source_cgal_program( "example_random_forest.cpp" CXX_FEATURES ${needed_cxx_features} ) - target_link_libraries( example_random_forest ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) - message(STATUS "OpenCV not found, random forest example won't have OpenCV classifier.") - endif() +if( OpenCV_FOUND ) + message(STATUS "Found OpenCV ${OpenCV_VERSION}") + include_directories( ${OpenCV_INCLUDE_DIRS} ) + create_single_source_cgal_program( "example_opencv_random_forest.cpp" CXX_FEATURES ${needed_cxx_features} ) + target_link_libraries( example_opencv_random_forest ${OpenCV_LIBS} ) + target_compile_definitions(example_opencv_random_forest PUBLIC "-DCGAL_LINKED_WITH_OPENCV") +else() + message(STATUS "OpenCV not found, OpenCV random forest example won't be compiled.") +endif() + +if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) + create_single_source_cgal_program( "example_ethz_random_forest.cpp" CXX_FEATURES ${needed_cxx_features} ) + target_link_libraries( example_ethz_random_forest ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) + target_compile_definitions(example_ethz_random_forest PUBLIC "-DCGAL_LINKED_WITH_BOOST_SERIALIZATION") +else() + message(STATUS "Boost serialization and IO streams not found, ETHZ random forest example won't be compiled.") endif() diff --git a/Classification/examples/Classification/example_ethz_random_forest.cpp b/Classification/examples/Classification/example_ethz_random_forest.cpp new file mode 100644 index 00000000000..423056b12e8 --- /dev/null +++ b/Classification/examples/Classification/example_ethz_random_forest.cpp @@ -0,0 +1,156 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point; +typedef CGAL::Point_set_3 Point_set; +typedef Kernel::Iso_cuboid_3 Iso_cuboid_3; + +typedef Point_set::Point_map Pmap; +typedef Point_set::Property_map Imap; +typedef Point_set::Property_map UCmap; + +namespace Classification = CGAL::Classification; + +typedef Classification::Label_handle Label_handle; +typedef Classification::Feature_handle Feature_handle; +typedef Classification::Label_set Label_set; +typedef Classification::Feature_set Feature_set; + +typedef Classification::Point_set_feature_generator Feature_generator; + + +int main (int argc, char** argv) +{ + std::string filename = "data/b9_training.ply"; + bool use_opencv = false; + + if (argc > 1) + { + if (std::string(argv[1]) == "-cv") + { + use_opencv = true; + if (argc > 2) + filename = argv[2]; + } + else + filename = argv[1]; + } + + std::ifstream in (filename.c_str(), std::ios::binary); + Point_set pts; + + std::cerr << "Reading input" << std::endl; + in >> pts; + + Imap label_map; + bool lm_found = false; + boost::tie (label_map, lm_found) = pts.property_map ("label"); + if (!lm_found) + { + std::cerr << "Error: \"label\" property not found in input file." << std::endl; + return EXIT_FAILURE; + } + + std::vector ground_truth; + ground_truth.reserve (pts.size()); + std::copy (pts.range(label_map).begin(), pts.range(label_map).end(), + std::back_inserter (ground_truth)); + + Feature_set features; + + std::cerr << "Generating features" << std::endl; + CGAL::Real_timer t; + t.start(); + Feature_generator generator (features, pts, pts.point_map(), + 5); // using 5 scales + t.stop(); + std::cerr << "Done in " << t.time() << " second(s)" << std::endl; + + // Add types + Label_set labels; + Label_handle ground = labels.add ("ground"); + Label_handle vegetation = labels.add ("vegetation"); + Label_handle roof = labels.add ("roof"); + + std::vector label_indices(pts.size(), -1); + + std::cerr << "Using ETHZ Random Forest Classifier" << std::endl; + Classification::ETHZ_random_forest_classifier classifier (labels, features); + + std::cerr << "Training" << std::endl; + t.reset(); + t.start(); + classifier.train (ground_truth); + t.stop(); + std::cerr << "Done in " << t.time() << " second(s)" << std::endl; + + t.reset(); + t.start(); + Classification::classify_with_graphcut + (pts, pts.point_map(), labels, classifier, + generator.neighborhood().k_neighbor_query(12), + 0.2f, 1, label_indices); + t.stop(); + + std::cerr << "Classification with graphcut done in " << t.time() << " second(s)" << std::endl; + + std::cerr << "Precision, recall, F1 scores and IoU:" << std::endl; + Classification::Evaluation evaluation (labels, ground_truth, label_indices); + + for (std::size_t i = 0; i < labels.size(); ++ i) + { + std::cerr << " * " << labels[i]->name() << ": " + << evaluation.precision(labels[i]) << " ; " + << evaluation.recall(labels[i]) << " ; " + << evaluation.f1_score(labels[i]) << " ; " + << evaluation.intersection_over_union(labels[i]) << std::endl; + } + + std::cerr << "Accuracy = " << evaluation.accuracy() << std::endl + << "Mean F1 score = " << evaluation.mean_f1_score() << std::endl + << "Mean IoU = " << evaluation.mean_intersection_over_union() << std::endl; + + // Color point set according to class + UCmap red = pts.add_property_map("red", 0).first; + UCmap green = pts.add_property_map("green", 0).first; + UCmap blue = pts.add_property_map("blue", 0).first; + + for (std::size_t i = 0; i < label_indices.size(); ++ i) + { + label_map[i] = label_indices[i]; // update label map with computed classification + + Label_handle label = labels[label_indices[i]]; + + if (label == ground) + { + red[i] = 245; green[i] = 180; blue[i] = 0; + } + else if (label == vegetation) + { + red[i] = 0; green[i] = 255; blue[i] = 27; + } + else if (label == roof) + { + red[i] = 255; green[i] = 0; blue[i] = 170; + } + } + + // Write result + std::ofstream f ("classification.ply"); + f.precision(18); + f << pts; + + std::cerr << "All done" << std::endl; + + return EXIT_SUCCESS; +} diff --git a/Classification/examples/Classification/example_random_forest.cpp b/Classification/examples/Classification/example_opencv_random_forest.cpp similarity index 72% rename from Classification/examples/Classification/example_random_forest.cpp rename to Classification/examples/Classification/example_opencv_random_forest.cpp index f9ba4302531..f14eb20b303 100644 --- a/Classification/examples/Classification/example_random_forest.cpp +++ b/Classification/examples/Classification/example_opencv_random_forest.cpp @@ -1,8 +1,3 @@ -#if defined (_MSC_VER) && !defined (_WIN64) -#pragma warning(disable:4244) // boost::number_distance::distance() - // converts 64 to 32 bits integers -#endif - #include #include #include @@ -51,14 +46,6 @@ int main (int argc, char** argv) filename = argv[1]; } -#ifndef CGAL_LINKED_WITH_OPENCV - if (use_opencv) - { - std::cerr << "OpenCV not available, exiting." << std::endl; - return EXIT_SUCCESS; - } -#endif - std::ifstream in (filename.c_str(), std::ios::binary); Point_set pts; @@ -97,48 +84,23 @@ int main (int argc, char** argv) std::vector label_indices(pts.size(), -1); -#ifdef CGAL_LINKED_WITH_OPENCV - if (use_opencv) - { - std::cerr << "Using OpenCV Random Forest Classifier" << std::endl; - Classification::OpenCV_random_forest_classifier classifier (labels, features); + std::cerr << "Using OpenCV Random Forest Classifier" << std::endl; + Classification::OpenCV_random_forest_classifier classifier (labels, features); - std::cerr << "Training" << std::endl; - t.reset(); - t.start(); - classifier.train (ground_truth); - t.stop(); - std::cerr << "Done in " << t.time() << " second(s)" << std::endl; + std::cerr << "Training" << std::endl; + t.reset(); + t.start(); + classifier.train (ground_truth); + t.stop(); + std::cerr << "Done in " << t.time() << " second(s)" << std::endl; - t.reset(); - t.start(); - Classification::classify_with_graphcut - (pts, pts.point_map(), labels, classifier, - generator.neighborhood().k_neighbor_query(12), - 0.2f, 1, label_indices); - t.stop(); - } - else -#endif - { - std::cerr << "Using ETHZ Random Forest Classifier" << std::endl; - Classification::ETHZ_random_forest_classifier classifier (labels, features); - - std::cerr << "Training" << std::endl; - t.reset(); - t.start(); - classifier.train (ground_truth); - t.stop(); - std::cerr << "Done in " << t.time() << " second(s)" << std::endl; - - t.reset(); - t.start(); - Classification::classify_with_graphcut - (pts, pts.point_map(), labels, classifier, - generator.neighborhood().k_neighbor_query(12), - 0.2f, 1, label_indices); - t.stop(); - } + t.reset(); + t.start(); + Classification::classify_with_graphcut + (pts, pts.point_map(), labels, classifier, + generator.neighborhood().k_neighbor_query(12), + 0.2f, 1, label_indices); + t.stop(); std::cerr << "Classification with graphcut done in " << t.time() << " second(s)" << std::endl; diff --git a/Classification/examples/Classification/example_random_forest.cmd b/Classification/examples/Classification/example_random_forest.cmd deleted file mode 100644 index 3c5cdf03236..00000000000 --- a/Classification/examples/Classification/example_random_forest.cmd +++ /dev/null @@ -1,2 +0,0 @@ -data/b9_training.ply --cv data/b9_training.ply diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index aec68d172d6..55af4855b66 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -33,10 +33,12 @@ #include #include +#ifdef CGAL_LINKED_WITH_BOOST_SERIALIZATION #include #include #include #include +#endif namespace CGAL { @@ -193,6 +195,7 @@ public: The output file is written in an GZIP container that is readable by the `load_configuration()` method. */ +#if defined(CGAL_LINKED_WITH_BOOST_SERIALIZATION) || defined(DOXYGEN_RUNNING) void save_configuration (std::ostream& output) { boost::iostreams::filtering_ostream outs; @@ -201,6 +204,13 @@ public: boost::archive::text_oarchive oas(outs); oas << BOOST_SERIALIZATION_NVP(*m_rfc); } +#else + void save_configuration (std::ostream&) + { + std::cerr << "Error: can't use ETHZ random forest classifier IO functions, " + << "missing Boost Serialization library." << std::endl; + } +#endif /*! \brief Loads a configuration from the stream `input`. @@ -211,6 +221,7 @@ public: the ones present when the file was generated using `save_configuration()`. */ +#if defined(CGAL_LINKED_WITH_BOOST_SERIALIZATION) || defined(DOXYGEN_RUNNING) void load_configuration (std::istream& input) { liblearning::RandomForest::ForestParams params; @@ -224,6 +235,13 @@ public: boost::archive::text_iarchive ias(ins); ias >> BOOST_SERIALIZATION_NVP(*m_rfc); } +#else + void load_configuration (std::istream&) + { + std::cerr << "Error: can't use ETHZ random forest classifier IO functions, " + << "missing Boost Serialization library." << std::endl; + } +#endif }; From 04ab6ed3d5f033a92376d76ae1725022be7721b5 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 20 Dec 2017 16:28:29 +0100 Subject: [PATCH 44/70] Fix classification plugin CMakeLists --- .../Plugins/Classification/CMakeLists.txt | 67 ++++++++----------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index caedb5fb77c..b2116e4748c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -4,48 +4,39 @@ if(EIGEN3_FOUND) qt5_wrap_ui( classificationUI_FILES Classification_widget.ui) polyhedron_demo_plugin(classification_plugin Classification_plugin Point_set_item_classification ${classificationUI_FILES}) - + + set(classification_linked_libraries) + set(classification_compile_definitions) + find_package(Boost COMPONENTS serialization iostreams) + if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) + set(classification_linked_libraries ${classification_linked_libraries} + ${Boost_SERIALIZATION_LIBRARY} + ${Boost_IOSTREAMS_LIBRARY}) + set(classification_compile_definitions ${classification_compile_definitions} + "-DCGAL_LINKED_WITH_BOOST_SERIALIZATION") + else() + message(STATUS "NOTICE: Boost Serialization or IO Streams not found. IO functions for ETHZ classifier won't be available.") + endif() - if (Boost_SERIALIZATION_FOUND) - if (Boost_IOSTREAMS_FOUND) - if (LASLIB_FOUND) - - find_package(OpenCV QUIET) - if (OpenCV_FOUND) - - message(STATUS "Found OpenCV ${OpenCV_VERSION}") - include_directories(${OpenCV_INCLUDE_DIRS}) - target_link_libraries(classification_plugin scene_points_with_normal_item - scene_polylines_item scene_polygon_soup_item scene_color_ramp ${OpenCV_LIBS} - ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY} - ${LASLIB_LIBRARIES}) - - target_compile_definitions(classification_plugin PUBLIC "-DCGAL_LINKED_WITH_OPENCV") - - else(OpenCV_FOUND) - target_link_libraries(classification_plugin scene_points_with_normal_item - scene_polylines_item scene_polygon_soup_item scene_color_ramp - ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY} - ${LASLIB_LIBRARIES}) - - message(STATUS "NOTICE: OpenCV was not found. Random forest predicate for classification will not be available.") - endif(OpenCV_FOUND) - - else(LASLIB_FOUND) - message(STATUS "NOTICE: LAS was not found. Classification plugin will not be available.") - endif(LASLIB_FOUND) - - else(Boost_IOSTREAMS_FOUND) - message(STATUS "NOTICE: Boost_iostreams was not found. Classification plugin will not be available.") - endif(Boost_IOSTREAMS_FOUND) - - else(Boost_SERIALIZATION_FOUND) - message(STATUS "NOTICE: Boost_serialization was not found. Classification plugin will not be available.") - endif(Boost_SERIALIZATION_FOUND) + find_package(OpenCV QUIET) + if (OpenCV_FOUND) + message(STATUS "Found OpenCV ${OpenCV_VERSION}") + include_directories(${OpenCV_INCLUDE_DIRS}) + set(classification_linked_libraries ${classification_linked_libraries} + ${OpenCV_LIBS}) + set(classification_compile_definitions ${classification_compile_definitions} + "-DCGAL_LINKED_WITH_OPENCV") + else() + message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.") + endif() + + target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item + scene_polylines_item scene_polygon_soup_item scene_color_ramp ${classification_linked_libraries}) + target_compile_definitions(classification_plugin PUBLIC ${classification_compile_definitions}) else(EIGEN3_FOUND) message(STATUS "NOTICE: Eigen 3.1 (or greater) was not found. Classification plugin will not be available.") endif() - + From f10503264719ba7f40b52e6d03ff6db4ea14a764 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 21 Dec 2017 10:15:01 +0100 Subject: [PATCH 45/70] Remove boost serialization flag from code --- .../ETHZ_random_forest_classifier.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 55af4855b66..28ad6a74dbf 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -33,12 +33,10 @@ #include #include -#ifdef CGAL_LINKED_WITH_BOOST_SERIALIZATION #include #include #include #include -#endif namespace CGAL { @@ -195,7 +193,6 @@ public: The output file is written in an GZIP container that is readable by the `load_configuration()` method. */ -#if defined(CGAL_LINKED_WITH_BOOST_SERIALIZATION) || defined(DOXYGEN_RUNNING) void save_configuration (std::ostream& output) { boost::iostreams::filtering_ostream outs; @@ -204,13 +201,6 @@ public: boost::archive::text_oarchive oas(outs); oas << BOOST_SERIALIZATION_NVP(*m_rfc); } -#else - void save_configuration (std::ostream&) - { - std::cerr << "Error: can't use ETHZ random forest classifier IO functions, " - << "missing Boost Serialization library." << std::endl; - } -#endif /*! \brief Loads a configuration from the stream `input`. @@ -221,7 +211,6 @@ public: the ones present when the file was generated using `save_configuration()`. */ -#if defined(CGAL_LINKED_WITH_BOOST_SERIALIZATION) || defined(DOXYGEN_RUNNING) void load_configuration (std::istream& input) { liblearning::RandomForest::ForestParams params; @@ -235,14 +224,6 @@ public: boost::archive::text_iarchive ias(ins); ias >> BOOST_SERIALIZATION_NVP(*m_rfc); } -#else - void load_configuration (std::istream&) - { - std::cerr << "Error: can't use ETHZ random forest classifier IO functions, " - << "missing Boost Serialization library." << std::endl; - } -#endif - }; From b9126941ad4a4dfb12d77e75608a3257171ac2db Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 21 Dec 2017 10:15:24 +0100 Subject: [PATCH 46/70] Improve CMakeLists of classification --- .../examples/Classification/CMakeLists.txt | 64 +++++++++++++------ .../test/Classification/CMakeLists.txt | 16 +++++ .../Plugins/Classification/CMakeLists.txt | 35 +++++----- 3 files changed, 78 insertions(+), 37 deletions(-) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index adedc2e73fd..86b9b15692a 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -42,29 +42,55 @@ include_directories( BEFORE ../../include ) include( CGAL_CreateSingleSourceCGALProgram ) +# Classification examples +set(targets + example_classification + example_ethz_random_forest + example_feature + example_generation_and_training) + +# Classification requires some C++11 features set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) -create_single_source_cgal_program( "example_classification.cpp" CXX_FEATURES ${needed_cxx_features} ) -if(TBB_FOUND) - CGAL_target_use_TBB(example_classification) -endif() -create_single_source_cgal_program( "example_generation_and_training.cpp" CXX_FEATURES ${needed_cxx_features} ) -create_single_source_cgal_program( "example_feature.cpp" CXX_FEATURES ${needed_cxx_features} ) -if( OpenCV_FOUND ) - message(STATUS "Found OpenCV ${OpenCV_VERSION}") - include_directories( ${OpenCV_INCLUDE_DIRS} ) - create_single_source_cgal_program( "example_opencv_random_forest.cpp" CXX_FEATURES ${needed_cxx_features} ) - target_link_libraries( example_opencv_random_forest ${OpenCV_LIBS} ) - target_compile_definitions(example_opencv_random_forest PUBLIC "-DCGAL_LINKED_WITH_OPENCV") -else() - message(STATUS "OpenCV not found, OpenCV random forest example won't be compiled.") -endif() +# Libraries and flags +set(classification_linked_libraries) +set(classification_compile_definitions) +find_package(Boost COMPONENTS serialization iostreams) if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) - create_single_source_cgal_program( "example_ethz_random_forest.cpp" CXX_FEATURES ${needed_cxx_features} ) - target_link_libraries( example_ethz_random_forest ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) - target_compile_definitions(example_ethz_random_forest PUBLIC "-DCGAL_LINKED_WITH_BOOST_SERIALIZATION") + set(classification_linked_libraries ${classification_linked_libraries} + ${Boost_SERIALIZATION_LIBRARY} + ${Boost_IOSTREAMS_LIBRARY}) else() - message(STATUS "Boost serialization and IO streams not found, ETHZ random forest example won't be compiled.") + message(STATUS "ERROR: Boost Serialization or IO Streams not found.") + exit() endif() +find_package(OpenCV QUIET) +if (OpenCV_FOUND) + message(STATUS "Found OpenCV ${OpenCV_VERSION}") + include_directories(${OpenCV_INCLUDE_DIRS}) + set(classification_linked_libraries ${classification_linked_libraries} + ${OpenCV_LIBS}) + set(classification_compile_definitions ${classification_compile_definitions} + "-DCGAL_LINKED_WITH_OPENCV") + + set(targets ${targets} example_opencv_random_forest) +else() + message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.") +endif() + +# Creating targets with correct libraries and flags +foreach(target ${targets}) + create_single_source_cgal_program( "${target}.cpp" CXX_FEATURES ${needed_cxx_features} ) + target_link_libraries(${target} PUBLIC ${classification_linked_libraries}) + target_compile_definitions(${target} PUBLIC ${classification_compile_definitions}) + if(TBB_FOUND AND TARGET ${target}) + CGAL_target_use_TBB(${target}) + endif() +endforeach() + + + + + diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index 30b903bf36c..7d69f5960e8 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -53,8 +53,24 @@ include( CGAL_CreateSingleSourceCGALProgram ) #add_definitions("-DCGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE") +# Classification requires some C++11 features set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) + +# Libraries and flags +set(classification_linked_libraries) + +find_package(Boost COMPONENTS serialization iostreams) +if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) + set(classification_linked_libraries ${classification_linked_libraries} + ${Boost_SERIALIZATION_LIBRARY} + ${Boost_IOSTREAMS_LIBRARY}) +else() + message(STATUS "ERROR: Boost Serialization or IO Streams not found.") + exit() +endif() + create_single_source_cgal_program( "test_classification_point_set.cpp" CXX_FEATURES ${needed_cxx_features} ) +target_link_libraries(test_classification_point_set PUBLIC ${classification_linked_libraries}) if(TBB_FOUND) CGAL_target_use_TBB( test_classification_point_set ) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index b2116e4748c..c2834495991 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -13,27 +13,26 @@ if(EIGEN3_FOUND) set(classification_linked_libraries ${classification_linked_libraries} ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) - set(classification_compile_definitions ${classification_compile_definitions} - "-DCGAL_LINKED_WITH_BOOST_SERIALIZATION") + + find_package(OpenCV QUIET) + if (OpenCV_FOUND) + message(STATUS "Found OpenCV ${OpenCV_VERSION}") + include_directories(${OpenCV_INCLUDE_DIRS}) + set(classification_linked_libraries ${classification_linked_libraries} + ${OpenCV_LIBS}) + set(classification_compile_definitions ${classification_compile_definitions} + "-DCGAL_LINKED_WITH_OPENCV") + else() + message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.") + endif() + + target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item + scene_polylines_item scene_polygon_soup_item scene_color_ramp ${classification_linked_libraries}) + target_compile_definitions(classification_plugin PUBLIC ${classification_compile_definitions}) else() - message(STATUS "NOTICE: Boost Serialization or IO Streams not found. IO functions for ETHZ classifier won't be available.") + message(STATUS "NOTICE: Boost Serialization or IO Streams not found. Classification plugin won't be available.") endif() - find_package(OpenCV QUIET) - if (OpenCV_FOUND) - message(STATUS "Found OpenCV ${OpenCV_VERSION}") - include_directories(${OpenCV_INCLUDE_DIRS}) - set(classification_linked_libraries ${classification_linked_libraries} - ${OpenCV_LIBS}) - set(classification_compile_definitions ${classification_compile_definitions} - "-DCGAL_LINKED_WITH_OPENCV") - else() - message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.") - endif() - - target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item - scene_polylines_item scene_polygon_soup_item scene_color_ramp ${classification_linked_libraries}) - target_compile_definitions(classification_plugin PUBLIC ${classification_compile_definitions}) else(EIGEN3_FOUND) message(STATUS "NOTICE: Eigen 3.1 (or greater) was not found. Classification plugin will not be available.") From e08729ca2daca6b38dfa5c6eaf76620804252048 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 21 Dec 2017 10:46:31 +0100 Subject: [PATCH 47/70] Add dependencies to boost libraries in manual --- Classification/doc/Classification/Classification.txt | 4 ++++ Classification/doc/Classification/PackageDescription.txt | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Classification/doc/Classification/Classification.txt b/Classification/doc/Classification/Classification.txt index 700ec6e93ce..bc49f0dd34b 100644 --- a/Classification/doc/Classification/Classification.txt +++ b/Classification/doc/Classification/Classification.txt @@ -8,6 +8,10 @@ namespace CGAL { This component implements the algorithm described in \cgalCite{cgal:lm-clscm-12} (section 2), generalized to handle different types of data, multiple features and multiple labels. It classifies a data set into a user-defined set of labels, such as _ground_, _vegetation_ and _buildings_. A flexible API is provided so that users can classify any type of data which they can index and for which they can compute relevant features, compute their own local features on the input data set and define their own labels. +\note This component depends on the Boost libraries +[Serialization](http://www.boost.org/libs/serialization) and +[IO Streams](http://www.boost.org/libs/iostreams). + \section Classification_Organization Package Organization %Classification of data sets is achieved as follows (see Figure \cgalFigureRef{Classification_organization_fig}): diff --git a/Classification/doc/Classification/PackageDescription.txt b/Classification/doc/Classification/PackageDescription.txt index 19746739b6d..291ebff818c 100644 --- a/Classification/doc/Classification/PackageDescription.txt +++ b/Classification/doc/Classification/PackageDescription.txt @@ -47,6 +47,8 @@ Features are defined as scalar fields that associates each input item with a spe \cgalPkgShortInfoBegin \cgalPkgSince{4.9} +\cgalPkgDependsOn{\ref PkgSolverSummary, \ref PkgSpatialSearchingDSummary, [Boost Serialization](http://www.boost.org/libs/serialization) and +[Boost IO Streams](http://www.boost.org/libs/iostreams)} \cgalPkgBib{cgal:lm-clscm-12} \cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgDemo{Operations on Polyhedra,polyhedron_3.zip} From 718366a0b94e2078952e9e7c0a6f027389d31119 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 21 Dec 2017 10:47:04 +0100 Subject: [PATCH 48/70] Add license headers to included ETHZ liblearning library --- .../internal/auxiliary/dataview.h | 26 +++++++++++++++++++ .../random-forest/common-libraries.hpp | 26 +++++++++++++++++++ .../auxiliary/random-forest/forest.hpp | 26 +++++++++++++++++++ .../auxiliary/random-forest/node-gini.hpp | 26 +++++++++++++++++++ .../internal/auxiliary/random-forest/node.hpp | 26 +++++++++++++++++++ .../internal/auxiliary/random-forest/tree.hpp | 26 +++++++++++++++++++ 6 files changed, 156 insertions(+) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h b/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h index e8a1ee9b3f9..095e3a8b671 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h +++ b/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h @@ -1,3 +1,29 @@ +// Copyright (c) 2014 Stefan Walk +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: MIT +// +// Author(s) : Stefan Walk + #ifndef LIBLEARNING_DATAVIEW_H #define LIBLEARNING_DATAVIEW_H #include diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp index 41c2dcaefe7..00b51a0dab1 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp @@ -1,3 +1,29 @@ +// Copyright (c) 2014 Stefan Walk +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: MIT +// +// Author(s) : Stefan Walk + #ifndef LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H #define LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H #include diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp index 774baf53134..97c25b40df5 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp @@ -1,3 +1,29 @@ +// Copyright (c) 2014 Stefan Walk +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: MIT +// +// Author(s) : Stefan Walk + #ifndef LIBLEARNING_RANDOMFOREST_FOREST_H #define LIBLEARNING_RANDOMFOREST_FOREST_H #include "common-libraries.hpp" diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp index 96302de889f..a2e9f66c049 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp @@ -1,3 +1,29 @@ +// Copyright (c) 2014 Stefan Walk +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: MIT +// +// Author(s) : Stefan Walk + #ifndef LIBLEARNING_RANDOMFOREST_NODE_GINI_H #define LIBLEARNING_RANDOMFOREST_NODE_GINI_H #include "node.hpp" diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp index 13458e90fb3..dcc7b8da9c2 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp @@ -1,3 +1,29 @@ +// Copyright (c) 2014 Stefan Walk +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: MIT +// +// Author(s) : Stefan Walk + #ifndef LIBLEARNING_RANDOMFORESTS_NODE_H #define LIBLEARNING_RANDOMFORESTS_NODE_H #include "../dataview.h" diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp index 50f214fd62e..1c76b57c91b 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp @@ -1,3 +1,29 @@ +// Copyright (c) 2014 Stefan Walk +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: MIT +// +// Author(s) : Stefan Walk + #ifndef LIBLEARNING_RANDOMFOREST_TREE_H #define LIBLEARNING_RANDOMFOREST_TREE_H #include "../dataview.h" From 8f076ae77f6420cbf398e50054ee38c1e5528697 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 21 Dec 2017 11:14:33 +0100 Subject: [PATCH 49/70] Move liblearning to CGAL::internal and document changes from original library --- .../ETHZ_random_forest_classifier.h | 18 +++++++++--------- .../internal/auxiliary/dataview.h | 15 +++++++++++++-- .../random-forest/common-libraries.hpp | 12 ++++++++++-- .../auxiliary/random-forest/forest.hpp | 15 +++++++++++++-- .../auxiliary/random-forest/node-gini.hpp | 13 +++++++++++-- .../internal/auxiliary/random-forest/node.hpp | 14 ++++++++++++-- .../internal/auxiliary/random-forest/tree.hpp | 13 +++++++++++-- 7 files changed, 79 insertions(+), 21 deletions(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 28ad6a74dbf..365d5e93398 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -52,9 +52,9 @@ namespace Classification { */ class ETHZ_random_forest_classifier { - typedef liblearning::RandomForest::RandomForest - < liblearning::RandomForest::NodeGini - < liblearning::RandomForest::AxisAlignedSplitter> > Forest; + typedef CGAL::internal::liblearning::RandomForest::RandomForest + < CGAL::internal::liblearning::RandomForest::NodeGini + < CGAL::internal::liblearning::RandomForest::AxisAlignedSplitter> > Forest; const Label_set& m_labels; const Feature_set& m_features; @@ -124,7 +124,7 @@ public: std::size_t num_trees = 25, std::size_t max_depth = 20) { - liblearning::RandomForest::ForestParams params; + CGAL::internal::liblearning::RandomForest::ForestParams params; params.n_trees = num_trees; params.max_depth = max_depth; @@ -139,8 +139,8 @@ public: gt.push_back(ground_truth[i]); } - liblearning::DataView2D label_vector (&(gt[0]), gt.size(), 1); - liblearning::DataView2D feature_vector(&(ft[0]), gt.size(), ft.size() / gt.size()); + CGAL::internal::liblearning::DataView2D label_vector (&(gt[0]), gt.size(), 1); + CGAL::internal::liblearning::DataView2D feature_vector(&(ft[0]), gt.size(), ft.size() / gt.size()); if (m_rfc != NULL && reset_trees) { @@ -151,9 +151,9 @@ public: if (m_rfc == NULL) m_rfc = new Forest (params); - liblearning::RandomForest::AxisAlignedRandomSplitGenerator generator; + CGAL::internal::liblearning::RandomForest::AxisAlignedRandomSplitGenerator generator; - m_rfc->train(feature_vector, label_vector, liblearning::DataView2D(), generator, 0, false, reset_trees); + m_rfc->train(feature_vector, label_vector, CGAL::internal::liblearning::DataView2D(), generator, 0, false, reset_trees); } /// \cond SKIP_IN_MANUAL @@ -213,7 +213,7 @@ public: */ void load_configuration (std::istream& input) { - liblearning::RandomForest::ForestParams params; + CGAL::internal::liblearning::RandomForest::ForestParams params; if (m_rfc != NULL) delete m_rfc; m_rfc = new Forest (params); diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h b/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h index 095e3a8b671..537b3b23a36 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h +++ b/Classification/include/CGAL/Classification/internal/auxiliary/dataview.h @@ -24,9 +24,17 @@ // // Author(s) : Stefan Walk -#ifndef LIBLEARNING_DATAVIEW_H -#define LIBLEARNING_DATAVIEW_H +// Modifications from original library: +// * changed inclusion protection tag +// * moved to namespace CGAL::internal:: + + +#ifndef CGAL_INTERNAL_LIBLEARNING_DATAVIEW_H +#define CGAL_INTERNAL_LIBLEARNING_DATAVIEW_H #include + +namespace CGAL { namespace internal { + namespace liblearning { //! \brief A view for one-dimensional data // @@ -164,4 +172,7 @@ bool equal_dims(DataView2D view_a, DataView2D view_b) return view_a.rows == view_b.rows && view_a.cols == view_b.cols; } } + +}} // namespace CGAL::internal:: + #endif diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp index 00b51a0dab1..3d9b9a60553 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/common-libraries.hpp @@ -24,8 +24,12 @@ // // Author(s) : Stefan Walk -#ifndef LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H -#define LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H +// Modifications from original library: +// * changed inclusion protection tag +// * moved to namespace CGAL::internal:: + +#ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H +#define CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_COMMON_LIBRARIES_H #include #include #include @@ -52,6 +56,8 @@ #include "../dataview.h" +namespace CGAL { namespace internal { + namespace liblearning { namespace RandomForest { @@ -329,4 +335,6 @@ struct QuadraticSplitGenerator { } } +}} // namespace CGAL::internal:: + #endif diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp index 97c25b40df5..a419baf7953 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp @@ -24,8 +24,14 @@ // // Author(s) : Stefan Walk -#ifndef LIBLEARNING_RANDOMFOREST_FOREST_H -#define LIBLEARNING_RANDOMFOREST_FOREST_H +// Modifications from original library: +// * changed inclusion protection tag +// * moved to namespace CGAL::internal:: +// * add parameter "reset_trees" to train() to be able to construct +// forest with several iterations + +#ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_FOREST_H +#define CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_FOREST_H #include "common-libraries.hpp" #include "tree.hpp" #include @@ -33,6 +39,8 @@ #include #endif +namespace CGAL { namespace internal { + namespace liblearning { namespace RandomForest { @@ -173,4 +181,7 @@ public: } } + +}} // namespace CGAL::internal:: + #endif diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp index a2e9f66c049..931a95bbb3a 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp @@ -24,11 +24,17 @@ // // Author(s) : Stefan Walk -#ifndef LIBLEARNING_RANDOMFOREST_NODE_GINI_H -#define LIBLEARNING_RANDOMFOREST_NODE_GINI_H +// Modifications from original library: +// * changed inclusion protection tag +// * moved to namespace CGAL::internal:: + +#ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_NODE_GINI_H +#define CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_NODE_GINI_H #include "node.hpp" #include "common-libraries.hpp" +namespace CGAL { namespace internal { + namespace liblearning { namespace RandomForest { @@ -104,4 +110,7 @@ public: } } + +}} // namespace CGAL::internal:: + #endif diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp index dcc7b8da9c2..00e86323f84 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node.hpp @@ -24,8 +24,13 @@ // // Author(s) : Stefan Walk -#ifndef LIBLEARNING_RANDOMFORESTS_NODE_H -#define LIBLEARNING_RANDOMFORESTS_NODE_H +// Modifications from original library: +// * changed inclusion protection tag +// * moved to namespace CGAL::internal:: +// * fix computation of node_dist[label] so that results are always <= 1.0 + +#ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFORESTS_NODE_H +#define CGAL_INTERNAL_LIBLEARNING_RANDOMFORESTS_NODE_H #include "../dataview.h" #include "common-libraries.hpp" #include @@ -34,6 +39,8 @@ #include #endif +namespace CGAL { namespace internal { + namespace liblearning { namespace RandomForest { @@ -249,4 +256,7 @@ public: } } + +}} // namespace CGAL::internal:: + #endif diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp index 1c76b57c91b..6c426f75141 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/tree.hpp @@ -24,12 +24,18 @@ // // Author(s) : Stefan Walk -#ifndef LIBLEARNING_RANDOMFOREST_TREE_H -#define LIBLEARNING_RANDOMFOREST_TREE_H +// Modifications from original library: +// * changed inclusion protection tag +// * moved to namespace CGAL::internal:: + +#ifndef CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_TREE_H +#define CGAL_INTERNAL_LIBLEARNING_RANDOMFOREST_TREE_H #include "../dataview.h" #include "common-libraries.hpp" #include +namespace CGAL { namespace internal { + namespace liblearning { namespace RandomForest { @@ -133,4 +139,7 @@ public: } } + +}} // namespace CGAL::internal:: + #endif From 8c725b75a90baf7dbf1ad1e3cd997f41e87ca693 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 22 Dec 2017 13:55:37 +0100 Subject: [PATCH 50/70] Fix CMakeLists: make components of Boost needed for classif optional --- Classification/examples/Classification/CMakeLists.txt | 5 ++--- Classification/test/Classification/CMakeLists.txt | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 86b9b15692a..eb11ede0e65 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -19,7 +19,7 @@ include( ${CGAL_USE_FILE} ) # Boost and its components -find_package( Boost REQUIRED COMPONENTS serialization iostreams) +find_package( Boost REQUIRED OPTIONAL_COMPONENTS serialization iostreams) if ( NOT Boost_FOUND ) message(STATUS "This project requires the Boost library, and will not be compiled.") @@ -56,13 +56,12 @@ set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) set(classification_linked_libraries) set(classification_compile_definitions) -find_package(Boost COMPONENTS serialization iostreams) if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) set(classification_linked_libraries ${classification_linked_libraries} ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) else() - message(STATUS "ERROR: Boost Serialization or IO Streams not found.") + message(STATUS "NOTICE: Boost Serialization or IO Streams not found, no example will be compiled.") exit() endif() diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index 7d69f5960e8..0f8877d4536 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -21,7 +21,7 @@ include( ${CGAL_USE_FILE} ) # Boost and its components -find_package( Boost REQUIRED ) +find_package( Boost REQUIRED OPTIONAL_COMPONENTS serialization iostreams) # Use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) @@ -59,13 +59,12 @@ set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) # Libraries and flags set(classification_linked_libraries) -find_package(Boost COMPONENTS serialization iostreams) if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) set(classification_linked_libraries ${classification_linked_libraries} ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) else() - message(STATUS "ERROR: Boost Serialization or IO Streams not found.") + message(STATUS "NOTICE: Boost Serialization or IO Streams not found, no test will be compiled.") exit() endif() From fc3cf7a27f07f0b3ef1a0d49f47fd942c31d0713 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 3 Jan 2018 10:21:19 +0100 Subject: [PATCH 51/70] Document MIT license and IO Stream's GZIP dependency --- Classification/doc/Classification/Classification.txt | 10 +++++----- .../Classification/ETHZ_random_forest_classifier.h | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Classification/doc/Classification/Classification.txt b/Classification/doc/Classification/Classification.txt index bc49f0dd34b..1295e5bf371 100644 --- a/Classification/doc/Classification/Classification.txt +++ b/Classification/doc/Classification/Classification.txt @@ -10,7 +10,7 @@ This component implements the algorithm described in \cgalCite{cgal:lm-clscm-12} \note This component depends on the Boost libraries [Serialization](http://www.boost.org/libs/serialization) and -[IO Streams](http://www.boost.org/libs/iostreams). +[IO Streams](http://www.boost.org/libs/iostreams) (compiled with the GZIP dependency). \section Classification_Organization Package Organization @@ -205,10 +205,10 @@ Example of classification on a point set with medium noise and outliers (left: i \cgal provides [ETHZ_random_forest_classifier](@ref CGAL::Classification::ETHZ_random_forest_classifier), a classifier based on the Random Forest Template Library developed by Stefan Walk at ETH Zurich \cgalCite{cgal:w-erftl-14} (the library is -included with the \cgal release, the user does not have to install -anything more). This classifier uses a ground truth training set to -construct several decision trees that are then used to assign a label -to each input item. +distributed under the MIT license and is included with the \cgal release, +the user does not have to install anything more). This classifier uses +a ground truth training set to construct several decision trees that +are then used to assign a label to each input item. This classifier cannot be set up by hand and requires a ground truth training set. The training algorithm is significantly faster but diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 365d5e93398..dc9d1d929c3 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -48,6 +48,8 @@ namespace Classification { \brief %Classifier based on the ETH Zurich version of random forest algorithm \cgalCite{cgal:w-erftl-14}. + \note This classifier is distributed under the MIT license. + \cgalModels `CGAL::Classification::Classifier` */ class ETHZ_random_forest_classifier From 0273ee4db30e8ff81a5666742dcd66bd07af7b73 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 3 Jan 2018 10:47:51 +0100 Subject: [PATCH 52/70] Acknowledge that this package uses two licenses, and fix the script --- Classification/package_info/Classification/license.txt | 1 + Scripts/developer_scripts/detect_packages_licenses | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Classification/package_info/Classification/license.txt b/Classification/package_info/Classification/license.txt index 8bb8efcb72b..d4a3c2cbe53 100644 --- a/Classification/package_info/Classification/license.txt +++ b/Classification/package_info/Classification/license.txt @@ -1 +1,2 @@ GPL (v3 or later) +MIT/X11 (BSD like) diff --git a/Scripts/developer_scripts/detect_packages_licenses b/Scripts/developer_scripts/detect_packages_licenses index 753059e6f38..a5cd34f30b3 100755 --- a/Scripts/developer_scripts/detect_packages_licenses +++ b/Scripts/developer_scripts/detect_packages_licenses @@ -15,8 +15,8 @@ for p in ^*build*(/); do elif [ -z "`echo $l | grep -Ev '^L?GPL \(v3 or later\) *$'`" ]; then echo 'GPL (v3 or later)' > "$licFile" else - echo "MULTIPLE!" > "$licFile"; - echo $l >> "$licFile" +# echo "MULTIPLE!" > "$licFile"; + echo $l > "$licFile" fi fi done From 59780674e7c3efd9057ec42cab846af0579b9f3f Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 4 Jan 2018 08:47:54 +0100 Subject: [PATCH 53/70] Fix Boost mixed-up required / optional_components --- .../examples/Classification/CMakeLists.txt | 4 +++- .../test/Classification/CMakeLists.txt | 17 ++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index eb11ede0e65..773dc85b31e 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -19,13 +19,15 @@ include( ${CGAL_USE_FILE} ) # Boost and its components -find_package( Boost REQUIRED OPTIONAL_COMPONENTS serialization iostreams) +find_package( Boost REQUIRED ) if ( NOT Boost_FOUND ) message(STATUS "This project requires the Boost library, and will not be compiled.") return() endif() +find_package( Boost OPTIONAL_COMPONENTS serialization iostreams) + find_package( TBB ) find_package(OpenCV QUIET) diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index 0f8877d4536..ba8fadc149d 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -21,7 +21,14 @@ include( ${CGAL_USE_FILE} ) # Boost and its components -find_package( Boost REQUIRED OPTIONAL_COMPONENTS serialization iostreams) +find_package( Boost REQUIRED ) + +if ( NOT Boost_FOUND ) + message(STATUS "This project requires the Boost library, and will not be compiled.") + return() +endif() + +find_package( Boost OPTIONAL_COMPONENTS serialization iostreams) # Use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) @@ -29,14 +36,6 @@ if (EIGEN3_FOUND) include( ${EIGEN3_USE_FILE} ) endif() -if ( NOT Boost_FOUND ) - - message(STATUS "This project requires the Boost library, and will not be compiled.") - - return() - -endif() - find_package( TBB ) # include for local directory From 945a6f31725290d4beda1c8d879801ff4c8aeeb0 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 5 Jan 2018 09:26:40 +0100 Subject: [PATCH 54/70] Make TBB optional in CMakeLists --- Classification/examples/Classification/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 773dc85b31e..0fbd0007ddd 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -28,7 +28,7 @@ endif() find_package( Boost OPTIONAL_COMPONENTS serialization iostreams) -find_package( TBB ) +find_package(TBB QUIET) find_package(OpenCV QUIET) From 739ccc00bb2d80f3c7ac8804bd996b8c90ba7e9e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 5 Jan 2018 09:26:49 +0100 Subject: [PATCH 55/70] Make Boost IO Streams/serialization optional in demo --- .../demo/Polyhedron/Plugins/Classification/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index c2834495991..be06f1ac02b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -8,7 +8,7 @@ if(EIGEN3_FOUND) set(classification_linked_libraries) set(classification_compile_definitions) - find_package(Boost COMPONENTS serialization iostreams) + find_package(Boost OPTIONAL_COMPONENTS serialization iostreams) if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) set(classification_linked_libraries ${classification_linked_libraries} ${Boost_SERIALIZATION_LIBRARY} From d9ee6920590ec00bc0b12c868f656f525de482d0 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 8 Jan 2018 09:49:53 +0100 Subject: [PATCH 56/70] Fix CMakeLists (exit() -> return()) --- Classification/examples/Classification/CMakeLists.txt | 2 +- Classification/test/Classification/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 0fbd0007ddd..4c73e0f65a5 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -64,7 +64,7 @@ if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) ${Boost_IOSTREAMS_LIBRARY}) else() message(STATUS "NOTICE: Boost Serialization or IO Streams not found, no example will be compiled.") - exit() + return() endif() find_package(OpenCV QUIET) diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index ba8fadc149d..a4c55197b3c 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -64,7 +64,7 @@ if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) ${Boost_IOSTREAMS_LIBRARY}) else() message(STATUS "NOTICE: Boost Serialization or IO Streams not found, no test will be compiled.") - exit() + return() endif() create_single_source_cgal_program( "test_classification_point_set.cpp" CXX_FEATURES ${needed_cxx_features} ) From 2d30b545d13dacd5877b35d41d3de4ea6c8dd4e1 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 8 Jan 2018 09:58:55 +0100 Subject: [PATCH 57/70] Fix warning: unused variable --- .../Classification/example_ethz_random_forest.cpp | 12 +----------- .../Classification/example_opencv_random_forest.cpp | 12 +----------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/Classification/examples/Classification/example_ethz_random_forest.cpp b/Classification/examples/Classification/example_ethz_random_forest.cpp index 423056b12e8..961c63b41ac 100644 --- a/Classification/examples/Classification/example_ethz_random_forest.cpp +++ b/Classification/examples/Classification/example_ethz_random_forest.cpp @@ -32,19 +32,9 @@ typedef Classification::Point_set_feature_generator int main (int argc, char** argv) { std::string filename = "data/b9_training.ply"; - bool use_opencv = false; if (argc > 1) - { - if (std::string(argv[1]) == "-cv") - { - use_opencv = true; - if (argc > 2) - filename = argv[2]; - } - else - filename = argv[1]; - } + filename = argv[1]; std::ifstream in (filename.c_str(), std::ios::binary); Point_set pts; diff --git a/Classification/examples/Classification/example_opencv_random_forest.cpp b/Classification/examples/Classification/example_opencv_random_forest.cpp index f14eb20b303..3f8971389e3 100644 --- a/Classification/examples/Classification/example_opencv_random_forest.cpp +++ b/Classification/examples/Classification/example_opencv_random_forest.cpp @@ -32,19 +32,9 @@ typedef Classification::Point_set_feature_generator int main (int argc, char** argv) { std::string filename = "data/b9_training.ply"; - bool use_opencv = false; if (argc > 1) - { - if (std::string(argv[1]) == "-cv") - { - use_opencv = true; - if (argc > 2) - filename = argv[2]; - } - else - filename = argv[1]; - } + filename = argv[1]; std::ifstream in (filename.c_str(), std::ios::binary); Point_set pts; From 9f4aaddd46145140219914cf8e560e7d80ff47aa Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 8 Jan 2018 15:27:15 +0100 Subject: [PATCH 58/70] Fix CMakeLists: move all classification plugin lines inside Boost condition --- .../demo/Polyhedron/Plugins/Classification/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index be06f1ac02b..9bb823f16d8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -2,14 +2,14 @@ include( polyhedron_demo_macros ) if(EIGEN3_FOUND) - qt5_wrap_ui( classificationUI_FILES Classification_widget.ui) - polyhedron_demo_plugin(classification_plugin Classification_plugin Point_set_item_classification ${classificationUI_FILES}) - set(classification_linked_libraries) set(classification_compile_definitions) find_package(Boost OPTIONAL_COMPONENTS serialization iostreams) if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) + qt5_wrap_ui( classificationUI_FILES Classification_widget.ui) + polyhedron_demo_plugin(classification_plugin Classification_plugin Point_set_item_classification ${classificationUI_FILES}) + set(classification_linked_libraries ${classification_linked_libraries} ${Boost_SERIALIZATION_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) From 0c2aa33cc1b6c18781afcad2b303fb0dc7b475ba Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 9 Jan 2018 10:36:16 +0100 Subject: [PATCH 59/70] Fix CMakeLists management of CXX required features --- Classification/examples/Classification/CMakeLists.txt | 10 ++++++---- Classification/test/Classification/CMakeLists.txt | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 4c73e0f65a5..503ce81ef92 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -84,10 +84,12 @@ endif() # Creating targets with correct libraries and flags foreach(target ${targets}) create_single_source_cgal_program( "${target}.cpp" CXX_FEATURES ${needed_cxx_features} ) - target_link_libraries(${target} PUBLIC ${classification_linked_libraries}) - target_compile_definitions(${target} PUBLIC ${classification_compile_definitions}) - if(TBB_FOUND AND TARGET ${target}) - CGAL_target_use_TBB(${target}) + if(TARGET ${target}) + target_link_libraries(${target} PUBLIC ${classification_linked_libraries}) + target_compile_definitions(${target} PUBLIC ${classification_compile_definitions}) + if(TBB_FOUND) + CGAL_target_use_TBB(${target}) + endif() endif() endforeach() diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index a4c55197b3c..57132fcdcb9 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -68,8 +68,10 @@ else() endif() create_single_source_cgal_program( "test_classification_point_set.cpp" CXX_FEATURES ${needed_cxx_features} ) -target_link_libraries(test_classification_point_set PUBLIC ${classification_linked_libraries}) -if(TBB_FOUND) - CGAL_target_use_TBB( test_classification_point_set ) +if(TARGET test_classification_point_set) + target_link_libraries(test_classification_point_set PUBLIC ${classification_linked_libraries}) + if (TBB_FOUND) + CGAL_target_use_TBB( test_classification_point_set ) + endif() endif() From 86090bf44726e18e530ea35eaf7ed3c8dd20d181 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 10 Jan 2018 12:22:04 +0100 Subject: [PATCH 60/70] Adapt CMakeLists.txt to the Win32 specific Boost/ZLIB dependencies --- .../examples/Classification/CMakeLists.txt | 17 ++++++++++++++++- .../test/Classification/CMakeLists.txt | 14 ++++++++++++++ .../Plugins/Classification/CMakeLists.txt | 13 +++++++++++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 503ce81ef92..60d61198e11 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -26,7 +26,11 @@ if ( NOT Boost_FOUND ) return() endif() -find_package( Boost OPTIONAL_COMPONENTS serialization iostreams) +find_package( Boost OPTIONAL_COMPONENTS serialization iostreams ) + +if( WIN32 ) + find_package( Boost OPTIONAL_COMPONENTS zlib) +endif() find_package(TBB QUIET) @@ -58,6 +62,7 @@ set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) set(classification_linked_libraries) set(classification_compile_definitions) + if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) set(classification_linked_libraries ${classification_linked_libraries} ${Boost_SERIALIZATION_LIBRARY} @@ -67,6 +72,16 @@ else() return() endif() +if( WIN23 ) + if (Boost_ZLIB_FOUND) + set(classification_linked_libraries ${classification_linked_libraries} + ${Boost_ZLIB_LIBRARY}) + else() + message(STATUS "NOTICE: Boost ZLIB not found, no example will be compiled.") + return() + endif() +endif() + find_package(OpenCV QUIET) if (OpenCV_FOUND) message(STATUS "Found OpenCV ${OpenCV_VERSION}") diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index 57132fcdcb9..b40652df907 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -30,6 +30,10 @@ endif() find_package( Boost OPTIONAL_COMPONENTS serialization iostreams) +if( WIN32 ) + find_package( Boost OPTIONAL_COMPONENTS zlib) +endif() + # Use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) if (EIGEN3_FOUND) @@ -67,6 +71,16 @@ else() return() endif() +if( WIN23 ) + if (Boost_ZLIB_FOUND) + set(classification_linked_libraries ${classification_linked_libraries} + ${Boost_ZLIB_LIBRARY}) + else() + message(STATUS "NOTICE: Boost ZLIB not found, no example will be compiled.") + return() + endif() +endif() + create_single_source_cgal_program( "test_classification_point_set.cpp" CXX_FEATURES ${needed_cxx_features} ) if(TARGET test_classification_point_set) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index 9bb823f16d8..4c2473e126f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -6,7 +6,16 @@ if(EIGEN3_FOUND) set(classification_compile_definitions) find_package(Boost OPTIONAL_COMPONENTS serialization iostreams) - if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND) + + if( WIN32 ) + find_package( Boost OPTIONAL_COMPONENTS zlib) + if( Boost_ZLIB_FOUND ) + set(classification_linked_libraries ${classification_linked_libraries} + ${Boost_ZLIB_LIBRARY}) + endif() + endif() + + if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND AND (NOT WIN23 OR Boost_ZLIB_FOUND)) qt5_wrap_ui( classificationUI_FILES Classification_widget.ui) polyhedron_demo_plugin(classification_plugin Classification_plugin Point_set_item_classification ${classificationUI_FILES}) @@ -30,7 +39,7 @@ if(EIGEN3_FOUND) scene_polylines_item scene_polygon_soup_item scene_color_ramp ${classification_linked_libraries}) target_compile_definitions(classification_plugin PUBLIC ${classification_compile_definitions}) else() - message(STATUS "NOTICE: Boost Serialization or IO Streams not found. Classification plugin won't be available.") + message(STATUS "NOTICE: Boost Serialization or IO Streams or ZLIB not found. Classification plugin won't be available.") endif() From 323281358b84b75f4af9d0f8ff708829d74755e9 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 11 Jan 2018 11:26:26 +0100 Subject: [PATCH 61/70] Disable Windows warnings from auxiliary library --- .../Classification/ETHZ_random_forest_classifier.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index dc9d1d929c3..135ffb6332c 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -30,9 +30,21 @@ #define VERBOSE_TREE_PROGRESS 1 #endif +// Disable warnings from auxiliary library +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4141) +# pragma warning(disable:4244) +# pragma warning(disable:4267) +#endif + #include #include +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + #include #include #include From 3d17f81308d5a804297a7ca4e3a19bf0f66a0217 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 15 Jan 2018 11:00:20 +0100 Subject: [PATCH 62/70] Fix bug in CMakeLists: WIN23 -> WIN32 --- Classification/examples/Classification/CMakeLists.txt | 2 +- Classification/test/Classification/CMakeLists.txt | 2 +- .../demo/Polyhedron/Plugins/Classification/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 60d61198e11..39a91b5a0da 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -72,7 +72,7 @@ else() return() endif() -if( WIN23 ) +if( WIN32 ) if (Boost_ZLIB_FOUND) set(classification_linked_libraries ${classification_linked_libraries} ${Boost_ZLIB_LIBRARY}) diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index b40652df907..09659bb2837 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -71,7 +71,7 @@ else() return() endif() -if( WIN23 ) +if( WIN32 ) if (Boost_ZLIB_FOUND) set(classification_linked_libraries ${classification_linked_libraries} ${Boost_ZLIB_LIBRARY}) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index 4c2473e126f..a57a1f32a11 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -15,7 +15,7 @@ if(EIGEN3_FOUND) endif() endif() - if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND AND (NOT WIN23 OR Boost_ZLIB_FOUND)) + if (Boost_SERIALIZATION_FOUND AND Boost_IOSTREAMS_FOUND AND (NOT WIN32 OR Boost_ZLIB_FOUND)) qt5_wrap_ui( classificationUI_FILES Classification_widget.ui) polyhedron_demo_plugin(classification_plugin Classification_plugin Point_set_item_classification ${classificationUI_FILES}) From 3db48cd98e8253ae93b8f792c225691678c77d2f Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 16 Jan 2018 08:54:12 +0100 Subject: [PATCH 63/70] Fix windows warning --- .../Classification/internal/auxiliary/random-forest/forest.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp index a419baf7953..4d22c2bb36b 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/forest.hpp @@ -133,7 +133,7 @@ public: } int evaluate(FeatureType const* sample, float* results) { // initialize output probabilities to 0 - std::fill_n(results, params.n_classes, 0); + std::fill_n(results, params.n_classes, 0.0f); // accumulate votes of the trees for (size_t i_tree = 0; i_tree < trees.size(); ++i_tree) { float const* tree_result = trees[i_tree].evaluate(sample); From 0922ccaefb22bdf65b79e836870a23fe59370902 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 16 Jan 2018 08:54:44 +0000 Subject: [PATCH 64/70] fix more Windows warnings --- .../Classification/ETHZ_random_forest_classifier.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h index 135ffb6332c..359961b32b8 100644 --- a/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h +++ b/Classification/include/CGAL/Classification/ETHZ_random_forest_classifier.h @@ -36,20 +36,22 @@ # pragma warning(disable:4141) # pragma warning(disable:4244) # pragma warning(disable:4267) +# pragma warning(disable:4275) +# pragma warning(disable:4251) #endif #include #include -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - #include #include #include #include +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + namespace CGAL { From effca64dd41250d4905d68b6113d1cd42fe3ec32 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 17 Jan 2018 07:31:34 +0000 Subject: [PATCH 65/70] Cast to avoid warning --- .../internal/auxiliary/random-forest/node-gini.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp index 931a95bbb3a..1b3c6ec89c8 100644 --- a/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp +++ b/Classification/include/CGAL/Classification/internal/auxiliary/random-forest/node-gini.hpp @@ -98,7 +98,7 @@ public: best_thresh = fraction * data_points[i_point-1].first + (1-fraction) * data_points[i_point].first; } } - return std::make_pair(best_thresh, best_loss); + return std::make_pair(best_thresh, float(best_loss)); } template From 8d15f77479eb60b7c6bc630e01b303d0cbb71462 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 17 Jan 2018 08:54:06 +0000 Subject: [PATCH 66/70] Workaround for silencing a cmake warning for older versions --- Classification/examples/Classification/CMakeLists.txt | 3 +++ Classification/test/Classification/CMakeLists.txt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index 39a91b5a0da..b991947625a 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -29,6 +29,9 @@ endif() find_package( Boost OPTIONAL_COMPONENTS serialization iostreams ) if( WIN32 ) +# to avoid a warning with old cmake + set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp") + set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp") find_package( Boost OPTIONAL_COMPONENTS zlib) endif() diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index 09659bb2837..411b07dce92 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -31,6 +31,9 @@ endif() find_package( Boost OPTIONAL_COMPONENTS serialization iostreams) if( WIN32 ) +# to avoid a warning with old cmake + set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp") + set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp") find_package( Boost OPTIONAL_COMPONENTS zlib) endif() From 5d1aa4de878e3a9d8fd2ea94e836afa44fcb2565 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Fri, 19 Jan 2018 14:13:32 +0100 Subject: [PATCH 67/70] Fix conversion warning --- .../Plugins/Classification/Point_set_item_classification.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a7ea0c3dc2e..638879548a9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -172,7 +172,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n Label_handle new_label; std::map::iterator found - = label_names.find (i); + = label_names.find (int(i)); if (found != label_names.end()) new_label = m_labels.add(found->second.c_str()); else From 6269309d86aaabd28a4c5ae01d4079781c5d52e6 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 23 Jan 2018 11:09:52 +0100 Subject: [PATCH 68/70] Use CGAL include for boost counting/transform iterators everywhere --- .../include/CGAL/Algebraic_kernel_d/Curve_pair_analysis_2.h | 2 +- Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/shear.h | 2 +- BGL/examples/BGL_LCC/transform_iterator_lcc.cpp | 2 +- BGL/examples/BGL_polyhedron_3/transform_iterator.cpp | 2 +- BGL/include/CGAL/boost/graph/Face_filtered_graph.h | 2 +- .../CGAL/boost/graph/Graph_with_descriptor_with_graph.h | 2 +- BGL/include/CGAL/boost/graph/graph_traits_OpenMesh.h | 2 +- BGL/include/CGAL/boost/graph/graph_traits_Seam_mesh.h | 2 +- Bounding_volumes/include/CGAL/Min_annulus_d.h | 2 +- .../include/CGAL/Classification/Point_set_neighborhood.h | 2 +- HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS.h | 2 +- .../archive/include/CGAL/Kinetic/Active_objects_set.h | 2 +- .../include/CGAL/Kinetic/Active_objects_vector.h | 2 +- Mesh_2/include/CGAL/Mesh_2/Clusters.h | 2 +- Mesh_2/include/CGAL/Mesh_2/Refine_edges.h | 2 +- Mesh_2/include/CGAL/Mesh_2/Refine_faces.h | 2 +- Mesh_3/benchmark/Mesh_3/StdAfx.h | 4 ++-- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Triangulation_sizing_field.h | 2 +- Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h | 2 +- Mesh_3/include/CGAL/Polyhedral_complex_mesh_domain_3.h | 2 +- Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h | 2 +- NewKernel_d/include/CGAL/NewKernel_d/Types/Hyperplane.h | 2 +- Number_types/include/CGAL/Counted_number.h | 2 +- Number_types/include/CGAL/Lazy_exact_nt.h | 2 +- .../include/CGAL/Optimal_transportation_reconstruction_2.h | 2 +- .../include/CGAL/Shape_detection_3/Region_growing.h | 4 ++-- .../benchmark/Polygon_mesh_processing/polygon_mesh_slicer.cpp | 2 +- .../internal/Hole_filling/Triangulate_hole_polyline.h | 2 +- .../include/CGAL/Polygon_mesh_processing/intersection.h | 2 +- .../Polyhedron/Plugins/Convex_hull/Convex_hull_plugin.cpp | 2 +- .../Polyhedron/Plugins/PMP/Hole_filling_polyline_plugin.cpp | 2 +- .../Polyhedron/Plugins/PMP/Point_inside_polyhedron_plugin.cpp | 2 +- Polynomial/include/CGAL/Polynomial.h | 2 +- Polynomial/include/CGAL/Polynomial_traits_d.h | 2 +- .../demo/Principal_component_analysis/types.h | 2 +- .../examples/QP_solver/solve_convex_hull_containment_lp2.h | 2 +- .../examples/QP_solver/solve_convex_hull_containment_lp3.h | 2 +- QP_solver/include/CGAL/QP_models.h | 2 +- QP_solver/include/CGAL/QP_solution.h | 2 +- QP_solver/include/CGAL/QP_solver/QP_solver.h | 2 +- QP_solver/test/QP_solver/master_mps_to_derivatives.cpp | 2 +- .../include/CGAL/Segment_Delaunay_graph_2.h | 2 +- Spatial_searching/include/CGAL/internal/K_neighbor_search.h | 2 +- Spatial_searching/test/Spatial_searching/Point_with_info.h | 2 +- .../include/CGAL/boost/graph/graph_traits_Surface_mesh.h | 2 +- .../Surface_mesh_skeletonization/solver_benchmark.cpp | 2 +- .../include/CGAL/Mean_curvature_flow_skeletonization.h | 2 +- .../CGAL/Surface_mesher/Intersection_data_structure_3.h | 2 +- Triangulation/include/CGAL/Delaunay_triangulation.h | 2 +- .../include/CGAL/Regular_triangulation_traits_adapter.h | 2 +- Triangulation/include/CGAL/Triangulation.h | 2 +- .../benchmark/Triangulation_2/CDT_with_intersection_2.cpp | 2 +- .../Triangulation_2/info_insert_with_transform_iterator_2.cpp | 2 +- Triangulation_2/include/CGAL/Triangulation_2.h | 2 +- .../Triangulation_3/info_insert_with_transform_iterator.cpp | 2 +- Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h | 2 +- Voronoi_diagram_2/include/CGAL/Voronoi_diagram_2.h | 2 +- 60 files changed, 62 insertions(+), 62 deletions(-) diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_pair_analysis_2.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_pair_analysis_2.h index b0a62fa534a..a7ec12aa317 100644 --- a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_pair_analysis_2.h +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_pair_analysis_2.h @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/shear.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/shear.h index 887f56d1577..4661ee97fa6 100644 --- a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/shear.h +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/shear.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include namespace CGAL { diff --git a/BGL/examples/BGL_LCC/transform_iterator_lcc.cpp b/BGL/examples/BGL_LCC/transform_iterator_lcc.cpp index e8c75364dc3..1268d4d9d77 100644 --- a/BGL/examples/BGL_LCC/transform_iterator_lcc.cpp +++ b/BGL/examples/BGL_LCC/transform_iterator_lcc.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include typedef CGAL::Simple_cartesian Kernel; diff --git a/BGL/examples/BGL_polyhedron_3/transform_iterator.cpp b/BGL/examples/BGL_polyhedron_3/transform_iterator.cpp index a990901c61b..c03df6f0b7f 100644 --- a/BGL/examples/BGL_polyhedron_3/transform_iterator.cpp +++ b/BGL/examples/BGL_polyhedron_3/transform_iterator.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include diff --git a/BGL/include/CGAL/boost/graph/Face_filtered_graph.h b/BGL/include/CGAL/boost/graph/Face_filtered_graph.h index e18921b5ef9..be5dfa39830 100644 --- a/BGL/include/CGAL/boost/graph/Face_filtered_graph.h +++ b/BGL/include/CGAL/boost/graph/Face_filtered_graph.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/BGL/include/CGAL/boost/graph/Graph_with_descriptor_with_graph.h b/BGL/include/CGAL/boost/graph/Graph_with_descriptor_with_graph.h index ab5f11f7bb8..ce92302b96b 100644 --- a/BGL/include/CGAL/boost/graph/Graph_with_descriptor_with_graph.h +++ b/BGL/include/CGAL/boost/graph/Graph_with_descriptor_with_graph.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include diff --git a/BGL/include/CGAL/boost/graph/graph_traits_OpenMesh.h b/BGL/include/CGAL/boost/graph/graph_traits_OpenMesh.h index e291c006f1a..2f363ebb3d5 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_OpenMesh.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_OpenMesh.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/BGL/include/CGAL/boost/graph/graph_traits_Seam_mesh.h b/BGL/include/CGAL/boost/graph/graph_traits_Seam_mesh.h index bbde0c6bcec..a293f534152 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_Seam_mesh.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_Seam_mesh.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/Bounding_volumes/include/CGAL/Min_annulus_d.h b/Bounding_volumes/include/CGAL/Min_annulus_d.h index 5fb5c803afe..f1f349b64fe 100644 --- a/Bounding_volumes/include/CGAL/Min_annulus_d.h +++ b/Bounding_volumes/include/CGAL/Min_annulus_d.h @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include // here is how it works. We have d+2 variables: diff --git a/Classification/include/CGAL/Classification/Point_set_neighborhood.h b/Classification/include/CGAL/Classification/Point_set_neighborhood.h index 29765db9be5..79977a3eb43 100644 --- a/Classification/include/CGAL/Classification/Point_set_neighborhood.h +++ b/Classification/include/CGAL/Classification/Point_set_neighborhood.h @@ -25,7 +25,7 @@ #include -#include +#include #include #include diff --git a/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS.h b/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS.h index 6935008ae26..53304971c7b 100644 --- a/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS.h +++ b/HalfedgeDS/include/CGAL/boost/graph/graph_traits_HalfedgeDS.h @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include diff --git a/Kinetic_data_structures/archive/include/CGAL/Kinetic/Active_objects_set.h b/Kinetic_data_structures/archive/include/CGAL/Kinetic/Active_objects_set.h index a539a72435a..f86b872e0a2 100644 --- a/Kinetic_data_structures/archive/include/CGAL/Kinetic/Active_objects_set.h +++ b/Kinetic_data_structures/archive/include/CGAL/Kinetic/Active_objects_set.h @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include namespace CGAL { namespace Kinetic {; diff --git a/Kinetic_data_structures/include/CGAL/Kinetic/Active_objects_vector.h b/Kinetic_data_structures/include/CGAL/Kinetic/Active_objects_vector.h index 22e4a012a16..f51d72495c0 100644 --- a/Kinetic_data_structures/include/CGAL/Kinetic/Active_objects_vector.h +++ b/Kinetic_data_structures/include/CGAL/Kinetic/Active_objects_vector.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include #if defined(BOOST_MSVC) # pragma warning(push) diff --git a/Mesh_2/include/CGAL/Mesh_2/Clusters.h b/Mesh_2/include/CGAL/Mesh_2/Clusters.h index d351d67fc34..9bf140dc531 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Clusters.h +++ b/Mesh_2/include/CGAL/Mesh_2/Clusters.h @@ -30,7 +30,7 @@ #include #include -#include +#include namespace CGAL { diff --git a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h index 070de821ae9..8bdddb618e8 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h +++ b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include namespace CGAL { diff --git a/Mesh_2/include/CGAL/Mesh_2/Refine_faces.h b/Mesh_2/include/CGAL/Mesh_2/Refine_faces.h index b687881a7f9..a1da7301e30 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Refine_faces.h +++ b/Mesh_2/include/CGAL/Mesh_2/Refine_faces.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include diff --git a/Mesh_3/benchmark/Mesh_3/StdAfx.h b/Mesh_3/benchmark/Mesh_3/StdAfx.h index 0aa9e0bd9a7..e4e8a7a319d 100644 --- a/Mesh_3/benchmark/Mesh_3/StdAfx.h +++ b/Mesh_3/benchmark/Mesh_3/StdAfx.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -282,4 +282,4 @@ #include #include */ -#endif //STDAFX_H \ No newline at end of file +#endif //STDAFX_H diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index 68dfd5ddb8f..ebcbcf146da 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h index 044eaf0433c..b4d38434920 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h +++ b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h @@ -78,7 +78,7 @@ namespace internal { #include #include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h index 4732593f45f..d794b3f6806 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h +++ b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h @@ -39,7 +39,7 @@ #include #include // std::setprecision #include // std::cerr/cout -#include +#include #include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Triangulation_sizing_field.h b/Mesh_3/include/CGAL/Mesh_3/Triangulation_sizing_field.h index ab65987d156..91fff95bb75 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Triangulation_sizing_field.h +++ b/Mesh_3/include/CGAL/Mesh_3/Triangulation_sizing_field.h @@ -35,7 +35,7 @@ #include #include -#include +#include namespace CGAL { diff --git a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h b/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h index b39d377682d..21a5d5026e7 100644 --- a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h +++ b/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Mesh_3/include/CGAL/Polyhedral_complex_mesh_domain_3.h b/Mesh_3/include/CGAL/Polyhedral_complex_mesh_domain_3.h index 146a927967f..a6702b11db1 100644 --- a/Mesh_3/include/CGAL/Polyhedral_complex_mesh_domain_3.h +++ b/Mesh_3/include/CGAL/Polyhedral_complex_mesh_domain_3.h @@ -48,7 +48,7 @@ #include #include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h index 9d2e05f04c9..719045910dd 100644 --- a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h +++ b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h @@ -52,7 +52,7 @@ #include #include -#include +#include #include #include diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Hyperplane.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Hyperplane.h index ac60adf362d..1a32b080bed 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Hyperplane.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Hyperplane.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include namespace CGAL { template class Hyperplane { diff --git a/Number_types/include/CGAL/Counted_number.h b/Number_types/include/CGAL/Counted_number.h index 194d0079540..22c9b009400 100644 --- a/Number_types/include/CGAL/Counted_number.h +++ b/Number_types/include/CGAL/Counted_number.h @@ -29,7 +29,7 @@ #include #include -#include // for Root_of_selector +#include // for Root_of_selector #include namespace CGAL { diff --git a/Number_types/include/CGAL/Lazy_exact_nt.h b/Number_types/include/CGAL/Lazy_exact_nt.h index 7e4c86363f9..a69313bee8e 100644 --- a/Number_types/include/CGAL/Lazy_exact_nt.h +++ b/Number_types/include/CGAL/Lazy_exact_nt.h @@ -30,7 +30,7 @@ #include #include -#include // for Root_of functor +#include // for Root_of functor #include #include #include diff --git a/Optimal_transportation_reconstruction_2/include/CGAL/Optimal_transportation_reconstruction_2.h b/Optimal_transportation_reconstruction_2/include/CGAL/Optimal_transportation_reconstruction_2.h index c5b9d304e32..d522c9ffa8a 100644 --- a/Optimal_transportation_reconstruction_2/include/CGAL/Optimal_transportation_reconstruction_2.h +++ b/Optimal_transportation_reconstruction_2/include/CGAL/Optimal_transportation_reconstruction_2.h @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include namespace CGAL { diff --git a/Point_set_shape_detection_3/include/CGAL/Shape_detection_3/Region_growing.h b/Point_set_shape_detection_3/include/CGAL/Shape_detection_3/Region_growing.h index 885c1d0ebd1..f4ebad8a741 100644 --- a/Point_set_shape_detection_3/include/CGAL/Shape_detection_3/Region_growing.h +++ b/Point_set_shape_detection_3/include/CGAL/Shape_detection_3/Region_growing.h @@ -33,8 +33,8 @@ #include #include -#include -#include +#include +#include namespace CGAL { namespace Shape_detection_3 { diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/polygon_mesh_slicer.cpp b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/polygon_mesh_slicer.cpp index 4abd5c247a7..092f2bec741 100644 --- a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/polygon_mesh_slicer.cpp +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/polygon_mesh_slicer.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Hole_filling/Triangulate_hole_polyline.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Hole_filling/Triangulate_hole_polyline.h index 630702b8651..e3c16de3575 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Hole_filling/Triangulate_hole_polyline.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Hole_filling/Triangulate_hole_polyline.h @@ -37,7 +37,7 @@ #include #include -#include +#include #include namespace CGAL { diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h index 9e43ceffc82..b7045a0b604 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/Convex_hull_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/Convex_hull_plugin.cpp index 5d2e487337e..de075a1841c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/Convex_hull_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/Convex_hull_plugin.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include using namespace CGAL::Three; class Polyhedron_demo_convex_hull_plugin : public QObject, diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_polyline_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_polyline_plugin.cpp index 5107cca03d0..561dbeb7163 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_polyline_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_polyline_plugin.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include struct Face : public CGAL::cpp11::array diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Point_inside_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Point_inside_polyhedron_plugin.cpp index 05e42b51397..057db99a16b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Point_inside_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Point_inside_polyhedron_plugin.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include using namespace CGAL::Three; diff --git a/Polynomial/include/CGAL/Polynomial.h b/Polynomial/include/CGAL/Polynomial.h index f600d49b9d8..78f4510eec2 100644 --- a/Polynomial/include/CGAL/Polynomial.h +++ b/Polynomial/include/CGAL/Polynomial.h @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include diff --git a/Polynomial/include/CGAL/Polynomial_traits_d.h b/Polynomial/include/CGAL/Polynomial_traits_d.h index 627fc69ef59..d0a204b239f 100644 --- a/Polynomial/include/CGAL/Polynomial_traits_d.h +++ b/Polynomial/include/CGAL/Polynomial_traits_d.h @@ -43,7 +43,7 @@ #include #include -#include +#include #define CGAL_POLYNOMIAL_TRAITS_D_BASE_TYPEDEFS \ diff --git a/Principal_component_analysis/demo/Principal_component_analysis/types.h b/Principal_component_analysis/demo/Principal_component_analysis/types.h index c30211fcb8a..5fca2488f30 100644 --- a/Principal_component_analysis/demo/Principal_component_analysis/types.h +++ b/Principal_component_analysis/demo/Principal_component_analysis/types.h @@ -3,7 +3,7 @@ #include #include -#include +#include typedef CGAL::Simple_cartesian Kernel; typedef Kernel::FT FT; diff --git a/QP_solver/examples/QP_solver/solve_convex_hull_containment_lp2.h b/QP_solver/examples/QP_solver/solve_convex_hull_containment_lp2.h index bb022e19318..675af0f94b7 100644 --- a/QP_solver/examples/QP_solver/solve_convex_hull_containment_lp2.h +++ b/QP_solver/examples/QP_solver/solve_convex_hull_containment_lp2.h @@ -1,6 +1,6 @@ // example: function to check whether a point is in the convex // hull of other points; this version uses a maker -#include +#include #include #include #include diff --git a/QP_solver/examples/QP_solver/solve_convex_hull_containment_lp3.h b/QP_solver/examples/QP_solver/solve_convex_hull_containment_lp3.h index f5cf1a45a4f..98266e30dbd 100644 --- a/QP_solver/examples/QP_solver/solve_convex_hull_containment_lp3.h +++ b/QP_solver/examples/QP_solver/solve_convex_hull_containment_lp3.h @@ -1,6 +1,6 @@ // example: function to check whether a point is in the convex // hull of other points; this version uses a maker -#include +#include #include #include #include diff --git a/QP_solver/include/CGAL/QP_models.h b/QP_solver/include/CGAL/QP_models.h index 4ca5db648cc..428e2543b86 100644 --- a/QP_solver/include/CGAL/QP_models.h +++ b/QP_solver/include/CGAL/QP_models.h @@ -38,7 +38,7 @@ #include #include -#include +#include // this file defines the following models: // - Quadratic_program_from_iterators diff --git a/QP_solver/include/CGAL/QP_solution.h b/QP_solver/include/CGAL/QP_solution.h index e1ebcca0b58..109c319abe6 100644 --- a/QP_solver/include/CGAL/QP_solution.h +++ b/QP_solver/include/CGAL/QP_solution.h @@ -39,7 +39,7 @@ #include #include -#include +#include namespace CGAL { diff --git a/QP_solver/include/CGAL/QP_solver/QP_solver.h b/QP_solver/include/CGAL/QP_solver/QP_solver.h index 743ff7dbb18..f49093e4733 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_solver.h +++ b/QP_solver/include/CGAL/QP_solver/QP_solver.h @@ -48,7 +48,7 @@ #include #include -#include +#include #include #include diff --git a/QP_solver/test/QP_solver/master_mps_to_derivatives.cpp b/QP_solver/test/QP_solver/master_mps_to_derivatives.cpp index 718595f2d54..14124909a84 100644 --- a/QP_solver/test/QP_solver/master_mps_to_derivatives.cpp +++ b/QP_solver/test/QP_solver/master_mps_to_derivatives.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/Segment_Delaunay_graph_2/include/CGAL/Segment_Delaunay_graph_2.h b/Segment_Delaunay_graph_2/include/CGAL/Segment_Delaunay_graph_2.h index b4f898ef627..217f00d6491 100644 --- a/Segment_Delaunay_graph_2/include/CGAL/Segment_Delaunay_graph_2.h +++ b/Segment_Delaunay_graph_2/include/CGAL/Segment_Delaunay_graph_2.h @@ -57,7 +57,7 @@ #include #include -#include +#include /* Conventions: diff --git a/Spatial_searching/include/CGAL/internal/K_neighbor_search.h b/Spatial_searching/include/CGAL/internal/K_neighbor_search.h index 0a6593a79f6..4cbfe31707f 100644 --- a/Spatial_searching/include/CGAL/internal/K_neighbor_search.h +++ b/Spatial_searching/include/CGAL/internal/K_neighbor_search.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include namespace CGAL { namespace internal{ diff --git a/Spatial_searching/test/Spatial_searching/Point_with_info.h b/Spatial_searching/test/Spatial_searching/Point_with_info.h index 9cf9670b1aa..48557ff6cdd 100644 --- a/Spatial_searching/test/Spatial_searching/Point_with_info.h +++ b/Spatial_searching/test/Spatial_searching/Point_with_info.h @@ -1,4 +1,4 @@ -#include +#include template struct My_point_with_info diff --git a/Surface_mesh/include/CGAL/boost/graph/graph_traits_Surface_mesh.h b/Surface_mesh/include/CGAL/boost/graph/graph_traits_Surface_mesh.h index 3a5b09364a2..9f79653b7f1 100644 --- a/Surface_mesh/include/CGAL/boost/graph/graph_traits_Surface_mesh.h +++ b/Surface_mesh/include/CGAL/boost/graph/graph_traits_Surface_mesh.h @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include diff --git a/Surface_mesh_skeletonization/benchmark/Surface_mesh_skeletonization/solver_benchmark.cpp b/Surface_mesh_skeletonization/benchmark/Surface_mesh_skeletonization/solver_benchmark.cpp index a5fda169ac8..569b6a1594d 100644 --- a/Surface_mesh_skeletonization/benchmark/Surface_mesh_skeletonization/solver_benchmark.cpp +++ b/Surface_mesh_skeletonization/benchmark/Surface_mesh_skeletonization/solver_benchmark.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h b/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h index f74f8192676..ae2f5d77a0e 100644 --- a/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h +++ b/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include diff --git a/Surface_mesher/include/CGAL/Surface_mesher/Intersection_data_structure_3.h b/Surface_mesher/include/CGAL/Surface_mesher/Intersection_data_structure_3.h index 410b10e6a17..1da2b1339b4 100644 --- a/Surface_mesher/include/CGAL/Surface_mesher/Intersection_data_structure_3.h +++ b/Surface_mesher/include/CGAL/Surface_mesher/Intersection_data_structure_3.h @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include diff --git a/Triangulation/include/CGAL/Delaunay_triangulation.h b/Triangulation/include/CGAL/Delaunay_triangulation.h index 40076704d30..3a6185d9a02 100644 --- a/Triangulation/include/CGAL/Delaunay_triangulation.h +++ b/Triangulation/include/CGAL/Delaunay_triangulation.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include diff --git a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h index fb1d220f1bc..c9046c0ea27 100644 --- a/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h +++ b/Triangulation/include/CGAL/Regular_triangulation_traits_adapter.h @@ -25,7 +25,7 @@ #include -#include +#include namespace CGAL { diff --git a/Triangulation/include/CGAL/Triangulation.h b/Triangulation/include/CGAL/Triangulation.h index dd1f7c9c560..460030287c3 100644 --- a/Triangulation/include/CGAL/Triangulation.h +++ b/Triangulation/include/CGAL/Triangulation.h @@ -36,7 +36,7 @@ #include #include -#include +#include namespace CGAL { diff --git a/Triangulation_2/benchmark/Triangulation_2/CDT_with_intersection_2.cpp b/Triangulation_2/benchmark/Triangulation_2/CDT_with_intersection_2.cpp index 6075b23de80..c4bd24a23b3 100644 --- a/Triangulation_2/benchmark/Triangulation_2/CDT_with_intersection_2.cpp +++ b/Triangulation_2/benchmark/Triangulation_2/CDT_with_intersection_2.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include diff --git a/Triangulation_2/examples/Triangulation_2/info_insert_with_transform_iterator_2.cpp b/Triangulation_2/examples/Triangulation_2/info_insert_with_transform_iterator_2.cpp index 0f2cc96d356..cf865ef9ffc 100644 --- a/Triangulation_2/examples/Triangulation_2/info_insert_with_transform_iterator_2.cpp +++ b/Triangulation_2/examples/Triangulation_2/info_insert_with_transform_iterator_2.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h index 36e6e56cf69..aaa1a301d3e 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2.h @@ -50,7 +50,7 @@ #include #include #include -#include +#include #ifndef CGAL_NO_STRUCTURAL_FILTERING #include diff --git a/Triangulation_3/examples/Triangulation_3/info_insert_with_transform_iterator.cpp b/Triangulation_3/examples/Triangulation_3/info_insert_with_transform_iterator.cpp index 402cbb76e13..9b84be9b8af 100644 --- a/Triangulation_3/examples/Triangulation_3/info_insert_with_transform_iterator.cpp +++ b/Triangulation_3/examples/Triangulation_3/info_insert_with_transform_iterator.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; diff --git a/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h b/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h index 134c59736b6..f391ac0a075 100644 --- a/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h +++ b/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include #include diff --git a/Voronoi_diagram_2/include/CGAL/Voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/Voronoi_diagram_2.h index 7bdd1c10045..4f1bd13a3af 100644 --- a/Voronoi_diagram_2/include/CGAL/Voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/Voronoi_diagram_2.h @@ -51,7 +51,7 @@ #include #include -#include +#include namespace CGAL { From 361f132290b08c8d45e9b42afc2e487add9f634c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 31 Jan 2018 13:55:51 +0100 Subject: [PATCH 69/70] Fix conversion warning --- .../Plugins/Classification/Point_set_item_classification.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 638879548a9..98231a5e773 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -638,8 +638,8 @@ void Point_set_item_classification::train(int classifier, unsigned int nb_trials if (m_random_forest != NULL) delete m_random_forest; m_random_forest = new Random_forest (m_labels, m_features, - max_depth, 5, 15, - num_trees); + int(max_depth), 5, 15, + int(num_trees)); m_random_forest->train (training); CGAL::Classification::classify (*(m_points->point_set()), m_labels, *m_random_forest, From 30713b02c6b7bbc68025a89eccf30ddfcb7ce66f Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 31 Jan 2018 13:56:05 +0100 Subject: [PATCH 70/70] Disable *once again* that boost counting iterator warning --- .../examples/Classification/example_ethz_random_forest.cpp | 5 +++++ .../examples/Classification/example_opencv_random_forest.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Classification/examples/Classification/example_ethz_random_forest.cpp b/Classification/examples/Classification/example_ethz_random_forest.cpp index 961c63b41ac..f794e796680 100644 --- a/Classification/examples/Classification/example_ethz_random_forest.cpp +++ b/Classification/examples/Classification/example_ethz_random_forest.cpp @@ -1,3 +1,8 @@ +#if defined (_MSC_VER) && !defined (_WIN64) +#pragma warning(disable:4244) // boost::number_distance::distance() + // converts 64 to 32 bits integers +#endif + #include #include #include diff --git a/Classification/examples/Classification/example_opencv_random_forest.cpp b/Classification/examples/Classification/example_opencv_random_forest.cpp index 3f8971389e3..c7ca356c5bb 100644 --- a/Classification/examples/Classification/example_opencv_random_forest.cpp +++ b/Classification/examples/Classification/example_opencv_random_forest.cpp @@ -1,3 +1,8 @@ +#if defined (_MSC_VER) && !defined (_WIN64) +#pragma warning(disable:4244) // boost::number_distance::distance() + // converts 64 to 32 bits integers +#endif + #include #include #include