From 1c8cef1874262f45b8c85232d5b97f202d175ee5 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 15 Mar 2017 10:18:55 +0100 Subject: [PATCH] Make plugin more generic with Item_classification_base class --- .../Classification/Classification_plugin.cpp | 147 +++++++++--------- .../Classification/Item_classification_base.h | 68 ++++++++ .../Point_set_item_classification.cpp | 2 +- .../Point_set_item_classification.h | 145 ++++++++--------- 4 files changed, 203 insertions(+), 159 deletions(-) create mode 100644 Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index 7b9c4c8e1f4..bf1e9998b3b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -169,8 +169,8 @@ public: dock_widget->hide(); for (Item_map::iterator it = item_map.begin(); it != item_map.end(); ++ it) { - Point_set_item_classification* classif = it->second; - classif->erase_points_item(); + Item_classification_base* classif = it->second; + classif->erase_item(); delete classif; } item_map.clear(); @@ -180,18 +180,13 @@ public: public Q_SLOTS: void item_about_to_be_destroyed(CGAL::Three::Scene_item* scene_item) { - // if points item - Scene_points_with_normal_item* points_item = qobject_cast(scene_item); - if(points_item) + Item_map::iterator it = item_map.find(scene_item); + if (it != item_map.end()) { - Item_map::iterator it = item_map.find(points_item); - if (it != item_map.end()) - { - Point_set_item_classification* classif = it->second; - item_map.erase(it); // first erase from map, because scene->erase will cause a call to this function - classif->erase_points_item(); - delete classif; - } + Item_classification_base* classif = it->second; + item_map.erase(it); // first erase from map, because scene->erase will cause a call to this function + classif->erase_item(); + delete classif; } } @@ -200,14 +195,13 @@ public Q_SLOTS: dock_widget->show(); dock_widget->raise(); Scene_points_with_normal_item* points_item = getSelectedItem(); - create_from_item(points_item); } - void item_changed (Scene_points_with_normal_item* points_item) + void item_changed (Scene_item* item) { - scene->itemChanged(points_item); - points_item->invalidateOpenGLBuffers(); + scene->itemChanged(item); + item->invalidateOpenGLBuffers(); } void update_plugin(int) @@ -251,7 +245,7 @@ public Q_SLOTS: } - void update_plugin_from_item(Point_set_item_classification* classif) + void update_plugin_from_item(Item_classification_base* classif) { if (classif == NULL) // Deactivate plugin { @@ -314,7 +308,7 @@ public Q_SLOTS: void on_update_nb_scales() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) return; @@ -322,7 +316,7 @@ public Q_SLOTS: } void on_update_number_of_trials() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) return; @@ -330,31 +324,31 @@ public Q_SLOTS: } - Point_set_item_classification* get_classification(Scene_points_with_normal_item* points_item = NULL) + Item_classification_base* get_classification(Scene_item* item = NULL) { - if (!points_item) - points_item = - qobject_cast(scene->item(scene->mainSelectionIndex())); + if (!item) + item = scene->item(scene->mainSelectionIndex()); - if (!points_item) + if (!item) return NULL; - Item_map::iterator it = item_map.find(points_item); + Item_map::iterator it = item_map.find(item); if (it != item_map.end()) return it->second; - else + else if (Scene_points_with_normal_item* points_item + = qobject_cast(scene->item(scene->mainSelectionIndex()))) return create_from_item(points_item); } - Point_set_item_classification* create_from_item(Scene_points_with_normal_item* points_item) + Item_classification_base* create_from_item(Scene_points_with_normal_item* points_item) { if (item_map.find(points_item) != item_map.end()) return item_map[points_item]; QApplication::setOverrideCursor(Qt::WaitCursor); - Point_set_item_classification* classif + Item_classification_base* classif = new Point_set_item_classification (points_item); item_map.insert (std::make_pair (points_item, classif)); QApplication::restoreOverrideCursor(); @@ -362,14 +356,14 @@ public Q_SLOTS: return classif; } - void run (Point_set_item_classification* classif, int method) + void run (Item_classification_base* classif, int method) { classif->run (method); } void on_compute_features_button_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -383,12 +377,12 @@ public Q_SLOTS: update_plugin_from_item(classif); QApplication::restoreOverrideCursor(); - item_changed(classif->points_item()); + item_changed(classif->item()); } void on_save_config_button_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -414,7 +408,7 @@ public Q_SLOTS: void on_load_config_button_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -436,24 +430,24 @@ public Q_SLOTS: run (classif, 0); QApplication::restoreOverrideCursor(); - item_changed(classif->points_item()); + item_changed(classif->item()); } void on_display_button_clicked(int index) { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) return; classif->change_color (index); - item_changed(classif->points_item()); + item_changed(classif->item()); } void on_run_button_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -463,12 +457,12 @@ public Q_SLOTS: QApplication::setOverrideCursor(Qt::WaitCursor); run (classif, 0); QApplication::restoreOverrideCursor(); - item_changed(classif->points_item()); + item_changed(classif->item()); } void on_run_smoothed_button_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -482,12 +476,12 @@ public Q_SLOTS: run (classif, 1); std::cerr << "Smoothed classification computed in " << time.elapsed() / 1000 << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); - item_changed(classif->points_item()); + item_changed(classif->item()); } void on_run_graphcut_button_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -501,12 +495,12 @@ public Q_SLOTS: run (classif, 2); std::cerr << "Graphcut classification computed in " << time.elapsed() / 1000 << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); - item_changed(classif->points_item()); + item_changed(classif->item()); } void on_smoothing_value_changed(double v) { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) return; @@ -515,7 +509,7 @@ public Q_SLOTS: void on_subdivisions_value_changed(int v) { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) return; @@ -527,7 +521,7 @@ public Q_SLOTS: Scene_points_with_normal_item* points_item = qobject_cast(scene->item(scene->mainSelectionIndex())); - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(points_item); if(!classif) { @@ -546,7 +540,7 @@ public Q_SLOTS: std::ofstream out(filename.toUtf8()); QApplication::setOverrideCursor(Qt::WaitCursor); - classif->write_ply_point_set (out); + classif->write_output (out); QApplication::restoreOverrideCursor(); out.close(); @@ -554,7 +548,7 @@ public Q_SLOTS: void on_generate_items_button_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -565,16 +559,21 @@ public Q_SLOTS: QApplication::setOverrideCursor(Qt::WaitCursor); - std::vector new_items; - classif->generate_point_set_items - (new_items, classif->points_item()->name().toStdString().c_str()); + std::vector new_items; + classif->generate_one_item_per_label + (new_items, classif->item()->name().toStdString().c_str()); for (std::size_t i = 0; i < new_items.size(); ++ i) { - if (new_items[i]->point_set()->empty()) - delete new_items[i]; + Scene_points_with_normal_item* points_item + = qobject_cast(new_items[i]); + if (!points_item) + continue; + + if (points_item->point_set()->empty()) + delete points_item; else - scene->addItem (new_items[i]); + scene->addItem (points_item); } QApplication::restoreOverrideCursor(); @@ -582,7 +581,7 @@ public Q_SLOTS: void on_add_new_label_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -613,7 +612,7 @@ public Q_SLOTS: void on_reset_training_sets_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -626,7 +625,7 @@ public Q_SLOTS: void on_validate_selection_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -639,7 +638,7 @@ public Q_SLOTS: void on_train_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -688,7 +687,7 @@ public Q_SLOTS: void on_remove_class_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -731,12 +730,12 @@ public Q_SLOTS: class_rows.erase (class_rows.begin() + row_index); - item_changed(classif->points_item()); + item_changed(classif->item()); } void on_color_changed_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -756,12 +755,12 @@ public Q_SLOTS: classif->change_label_color (class_rows[row_index].label->text().toStdString().c_str(), color); - item_changed(classif->points_item()); + item_changed(classif->item()); } void on_add_selection_to_training_set_clicked() { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -777,12 +776,12 @@ public Q_SLOTS: classif->add_selection_to_training_set (class_rows[row_index].label->text().toStdString().c_str()); - item_changed(classif->points_item()); + item_changed(classif->item()); } void on_selected_feature_changed(int v) { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { @@ -793,10 +792,10 @@ public Q_SLOTS: if (classif->number_of_features() <= (std::size_t)v) return; - Point_set_item_classification::Feature_handle + Item_classification_base::Feature_handle att = classif->feature(v); - if (att == Point_set_item_classification::Feature_handle()) + if (att == Item_classification_base::Feature_handle()) return; // std::cerr << att->weight() @@ -819,17 +818,17 @@ public Q_SLOTS: void on_feature_weight_changed(int v) { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { print_message("Error: there is no point set classification item!"); return; } - Point_set_item_classification::Feature_handle + Item_classification_base::Feature_handle att = classif->feature(ui_widget.selected_feature->currentIndex()); - if (att == Point_set_item_classification::Feature_handle()) + if (att == Item_classification_base::Feature_handle()) return; att->set_weight(std::tan ((CGAL_PI/2.) * v / 1001.)); @@ -841,17 +840,17 @@ public Q_SLOTS: void on_effect_changed (int v) { - Point_set_item_classification* classif + Item_classification_base* classif = get_classification(); if(!classif) { print_message("Error: there is no point set classification item!"); return; } - Point_set_item_classification::Feature_handle + Item_classification_base::Feature_handle att = classif->feature(ui_widget.selected_feature->currentIndex()); - if (att == Point_set_item_classification::Feature_handle()) + if (att == Item_classification_base::Feature_handle()) return; QComboBox* combo = qobject_cast(QObject::sender()); @@ -894,7 +893,7 @@ private: QColor color_att; - typedef std::map Item_map; + typedef std::map Item_map; Item_map item_map; }; // end Polyhedron_demo_classification_plugin diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h new file mode 100644 index 00000000000..c4894f60937 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Item_classification_base.h @@ -0,0 +1,68 @@ +#ifndef ITEM_CLASSIFICATION_BASE_H +#define ITEM_CLASSIFICATION_BASE_H + +#include + +#include + +#include +#include + +class Item_classification_base +{ +public: + typedef CGAL::Classification::Label_handle Label_handle; + typedef CGAL::Classification::Feature_handle Feature_handle; + +public: + + Item_classification_base() { } + virtual ~Item_classification_base() { } + + virtual CGAL::Three::Scene_item* item() = 0; + virtual void erase_item() = 0; + + virtual void compute_features () = 0; + virtual bool features_computed() const = 0; + virtual std::size_t number_of_features() const = 0; + virtual Feature_handle feature(std::size_t i) = 0; + + virtual void add_new_label (const char* name, const QColor& color) = 0; + virtual void remove_label (const char* name) = 0; + + virtual void add_selection_to_training_set (const char* name) = 0; + virtual void reset_training_sets() = 0; + virtual void validate_selection () = 0; + virtual void train() = 0; + virtual bool run (int method) = 0; + + virtual void change_color (int index) = 0; + virtual void change_label_color (const char* name, const QColor& color) = 0; + virtual void fill_display_combo_box (QComboBox* cb, QComboBox* cb1) const = 0; + virtual void generate_one_item_per_label(std::vector& items, + const char* name) const = 0; + + virtual bool write_output(std::ostream& out) = 0; + virtual void save_config(const char* filename) = 0; + virtual void load_config(const char* filename) = 0; + + std::size_t& nb_scales() { return m_nb_scales; } + std::size_t& number_of_trials() { return m_nb_trials; } + double& smoothing() { return m_smoothing; } + std::size_t& subdivisions() { return m_subdivisions; } + std::vector >& labels() { return m_labels; } + +protected: + + std::size_t m_nb_scales; + std::vector > m_labels; + std::size_t m_nb_trials; + double m_smoothing; + std::size_t m_subdivisions; + +}; + + + + +#endif // ITEM_CLASSIFICATION_BASE_H 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 9ac76368efa..1d09be9a6db 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -103,7 +103,7 @@ void Point_set_item_classification::reset_colors() } // Write point set to .PLY file -bool Point_set_item_classification::write_ply_point_set(std::ostream& stream) +bool Point_set_item_classification::write_output(std::ostream& stream) { if (m_psc->number_of_features() == 0) return false; 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 85eb93ff57e..db12f80afdb 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.h @@ -17,6 +17,7 @@ #include #include "Scene_points_with_normal_item.h" +#include "Item_classification_base.h" #include "Polyhedron_type_fwd.h" #include "Kernel_type.h" #include "Point_set_3.h" @@ -25,7 +26,7 @@ // This class represents a point set in the OpenGL scene -class Point_set_item_classification +class Point_set_item_classification : public Item_classification_base { public: typedef Kernel::Point_3 Point_3; @@ -50,59 +51,30 @@ class Point_set_item_classification Point_set_item_classification(Scene_points_with_normal_item* points); ~Point_set_item_classification(); - // IO - bool write_ply_point_set(std::ostream& out); + CGAL::Three::Scene_item* item() { return m_points; } + void erase_item() { m_points = NULL; } - void change_color (int index); - int real_index_color() const; - - void reset_indices(); void compute_features (); - bool run (int method); - - void backup_existing_colors_and_add_new(); - void reset_colors(); - - template - void generate_point_set_items(std::vector& items, - const char* name) + bool features_computed() const { return (m_psc->number_of_features() != 0); } + std::size_t number_of_features() const { return m_psc->number_of_features(); } + Feature_handle feature(std::size_t i) { return m_psc->feature(i); } + + void add_new_label (const char* name, const QColor& color) { - std::map map_labels; - for (std::size_t i = 0; i < m_labels.size(); ++ i) - { - items.push_back (new Item); - items.back()->setName (QString("%1 (%2)").arg(name).arg(m_labels[i].first->name().c_str())); - items.back()->setColor (m_labels[i].second); - map_labels[m_labels[i].first] = i; - } - - for (Point_set::const_iterator it = m_points->point_set()->begin(); - it != m_points->point_set()->end(); ++ it) - { - Label_handle c = m_psc->label_of(*it); - if (c != Label_handle()) - items[map_labels[c]]->point_set()->insert (m_points->point_set()->point(*it)); - } + m_labels.push_back (std::make_pair (m_psc->add_label(name), + color)); } - - Scene_points_with_normal_item* points_item() { return m_points; } - void erase_points_item() { m_points = NULL; } - - void reset_training_sets() - { - m_trainer->reset_inlier_sets(); - } - - void train(); - - Label_handle get_label (const char* name) + void remove_label (const char* name) { for (std::size_t i = 0; i < m_labels.size(); ++ i) if (m_labels[i].first->name() == name) - return m_labels[i].first; - return Label_handle(); + { + m_psc->remove_label (m_labels[i].first); + m_labels.erase (m_labels.begin() + i); + break; + } } - + void add_selection_to_training_set (const char* name) { Label_handle label = get_label (name); @@ -119,7 +91,10 @@ class Point_set_item_classification if (m_index_color == 1 || m_index_color == 2) change_color (m_index_color); } - + void reset_training_sets() + { + m_trainer->reset_inlier_sets(); + } void validate_selection () { for (Point_set::const_iterator it = m_points->point_set()->first_selected(); @@ -133,33 +108,10 @@ class Point_set_item_classification if (m_index_color == 1 || m_index_color == 2) change_color (m_index_color); } + void train(); + bool run (int method); - double& smoothing() { return m_smoothing; } - std::size_t& subdivisions() { return m_subdivisions; } - std::size_t& nb_scales() { return m_nb_scales; } - std::size_t& number_of_trials() { return m_nb_trials; } - bool features_computed() const { return (m_psc->number_of_features() != 0); } - - std::vector >& labels() { return m_labels; } - std::size_t number_of_features() const { return m_psc->number_of_features(); } - Feature_handle feature(std::size_t i) { return m_psc->feature(i); } - void add_new_label (const char* name, const QColor& color) - { - m_labels.push_back (std::make_pair (m_psc->add_label(name), - color)); - } - - void remove_label (const char* name) - { - for (std::size_t i = 0; i < m_labels.size(); ++ i) - if (m_labels[i].first->name() == name) - { - m_psc->remove_label (m_labels[i].first); - m_labels.erase (m_labels.begin() + i); - break; - } - } - + void change_color (int index); void change_label_color (const char* name, const QColor& color) { for (std::size_t i = 0; i < m_labels.size(); ++ i) @@ -169,9 +121,7 @@ class Point_set_item_classification break; } } - - template - void fill_display_combo_box (ComboBox* cb, ComboBox* cb1) + void fill_display_combo_box (QComboBox* cb, QComboBox* cb1) const { for (std::size_t i = 0; i < m_psc->number_of_features(); ++ i) { @@ -182,7 +132,29 @@ class Point_set_item_classification cb1->addItem (oss.str().c_str()); } } + void generate_one_item_per_label(std::vector& items, + const char* name) const + { + std::map map_labels; + for (std::size_t i = 0; i < m_labels.size(); ++ i) + { + Scene_points_with_normal_item* new_item = new Scene_points_with_normal_item; + new_item->setName (QString("%1 (%2)").arg(name).arg(m_labels[i].first->name().c_str())); + new_item->setColor (m_labels[i].second); + map_labels[m_labels[i].first] = new_item; + items.push_back (new_item); + } + for (Point_set::const_iterator it = m_points->point_set()->begin(); + it != m_points->point_set()->end(); ++ it) + { + Label_handle c = m_psc->label_of(*it); + if (c != Label_handle()) + map_labels[c]->point_set()->insert (m_points->point_set()->point(*it)); + } + } + + bool write_output(std::ostream& out); void save_config(const char* filename) { if (m_psc->number_of_features() == 0) @@ -194,7 +166,6 @@ class Point_set_item_classification std::ofstream f (filename); m_psc->save_configuration (f); } - void load_config(const char* filename) { if (m_psc->number_of_features() != 0) @@ -246,6 +217,19 @@ class Point_set_item_classification m_labels.swap (new_labels); } + + int real_index_color() const; + void reset_indices(); + void backup_existing_colors_and_add_new(); + void reset_colors(); + Label_handle get_label (const char* name) + { + for (std::size_t i = 0; i < m_labels.size(); ++ i) + if (m_labels[i].first->name() == name) + return m_labels[i].first; + return Label_handle(); + } + private: Scene_points_with_normal_item* m_points; @@ -257,13 +241,6 @@ class Point_set_item_classification PSC* m_psc; Trainer* m_trainer; - - std::size_t m_nb_scales; - - std::vector > m_labels; - std::size_t m_nb_trials; - double m_smoothing; - std::size_t m_subdivisions; int m_index_color;