Global change of API
This commit is contained in:
@@ -50,6 +50,6 @@ include_directories( BEFORE ../../include )
|
||||
|
||||
include( CGAL_CreateSingleSourceCGALProgram )
|
||||
|
||||
create_single_source_cgal_program( "example_classifier.cpp" )
|
||||
create_single_source_cgal_program( "example_point_set_classifier.cpp" )
|
||||
create_single_source_cgal_program( "example_classification.cpp" )
|
||||
create_single_source_cgal_program( "example_generation_and_training.cpp" )
|
||||
create_single_source_cgal_program( "example_feature.cpp" )
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Classification.h>
|
||||
#include <CGAL/bounding_box.h>
|
||||
|
||||
#include <CGAL/IO/read_ply_points.h>
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef Kernel::Iso_cuboid_3 Iso_cuboid_3;
|
||||
typedef std::vector<Point> Point_range;
|
||||
typedef CGAL::Identity_property_map<Point> Pmap;
|
||||
|
||||
namespace Classif = CGAL::Classification;
|
||||
|
||||
typedef Classif::Sum_of_weighted_features_predicate Classification_predicate;
|
||||
|
||||
typedef Classif::Planimetric_grid<Kernel, Point_range, Pmap> Planimetric_grid;
|
||||
typedef Classif::Point_set_neighborhood<Kernel, Point_range, Pmap> Neighborhood;
|
||||
typedef Classif::Local_eigen_analysis<Kernel, Point_range, Pmap> Local_eigen_analysis;
|
||||
|
||||
typedef Classif::Label_handle Label_handle;
|
||||
typedef Classif::Feature_handle Feature_handle;
|
||||
typedef Classif::Label_set Label_set;
|
||||
typedef Classif::Feature_set Feature_set;
|
||||
|
||||
typedef Classif::Feature::Distance_to_plane<Kernel, Point_range, Pmap> Distance_to_plane;
|
||||
typedef Classif::Feature::Linearity<Kernel, Point_range, Pmap> Linearity;
|
||||
typedef Classif::Feature::Omnivariance<Kernel, Point_range, Pmap> Omnivariance;
|
||||
typedef Classif::Feature::Planarity<Kernel, Point_range, Pmap> Planarity;
|
||||
typedef Classif::Feature::Surface_variation<Kernel, Point_range, Pmap> Surface_variation;
|
||||
typedef Classif::Feature::Elevation<Kernel, Point_range, Pmap> Elevation;
|
||||
typedef Classif::Feature::Vertical_dispersion<Kernel, Point_range, Pmap> Dispersion;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//! [Analysis]
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
std::string filename (argc > 1 ? argv[1] : "data/b9.ply");
|
||||
std::ifstream in (filename.c_str());
|
||||
std::vector<Point> pts;
|
||||
|
||||
std::cerr << "Reading input" << std::endl;
|
||||
if (!in
|
||||
|| !(CGAL::read_ply_points (in, std::back_inserter (pts))))
|
||||
{
|
||||
std::cerr << "Error: cannot read " << filename << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
double grid_resolution = 0.34;
|
||||
double radius_neighbors = 1.7;
|
||||
double radius_dtm = 15.0;
|
||||
|
||||
std::cerr << "Computing useful structures" << std::endl;
|
||||
|
||||
Iso_cuboid_3 bbox = CGAL::bounding_box (pts.begin(), pts.end());
|
||||
|
||||
Planimetric_grid grid (pts, Pmap(), bbox, grid_resolution);
|
||||
Neighborhood neighborhood (pts, Pmap());
|
||||
Local_eigen_analysis eigen (pts, Pmap(), neighborhood.k_neighbor_query(6));
|
||||
|
||||
//! [Analysis]
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//! [Features]
|
||||
|
||||
std::cerr << "Computing features" << std::endl;
|
||||
Feature_set features;
|
||||
Feature_handle d2p = features.add<Distance_to_plane> (pts, Pmap(), eigen);
|
||||
Feature_handle lin = features.add<Linearity> (pts, eigen);
|
||||
Feature_handle omni = features.add<Omnivariance> (pts, eigen);
|
||||
Feature_handle plan = features.add<Planarity> (pts, eigen);
|
||||
Feature_handle surf = features.add<Surface_variation> (pts, eigen);
|
||||
Feature_handle disp = features.add<Dispersion> (pts, Pmap(), grid,
|
||||
grid_resolution,
|
||||
radius_neighbors);
|
||||
Feature_handle elev = features.add<Elevation> (pts, Pmap(), grid,
|
||||
grid_resolution,
|
||||
radius_dtm);
|
||||
|
||||
//! [Features]
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//! [Labels]
|
||||
|
||||
Label_set labels;
|
||||
Label_handle ground = labels.add ("ground");
|
||||
Label_handle vege = labels.add ("vegetation");
|
||||
Label_handle roof = labels.add ("roof");
|
||||
|
||||
std::cerr << "Setting weights" << std::endl;
|
||||
Classification_predicate predicate (labels, features);
|
||||
predicate.set_weight (d2p, 6.75e-2);
|
||||
predicate.set_weight (lin, 1.19);
|
||||
predicate.set_weight (omni, 1.34e-1);
|
||||
predicate.set_weight (plan, 7.32e-1);
|
||||
predicate.set_weight (surf, 1.36e-1);
|
||||
predicate.set_weight (disp, 5.45e-1);
|
||||
predicate.set_weight (elev, 1.47e1);
|
||||
|
||||
std::cerr << "Setting effects" << std::endl;
|
||||
predicate.set_effect (ground, d2p, Classification_predicate::NEUTRAL);
|
||||
predicate.set_effect (ground, lin, Classification_predicate::PENALIZING);
|
||||
predicate.set_effect (ground, omni, Classification_predicate::NEUTRAL);
|
||||
predicate.set_effect (ground, plan, Classification_predicate::FAVORING);
|
||||
predicate.set_effect (ground, surf, Classification_predicate::PENALIZING);
|
||||
predicate.set_effect (ground, disp, Classification_predicate::NEUTRAL);
|
||||
predicate.set_effect (ground, elev, Classification_predicate::PENALIZING);
|
||||
|
||||
predicate.set_effect (vege, d2p, Classification_predicate::FAVORING);
|
||||
predicate.set_effect (vege, lin, Classification_predicate::NEUTRAL);
|
||||
predicate.set_effect (vege, omni, Classification_predicate::FAVORING);
|
||||
predicate.set_effect (vege, plan, Classification_predicate::NEUTRAL);
|
||||
predicate.set_effect (vege, surf, Classification_predicate::NEUTRAL);
|
||||
predicate.set_effect (vege, disp, Classification_predicate::FAVORING);
|
||||
predicate.set_effect (vege, elev, Classification_predicate::NEUTRAL);
|
||||
|
||||
predicate.set_effect (roof, d2p, Classification_predicate::NEUTRAL);
|
||||
predicate.set_effect (roof, lin, Classification_predicate::PENALIZING);
|
||||
predicate.set_effect (roof, omni, Classification_predicate::FAVORING);
|
||||
predicate.set_effect (roof, plan, Classification_predicate::FAVORING);
|
||||
predicate.set_effect (roof, surf, Classification_predicate::PENALIZING);
|
||||
predicate.set_effect (roof, disp, Classification_predicate::NEUTRAL);
|
||||
predicate.set_effect (roof, elev, Classification_predicate::FAVORING);
|
||||
|
||||
//! [Labels]
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
// Run classification
|
||||
std::cerr << "Classifying" << std::endl;
|
||||
std::vector<std::size_t> label_indices;
|
||||
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
Classif::classify<CGAL::Parallel_tag> (pts, labels, predicate, label_indices);
|
||||
t.stop();
|
||||
std::cerr << "Raw classification performed in " << t.time() << " second(s)" << std::endl;
|
||||
t.reset();
|
||||
|
||||
t.start();
|
||||
Classif::classify_with_local_smoothing<CGAL::Parallel_tag>
|
||||
(pts, Pmap(), labels, predicate,
|
||||
neighborhood.range_neighbor_query(radius_neighbors),
|
||||
label_indices);
|
||||
t.stop();
|
||||
std::cerr << "Classification with local smoothing performed in " << t.time() << " second(s)" << std::endl;
|
||||
t.reset();
|
||||
|
||||
t.start();
|
||||
Classif::classify_with_graphcut<CGAL::Sequential_tag>
|
||||
(pts, Pmap(), Pmap(), labels, predicate,
|
||||
neighborhood.k_neighbor_query(12),
|
||||
0.2, 1, label_indices);
|
||||
t.stop();
|
||||
std::cerr << "Classification with graphcut performed in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
// Save the output in a colored PLY format
|
||||
|
||||
std::ofstream f ("classification.ply");
|
||||
f << "ply" << std::endl
|
||||
<< "format ascii 1.0" << std::endl
|
||||
<< "element vertex " << pts.size() << std::endl
|
||||
<< "property float x" << std::endl
|
||||
<< "property float y" << std::endl
|
||||
<< "property float z" << std::endl
|
||||
<< "property uchar red" << std::endl
|
||||
<< "property uchar green" << std::endl
|
||||
<< "property uchar blue" << std::endl
|
||||
<< "end_header" << std::endl;
|
||||
|
||||
for (std::size_t i = 0; i < pts.size(); ++ i)
|
||||
{
|
||||
f << pts[i] << " ";
|
||||
|
||||
Label_handle label = labels[label_indices[i]];
|
||||
if (label == ground)
|
||||
f << "245 180 0" << std::endl;
|
||||
else if (label == vege)
|
||||
f << "0 255 27" << std::endl;
|
||||
else if (label == roof)
|
||||
f << "255 0 170" << std::endl;
|
||||
else
|
||||
{
|
||||
f << "0 0 0" << std::endl;
|
||||
std::cerr << "Error: unknown classification label" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "All done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Classifier.h>
|
||||
#include <CGAL/Classification/Point_set_neighborhood.h>
|
||||
#include <CGAL/Classification/Planimetric_grid.h>
|
||||
#include <CGAL/Classification/Feature_base.h>
|
||||
#include <CGAL/Classification/Feature/Eigen.h>
|
||||
#include <CGAL/Classification/Feature/Distance_to_plane.h>
|
||||
#include <CGAL/Classification/Feature/Vertical_dispersion.h>
|
||||
#include <CGAL/Classification/Feature/Elevation.h>
|
||||
|
||||
#include <CGAL/IO/read_ply_points.h>
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef Kernel::Iso_cuboid_3 Iso_cuboid_3;
|
||||
typedef std::vector<Point> Point_range;
|
||||
typedef CGAL::Identity_property_map<Point> Pmap;
|
||||
|
||||
typedef CGAL::Classifier<Point_range, Pmap> Classifier;
|
||||
|
||||
typedef CGAL::Classification::Planimetric_grid<Kernel, Point_range, Pmap> Planimetric_grid;
|
||||
typedef CGAL::Classification::Point_set_neighborhood<Kernel, Point_range, Pmap> Neighborhood;
|
||||
typedef CGAL::Classification::Local_eigen_analysis<Kernel, Point_range, Pmap> Local_eigen_analysis;
|
||||
|
||||
typedef CGAL::Classification::Label_handle Label_handle;
|
||||
typedef CGAL::Classification::Feature_handle Feature_handle;
|
||||
|
||||
typedef CGAL::Classification::Feature::Distance_to_plane<Kernel, Point_range, Pmap> Distance_to_plane;
|
||||
typedef CGAL::Classification::Feature::Linearity<Kernel, Point_range, Pmap> Linearity;
|
||||
typedef CGAL::Classification::Feature::Omnivariance<Kernel, Point_range, Pmap> Omnivariance;
|
||||
typedef CGAL::Classification::Feature::Planarity<Kernel, Point_range, Pmap> Planarity;
|
||||
typedef CGAL::Classification::Feature::Surface_variation<Kernel, Point_range, Pmap> Surface_variation;
|
||||
typedef CGAL::Classification::Feature::Elevation<Kernel, Point_range, Pmap> Elevation;
|
||||
typedef CGAL::Classification::Feature::Vertical_dispersion<Kernel, Point_range, Pmap> Dispersion;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//! [Analysis]
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
std::string filename (argc > 1 ? argv[1] : "data/b9.ply");
|
||||
std::ifstream in (filename.c_str());
|
||||
std::vector<Point> pts;
|
||||
|
||||
std::cerr << "Reading input" << std::endl;
|
||||
if (!in
|
||||
|| !(CGAL::read_ply_points (in, std::back_inserter (pts))))
|
||||
{
|
||||
std::cerr << "Error: cannot read " << filename << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
double grid_resolution = 0.34;
|
||||
double radius_neighbors = 1.7;
|
||||
double radius_dtm = 15.0;
|
||||
|
||||
std::cerr << "Computing useful structures" << std::endl;
|
||||
|
||||
Iso_cuboid_3 bbox = CGAL::bounding_box (pts.begin(), pts.end());
|
||||
|
||||
Planimetric_grid grid (pts, Pmap(), bbox, grid_resolution);
|
||||
Neighborhood neighborhood (pts, Pmap());
|
||||
Local_eigen_analysis eigen (pts, Pmap(), neighborhood.k_neighbor_query(6));
|
||||
|
||||
Classifier classifier (pts, Pmap());
|
||||
|
||||
//! [Analysis]
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//! [Features]
|
||||
|
||||
std::cerr << "Computing features" << std::endl;
|
||||
Feature_handle d2p = classifier.add_feature<Distance_to_plane> (Pmap(), eigen);
|
||||
Feature_handle lin = classifier.add_feature<Linearity> (eigen);
|
||||
Feature_handle omni = classifier.add_feature<Omnivariance> (eigen);
|
||||
Feature_handle plan = classifier.add_feature<Planarity> (eigen);
|
||||
Feature_handle surf = classifier.add_feature<Surface_variation> (eigen);
|
||||
Feature_handle disp = classifier.add_feature<Dispersion> (Pmap(), grid,
|
||||
grid_resolution,
|
||||
radius_neighbors);
|
||||
Feature_handle elev = classifier.add_feature<Elevation> (Pmap(), grid,
|
||||
grid_resolution,
|
||||
radius_dtm);
|
||||
|
||||
std::cerr << "Setting weights" << std::endl;
|
||||
d2p->set_weight(6.75e-2);
|
||||
lin->set_weight(1.19);
|
||||
omni->set_weight(1.34e-1);
|
||||
plan->set_weight(7.32e-1);
|
||||
surf->set_weight(1.36e-1);
|
||||
disp->set_weight(5.45e-1);
|
||||
elev->set_weight(1.47e1);
|
||||
|
||||
|
||||
//! [Features]
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//! [Labels]
|
||||
|
||||
std::cerr << "Setting up labels" << std::endl;
|
||||
|
||||
// Create label and define how features affect them
|
||||
Label_handle ground = classifier.add_label ("ground");
|
||||
ground->set_feature_effect (d2p, CGAL::Classification::Feature::NEUTRAL);
|
||||
ground->set_feature_effect (lin, CGAL::Classification::Feature::PENALIZING);
|
||||
ground->set_feature_effect (omni, CGAL::Classification::Feature::NEUTRAL);
|
||||
ground->set_feature_effect (plan, CGAL::Classification::Feature::FAVORING);
|
||||
ground->set_feature_effect (surf, CGAL::Classification::Feature::PENALIZING);
|
||||
ground->set_feature_effect (disp, CGAL::Classification::Feature::NEUTRAL);
|
||||
ground->set_feature_effect (elev, CGAL::Classification::Feature::PENALIZING);
|
||||
|
||||
Label_handle vege = classifier.add_label ("vegetation");
|
||||
vege->set_feature_effect (d2p, CGAL::Classification::Feature::FAVORING);
|
||||
vege->set_feature_effect (lin, CGAL::Classification::Feature::NEUTRAL);
|
||||
vege->set_feature_effect (omni, CGAL::Classification::Feature::FAVORING);
|
||||
vege->set_feature_effect (plan, CGAL::Classification::Feature::NEUTRAL);
|
||||
vege->set_feature_effect (surf, CGAL::Classification::Feature::NEUTRAL);
|
||||
vege->set_feature_effect (disp, CGAL::Classification::Feature::FAVORING);
|
||||
vege->set_feature_effect (elev, CGAL::Classification::Feature::NEUTRAL);
|
||||
|
||||
Label_handle roof = classifier.add_label ("roof");
|
||||
roof->set_feature_effect (d2p, CGAL::Classification::Feature::NEUTRAL);
|
||||
roof->set_feature_effect (lin, CGAL::Classification::Feature::PENALIZING);
|
||||
roof->set_feature_effect (omni, CGAL::Classification::Feature::FAVORING);
|
||||
roof->set_feature_effect (plan, CGAL::Classification::Feature::FAVORING);
|
||||
roof->set_feature_effect (surf, CGAL::Classification::Feature::PENALIZING);
|
||||
roof->set_feature_effect (disp, CGAL::Classification::Feature::NEUTRAL);
|
||||
roof->set_feature_effect (elev, CGAL::Classification::Feature::FAVORING);
|
||||
|
||||
//! [Labels]
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
// Run classification
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
classifier.run ();
|
||||
t.stop();
|
||||
std::cerr << "Raw classification performed in " << t.time() << " second(s)" << std::endl;
|
||||
t.reset();
|
||||
t.start();
|
||||
classifier.run_with_local_smoothing (neighborhood.range_neighbor_query(radius_neighbors));
|
||||
t.stop();
|
||||
std::cerr << "Classification with local smoothing performed in " << t.time() << " second(s)" << std::endl;
|
||||
t.reset();
|
||||
t.start();
|
||||
classifier.run_with_graphcut (neighborhood.k_neighbor_query(12), 0.2);
|
||||
t.stop();
|
||||
std::cerr << "Classification with graphcut performed in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
// Save the output in a colored PLY format
|
||||
|
||||
std::ofstream f ("classification.ply");
|
||||
f << "ply" << std::endl
|
||||
<< "format ascii 1.0" << std::endl
|
||||
<< "element vertex " << pts.size() << std::endl
|
||||
<< "property float x" << std::endl
|
||||
<< "property float y" << std::endl
|
||||
<< "property float z" << std::endl
|
||||
<< "property uchar red" << std::endl
|
||||
<< "property uchar green" << std::endl
|
||||
<< "property uchar blue" << std::endl
|
||||
<< "end_header" << std::endl;
|
||||
|
||||
for (std::size_t i = 0; i < pts.size(); ++ i)
|
||||
{
|
||||
f << pts[i] << " ";
|
||||
|
||||
Label_handle label = classifier.label_of (i);
|
||||
if (label == ground)
|
||||
f << "245 180 0" << std::endl;
|
||||
else if (label == vege)
|
||||
f << "0 255 27" << std::endl;
|
||||
else if (label == roof)
|
||||
f << "255 0 170" << std::endl;
|
||||
else
|
||||
{
|
||||
f << "0 0 0" << std::endl;
|
||||
std::cerr << "Error: unknown classification label" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "All done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -4,12 +4,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Classifier.h>
|
||||
#include <CGAL/Classification/Point_set_neighborhood.h>
|
||||
#include <CGAL/Classification/Planimetric_grid.h>
|
||||
#include <CGAL/Classification/Feature_base.h>
|
||||
#include <CGAL/Classification/Feature/Eigen.h>
|
||||
|
||||
#include <CGAL/Classification.h>
|
||||
#include <CGAL/IO/read_ply_points.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
@@ -18,15 +13,19 @@ typedef Kernel::Iso_cuboid_3 Iso_cuboid_3;
|
||||
typedef std::vector<Point> Point_range;
|
||||
typedef CGAL::Identity_property_map<Point> Pmap;
|
||||
|
||||
typedef CGAL::Classifier<Point_range, Pmap> Classifier;
|
||||
namespace Classif = CGAL::Classification;
|
||||
|
||||
typedef CGAL::Classification::Point_set_neighborhood<Kernel, Point_range, Pmap> Neighborhood;
|
||||
typedef CGAL::Classification::Local_eigen_analysis<Kernel, Point_range, Pmap> Local_eigen_analysis;
|
||||
typedef Classif::Sum_of_weighted_features_predicate Classification_predicate;
|
||||
|
||||
typedef CGAL::Classification::Label_handle Label_handle;
|
||||
typedef CGAL::Classification::Feature_handle Feature_handle;
|
||||
typedef Classif::Point_set_neighborhood<Kernel, Point_range, Pmap> Neighborhood;
|
||||
typedef Classif::Local_eigen_analysis<Kernel, Point_range, Pmap> Local_eigen_analysis;
|
||||
|
||||
typedef CGAL::Classification::Feature::Sphericity<Kernel, Point_range, Pmap> Sphericity;
|
||||
typedef Classif::Label_handle Label_handle;
|
||||
typedef Classif::Feature_handle Feature_handle;
|
||||
typedef Classif::Label_set Label_set;
|
||||
typedef Classif::Feature_set Feature_set;
|
||||
|
||||
typedef Classif::Feature::Sphericity<Kernel, Point_range, Pmap> Sphericity;
|
||||
|
||||
|
||||
// User-defined feature that identifies a specific area of the 3D
|
||||
@@ -37,10 +36,12 @@ class My_feature : public CGAL::Classification::Feature_base
|
||||
const Point_range& range;
|
||||
double xmin, xmax, ymin, ymax;
|
||||
public:
|
||||
My_feature (const Point_range& range, // constructor should start with item range
|
||||
My_feature (const Point_range& range,
|
||||
double xmin, double xmax, double ymin, double ymax)
|
||||
: range (range), xmin(xmin), xmax(xmax), ymin(ymin), ymax(ymax)
|
||||
{ }
|
||||
{
|
||||
this->set_name ("my_feature");
|
||||
}
|
||||
|
||||
double value (std::size_t pt_index)
|
||||
{
|
||||
@@ -70,29 +71,36 @@ int main (int argc, char** argv)
|
||||
Neighborhood neighborhood (pts, Pmap());
|
||||
Local_eigen_analysis eigen (pts, Pmap(), neighborhood.k_neighbor_query(6));
|
||||
|
||||
Classifier classifier (pts, Pmap());
|
||||
|
||||
Label_set labels;
|
||||
Label_handle a = labels.add ("label_A");
|
||||
Label_handle b = labels.add ("label_B");
|
||||
|
||||
std::cerr << "Computing features" << std::endl;
|
||||
Feature_handle sphericity = classifier.add_feature<Sphericity> (eigen);
|
||||
Feature_set features;
|
||||
|
||||
Feature_handle sphericity = features.add<Sphericity> (pts, eigen);
|
||||
|
||||
// Feature that identifies points whose x coordinate is between -20
|
||||
// and 20 and whose y coordinate is between -15 and 15
|
||||
Feature_handle my_feature = classifier.add_feature<My_feature> (-20., 20., -15., 15.);
|
||||
|
||||
Feature_handle my_feature = features.add<My_feature> (pts, -20., 20., -15., 15.);
|
||||
|
||||
Classification_predicate predicate (labels, features);
|
||||
|
||||
std::cerr << "Setting weights" << std::endl;
|
||||
sphericity->set_weight(0.5);
|
||||
my_feature->set_weight(0.25);
|
||||
predicate.set_weight(sphericity, 0.5);
|
||||
predicate.set_weight(my_feature, 0.25);
|
||||
|
||||
std::cerr << "Setting up labels" << std::endl;
|
||||
Label_handle a = classifier.add_label ("label_A");
|
||||
a->set_feature_effect (sphericity, CGAL::Classification::Feature::FAVORING);
|
||||
a->set_feature_effect (my_feature, CGAL::Classification::Feature::FAVORING);
|
||||
predicate.set_effect (a, sphericity, Classification_predicate::FAVORING);
|
||||
predicate.set_effect (a, my_feature, Classification_predicate::FAVORING);
|
||||
predicate.set_effect (b, sphericity, Classification_predicate::PENALIZING);
|
||||
predicate.set_effect (b, my_feature, Classification_predicate::PENALIZING);
|
||||
|
||||
Label_handle b = classifier.add_label ("label_B");
|
||||
b->set_feature_effect (sphericity, CGAL::Classification::Feature::PENALIZING);
|
||||
b->set_feature_effect (my_feature, CGAL::Classification::Feature::PENALIZING);
|
||||
|
||||
classifier.run_with_graphcut (neighborhood.k_neighbor_query(12), 0.2);
|
||||
std::vector<std::size_t> label_indices;
|
||||
Classif::classify_with_graphcut<CGAL::Sequential_tag>
|
||||
(pts, Pmap(), Pmap(), labels, predicate,
|
||||
neighborhood.k_neighbor_query(12),
|
||||
0.5, 1, label_indices);
|
||||
|
||||
std::cerr << "All done" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
//#define CGAL_CLASSIFICATION_VERBOSE
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Classification.h>
|
||||
#include <CGAL/IO/read_ply_points.h>
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef Kernel::Iso_cuboid_3 Iso_cuboid_3;
|
||||
typedef std::vector<Point> Point_range;
|
||||
typedef CGAL::Identity_property_map<Point> Pmap;
|
||||
|
||||
namespace Classif = CGAL::Classification;
|
||||
|
||||
typedef Classif::Label_handle Label_handle;
|
||||
typedef Classif::Feature_handle Feature_handle;
|
||||
typedef Classif::Label_set Label_set;
|
||||
typedef Classif::Feature_set Feature_set;
|
||||
|
||||
typedef Classif::Sum_of_weighted_features_predicate Classification_predicate;
|
||||
|
||||
typedef Classif::Point_set_feature_generator<Kernel, Point_range, Pmap> Feature_generator;
|
||||
|
||||
/*
|
||||
This interpreter is used to read a PLY input that contains training
|
||||
attributes (with the PLY "label" property).
|
||||
*/
|
||||
class My_ply_interpreter
|
||||
{
|
||||
std::vector<Point>& points;
|
||||
std::vector<std::size_t>& labels;
|
||||
|
||||
public:
|
||||
My_ply_interpreter (std::vector<Point>& points,
|
||||
std::vector<std::size_t>& labels)
|
||||
: points (points), labels (labels)
|
||||
{ }
|
||||
|
||||
// Init and test if input file contains the right properties
|
||||
bool is_applicable (CGAL::Ply_reader& reader)
|
||||
{
|
||||
return reader.does_tag_exist<double> ("x")
|
||||
&& reader.does_tag_exist<double> ("y")
|
||||
&& reader.does_tag_exist<double> ("z")
|
||||
&& reader.does_tag_exist<int> ("label");
|
||||
}
|
||||
|
||||
// Describes how to process one line (= one point object)
|
||||
void process_line (CGAL::Ply_reader& reader)
|
||||
{
|
||||
double x = 0., y = 0., z = 0.;
|
||||
int l = 0;
|
||||
|
||||
reader.assign (x, "x");
|
||||
reader.assign (y, "y");
|
||||
reader.assign (z, "z");
|
||||
reader.assign (l, "label");
|
||||
|
||||
points.push_back (Point (x, y, z));
|
||||
labels.push_back(std::size_t(l));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
std::string filename (argc > 1 ? argv[1] : "data/b9_training.ply");
|
||||
std::ifstream in (filename.c_str());
|
||||
std::vector<Point> pts;
|
||||
std::vector<std::size_t> ground_truth;
|
||||
|
||||
std::cerr << "Reading input" << std::endl;
|
||||
My_ply_interpreter interpreter (pts, ground_truth);
|
||||
if (!in
|
||||
|| !(CGAL::read_ply_custom_points (in, interpreter, Kernel())))
|
||||
{
|
||||
std::cerr << "Error: cannot read " << filename << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Feature_set features;
|
||||
|
||||
std::cerr << "Generating features" << std::endl;
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
Feature_generator generator (features, 5, // using 5 scales
|
||||
pts, Pmap());
|
||||
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 vege = labels.add ("vegetation");
|
||||
Label_handle roof = labels.add ("roof");
|
||||
Label_handle facade = labels.add ("facade");
|
||||
|
||||
Classification_predicate predicate (labels, features);
|
||||
|
||||
std::cerr << "Training" << std::endl;
|
||||
t.reset();
|
||||
t.start();
|
||||
predicate.train<CGAL::Sequential_tag> (ground_truth, 400);
|
||||
t.stop();
|
||||
std::cerr << "Done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
t.reset();
|
||||
t.start();
|
||||
std::vector<std::size_t> label_indices;
|
||||
Classif::classify_with_graphcut<CGAL::Sequential_tag>
|
||||
(pts, Pmap(), Pmap(), labels, predicate,
|
||||
generator.neighborhood().k_neighbor_query(12),
|
||||
0.2, 10, 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;
|
||||
Classif::Evaluation eval (labels, ground_truth, label_indices);
|
||||
|
||||
for (std::size_t i = 0; i < labels.size(); ++ i)
|
||||
{
|
||||
std::cerr << " * " << labels[i]->name() << ": "
|
||||
<< eval.precision(labels[i]) << " ; "
|
||||
<< eval.recall(labels[i]) << " ; "
|
||||
<< eval.f1_score(labels[i]) << " ; "
|
||||
<< eval.intersection_over_union(labels[i]) << std::endl;
|
||||
}
|
||||
|
||||
std::cerr << "Accuracy = " << eval.accuracy() << std::endl
|
||||
<< "Mean F1 score = " << eval.mean_f1_score() << std::endl
|
||||
<< "Mean IoU = " << eval.mean_intersection_over_union() << std::endl;
|
||||
|
||||
|
||||
/// Save the configuration to be able to reload it later
|
||||
std::ofstream fconfig ("config.xml");
|
||||
predicate.save_configuration (fconfig);
|
||||
fconfig.close();
|
||||
|
||||
std::cerr << "All done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
//#define CGAL_CLASSIFICATION_VERBOSE
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Point_set_classifier.h>
|
||||
#include <CGAL/Classification/Trainer.h>
|
||||
#include <CGAL/IO/read_ply_points.h>
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef Kernel::Iso_cuboid_3 Iso_cuboid_3;
|
||||
typedef std::vector<Point> Point_range;
|
||||
typedef CGAL::Identity_property_map<Point> Pmap;
|
||||
|
||||
typedef CGAL::Point_set_classifier<Kernel, Point_range, Pmap> Point_set_classifier;
|
||||
typedef CGAL::Classification::Trainer<Point_range, Pmap> Trainer;
|
||||
|
||||
/*
|
||||
This interpreter is used to read a PLY input that contains training
|
||||
attributes (with the PLY "label" property).
|
||||
*/
|
||||
class My_ply_interpreter
|
||||
{
|
||||
std::vector<Point>& points;
|
||||
std::vector<int>& labels;
|
||||
|
||||
public:
|
||||
My_ply_interpreter (std::vector<Point>& points,
|
||||
std::vector<int>& labels)
|
||||
: points (points), labels (labels)
|
||||
{ }
|
||||
|
||||
// Init and test if input file contains the right properties
|
||||
bool is_applicable (CGAL::Ply_reader& reader)
|
||||
{
|
||||
return reader.does_tag_exist<double> ("x")
|
||||
&& reader.does_tag_exist<double> ("y")
|
||||
&& reader.does_tag_exist<double> ("z")
|
||||
&& reader.does_tag_exist<int> ("label");
|
||||
}
|
||||
|
||||
// Describes how to process one line (= one point object)
|
||||
void process_line (CGAL::Ply_reader& reader)
|
||||
{
|
||||
double x = 0., y = 0., z = 0.;
|
||||
int l = 0;
|
||||
|
||||
reader.assign (x, "x");
|
||||
reader.assign (y, "y");
|
||||
reader.assign (z, "z");
|
||||
reader.assign (l, "label");
|
||||
|
||||
points.push_back (Point (x, y, z));
|
||||
labels.push_back(l);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
std::string filename (argc > 1 ? argv[1] : "data/b9_training.ply");
|
||||
std::ifstream in (filename.c_str());
|
||||
std::vector<Point> pts;
|
||||
std::vector<int> labels;
|
||||
|
||||
std::cerr << "Reading input" << std::endl;
|
||||
My_ply_interpreter interpreter (pts, labels);
|
||||
if (!in
|
||||
|| !(CGAL::read_ply_custom_points (in, interpreter, Kernel())))
|
||||
{
|
||||
std::cerr << "Error: cannot read " << filename << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Point_set_classifier psc (pts, Pmap());
|
||||
|
||||
std::cerr << "Generating features" << std::endl;
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
psc.generate_features (5); // Using 5 scales
|
||||
t.stop();
|
||||
std::cerr << "Done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
// Add types to PSC
|
||||
CGAL::Classification::Label_handle ground
|
||||
= psc.add_label ("ground");
|
||||
CGAL::Classification::Label_handle vege
|
||||
= psc.add_label ("vegetation");
|
||||
CGAL::Classification::Label_handle roof
|
||||
= psc.add_label ("roof");
|
||||
CGAL::Classification::Label_handle facade
|
||||
= psc.add_label ("facade");
|
||||
|
||||
Trainer trainer (psc);
|
||||
|
||||
// Set training sets
|
||||
std::size_t nb_inliers = 0;
|
||||
for (std::size_t i = 0; i < labels.size(); ++ i)
|
||||
{
|
||||
switch (labels[i])
|
||||
{
|
||||
case 0:
|
||||
trainer.set_inlier(vege, i);
|
||||
++ nb_inliers;
|
||||
break;
|
||||
case 1:
|
||||
trainer.set_inlier(ground, i);
|
||||
++ nb_inliers;
|
||||
break;
|
||||
case 2:
|
||||
trainer.set_inlier(roof, i);
|
||||
++ nb_inliers;
|
||||
break;
|
||||
case 3:
|
||||
trainer.set_inlier(facade, i);
|
||||
++ nb_inliers;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "Training using " << nb_inliers << " inliers" << std::endl;
|
||||
t.reset();
|
||||
t.start();
|
||||
trainer.train (400); // 800 trials
|
||||
t.stop();
|
||||
std::cerr << "Done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
std::cerr << "Precision, recall, F1 scores and IoU:" << std::endl;
|
||||
for (std::size_t i = 0; i < psc.number_of_labels(); ++ i)
|
||||
{
|
||||
std::cerr << " * " << psc.label(i)->name() << ": "
|
||||
<< trainer.precision(psc.label(i)) << " ; "
|
||||
<< trainer.recall(psc.label(i)) << " ; "
|
||||
<< trainer.f1_score(psc.label(i)) << " ; "
|
||||
<< trainer.intersection_over_union(psc.label(i)) << std::endl;
|
||||
}
|
||||
|
||||
std::cerr << "Accuracy = " << trainer.accuracy() << std::endl
|
||||
<< "Mean F1 score = " << trainer.mean_f1_score() << std::endl
|
||||
<< "Mean IoU = " << trainer.mean_intersection_over_union() << std::endl;
|
||||
|
||||
t.reset();
|
||||
t.start();
|
||||
psc.run_with_graphcut (psc.neighborhood().k_neighbor_query(12), 0.5);
|
||||
t.stop();
|
||||
std::cerr << "One graphcut done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
// Save the output in a colored PLY format
|
||||
{
|
||||
std::ofstream f ("classification_one.ply");
|
||||
f.precision(18);
|
||||
psc.write_classification_to_ply (f);
|
||||
}
|
||||
|
||||
t.reset();
|
||||
t.start();
|
||||
psc.run_with_graphcut (psc.neighborhood().k_neighbor_query(12), 0.5, 30);
|
||||
t.stop();
|
||||
std::cerr << std::size_t(pts.size() / 25000) << " graphcuts done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
// Save the output in a colored PLY format
|
||||
{
|
||||
std::ofstream f ("classification_several.ply");
|
||||
f.precision(18);
|
||||
psc.write_classification_to_ply (f);
|
||||
}
|
||||
|
||||
/// Save the configuration to be able to reload it later
|
||||
std::ofstream fconfig ("config.xml");
|
||||
psc.save_configuration (fconfig);
|
||||
|
||||
std::cerr << "All done" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user