Make plugin more generic with Item_classification_base class

This commit is contained in:
Simon Giraudot 2017-03-15 10:18:55 +01:00
parent 5f17ba9cf1
commit 1c8cef1874
4 changed files with 203 additions and 159 deletions

View File

@ -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_points_with_normal_item*>(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<Scene_points_with_normal_item>();
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_points_with_normal_item*>(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_points_with_normal_item*>(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_points_with_normal_item*>(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<Scene_points_with_normal_item*> new_items;
classif->generate_point_set_items<Scene_points_with_normal_item>
(new_items, classif->points_item()->name().toStdString().c_str());
std::vector<Scene_item*> 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<Scene_points_with_normal_item*>(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<QComboBox*>(QObject::sender());
@ -894,7 +893,7 @@ private:
QColor color_att;
typedef std::map<Scene_points_with_normal_item*, Point_set_item_classification*> Item_map;
typedef std::map<Scene_item*, Item_classification_base*> Item_map;
Item_map item_map;
}; // end Polyhedron_demo_classification_plugin

View File

@ -0,0 +1,68 @@
#ifndef ITEM_CLASSIFICATION_BASE_H
#define ITEM_CLASSIFICATION_BASE_H
#include <CGAL/Three/Scene_item.h>
#include <QComboBox>
#include <CGAL/Classification/Trainer.h>
#include <CGAL/Classification/Feature_base.h>
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<CGAL::Three::Scene_item*>& 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<std::pair<Label_handle, QColor> >& labels() { return m_labels; }
protected:
std::size_t m_nb_scales;
std::vector<std::pair<Label_handle, QColor> > m_labels;
std::size_t m_nb_trials;
double m_smoothing;
std::size_t m_subdivisions;
};
#endif // ITEM_CLASSIFICATION_BASE_H

View File

@ -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;

View File

@ -17,6 +17,7 @@
#include <CGAL/Classification/Feature/Eigen.h>
#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 <typename Item>
void generate_point_set_items(std::vector<Item*>& 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<Label_handle, std::size_t> 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<std::pair<Label_handle, QColor> >& 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 <typename ComboBox>
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<CGAL::Three::Scene_item*>& items,
const char* name) const
{
std::map<Label_handle, Scene_points_with_normal_item*> 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<std::pair<Label_handle, QColor> > m_labels;
std::size_t m_nb_trials;
double m_smoothing;
std::size_t m_subdivisions;
int m_index_color;