mirror of https://github.com/CGAL/cgal
Use signed integer for label indices (better handling of unlabeled -1 case)
This commit is contained in:
parent
8043d342e7
commit
2ebc55e9c3
|
|
@ -3,19 +3,20 @@
|
|||
#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/Point_set_3.h>
|
||||
#include <CGAL/Point_set_3/IO.h>
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef CGAL::Point_set_3<Point> Point_set;
|
||||
typedef Kernel::Iso_cuboid_3 Iso_cuboid_3;
|
||||
typedef std::vector<Point> Point_range;
|
||||
typedef CGAL::Identity_property_map<Point> Pmap;
|
||||
|
||||
typedef typename Point_set::Point_map Pmap;
|
||||
typedef typename Point_set::Property_map<int> Imap;
|
||||
|
||||
namespace Classification = CGAL::Classification;
|
||||
|
||||
|
|
@ -24,68 +25,34 @@ typedef Classification::Feature_handle
|
|||
typedef Classification::Label_set Label_set;
|
||||
typedef Classification::Feature_set Feature_set;
|
||||
|
||||
typedef Classification::Sum_of_weighted_features_classifier Classifier;
|
||||
typedef Classification::Sum_of_weighted_features_classifier Classifier;
|
||||
|
||||
typedef Classification::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));
|
||||
}
|
||||
|
||||
};
|
||||
typedef Classification::Point_set_feature_generator<Kernel, Point_set, Pmap> Feature_generator;
|
||||
|
||||
|
||||
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;
|
||||
Point_set pts;
|
||||
|
||||
std::cerr << "Reading input" << std::endl;
|
||||
My_ply_interpreter interpreter (pts, ground_truth);
|
||||
if (!in
|
||||
|| !(CGAL::read_ply_custom_points (in, interpreter, Kernel())))
|
||||
in >> pts;
|
||||
|
||||
Imap label_map;
|
||||
bool lm_found = false;
|
||||
boost::tie (label_map, lm_found) = pts.property_map<int> ("label");
|
||||
if (!lm_found)
|
||||
{
|
||||
std::cerr << "Error: cannot read " << filename << std::endl;
|
||||
std::cerr << "Error: \"label\" property not found in input file." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::vector<int> ground_truth;
|
||||
ground_truth.reserve (pts.size());
|
||||
std::copy (pts.range(label_map).begin(), pts.range(label_map).end(),
|
||||
std::back_inserter (ground_truth));
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//! [Generator]
|
||||
|
||||
|
|
@ -94,7 +61,7 @@ int main (int argc, char** argv)
|
|||
std::cerr << "Generating features" << std::endl;
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
Feature_generator generator (features, pts, Pmap(),
|
||||
Feature_generator generator (features, pts, pts.point_map(),
|
||||
5); // using 5 scales
|
||||
t.stop();
|
||||
std::cerr << features.size() << " feature(s) generated in " << t.time() << " second(s)" << std::endl;
|
||||
|
|
@ -107,7 +74,6 @@ int main (int argc, char** argv)
|
|||
Label_handle ground = labels.add ("ground");
|
||||
Label_handle vegetation = labels.add ("vegetation");
|
||||
Label_handle roof = labels.add ("roof");
|
||||
Label_handle facade = labels.add ("facade");
|
||||
|
||||
Classifier classifier (labels, features);
|
||||
|
||||
|
|
@ -120,9 +86,9 @@ int main (int argc, char** argv)
|
|||
|
||||
t.reset();
|
||||
t.start();
|
||||
std::vector<std::size_t> label_indices;
|
||||
std::vector<int> label_indices(pts.size(), -1);
|
||||
Classification::classify_with_graphcut<CGAL::Sequential_tag>
|
||||
(pts, Pmap(), labels, classifier,
|
||||
(pts, pts.point_map(), labels, classifier,
|
||||
generator.neighborhood().k_neighbor_query(12),
|
||||
0.2, 10, label_indices);
|
||||
t.stop();
|
||||
|
|
|
|||
|
|
@ -3,20 +3,22 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
//#define CGAL_CLASSIFICATION_VERBOSE
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Classification.h>
|
||||
#include <CGAL/Classification/Random_forest_classifier.h>
|
||||
#include <CGAL/IO/read_ply_points.h>
|
||||
#include <CGAL/Point_set_3.h>
|
||||
#include <CGAL/Point_set_3/IO.h>
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> Kernel;
|
||||
typedef Kernel::Point_3 Point;
|
||||
typedef CGAL::Point_set_3<Point> Point_set;
|
||||
typedef Kernel::Iso_cuboid_3 Iso_cuboid_3;
|
||||
typedef std::vector<Point> Point_range;
|
||||
typedef CGAL::Identity_property_map<Point> Pmap;
|
||||
|
||||
typedef typename Point_set::Point_map Pmap;
|
||||
typedef typename Point_set::Property_map<int> Imap;
|
||||
typedef typename Point_set::Property_map<unsigned char> UCmap;
|
||||
|
||||
namespace Classification = CGAL::Classification;
|
||||
|
||||
|
|
@ -27,72 +29,38 @@ typedef Classification::Feature_set
|
|||
|
||||
typedef Classification::Random_forest_classifier Classifier;
|
||||
|
||||
typedef Classification::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));
|
||||
}
|
||||
|
||||
};
|
||||
typedef Classification::Point_set_feature_generator<Kernel, Point_set, Pmap> Feature_generator;
|
||||
|
||||
|
||||
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;
|
||||
Point_set pts;
|
||||
|
||||
std::cerr << "Reading input" << std::endl;
|
||||
My_ply_interpreter interpreter (pts, ground_truth);
|
||||
if (!in
|
||||
|| !(CGAL::read_ply_custom_points (in, interpreter, Kernel())))
|
||||
in >> pts;
|
||||
|
||||
Imap label_map;
|
||||
bool lm_found = false;
|
||||
boost::tie (label_map, lm_found) = pts.property_map<int> ("label");
|
||||
if (!lm_found)
|
||||
{
|
||||
std::cerr << "Error: cannot read " << filename << std::endl;
|
||||
std::cerr << "Error: \"label\" property not found in input file." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::vector<int> 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, Pmap(),
|
||||
Feature_generator generator (features, pts, pts.point_map(),
|
||||
5); // using 5 scales
|
||||
t.stop();
|
||||
std::cerr << "Done in " << t.time() << " second(s)" << std::endl;
|
||||
|
|
@ -102,7 +70,6 @@ int main (int argc, char** argv)
|
|||
Label_handle ground = labels.add ("ground");
|
||||
Label_handle vegetation = labels.add ("vegetation");
|
||||
Label_handle roof = labels.add ("roof");
|
||||
Label_handle facade = labels.add ("facade");
|
||||
|
||||
Classifier classifier (labels, features);
|
||||
|
||||
|
|
@ -115,11 +82,11 @@ int main (int argc, char** argv)
|
|||
|
||||
t.reset();
|
||||
t.start();
|
||||
std::vector<std::size_t> label_indices;
|
||||
std::vector<int> label_indices(pts.size(), -1);
|
||||
Classification::classify_with_graphcut<CGAL::Sequential_tag>
|
||||
(pts, Pmap(), labels, classifier,
|
||||
(pts, pts.point_map(), labels, classifier,
|
||||
generator.neighborhood().k_neighbor_query(12),
|
||||
0.2, 10, label_indices);
|
||||
0.2, 1, label_indices);
|
||||
t.stop();
|
||||
std::cerr << "Classification with graphcut done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
|
|
@ -138,40 +105,37 @@ int main (int argc, char** argv)
|
|||
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;
|
||||
|
||||
std::ofstream f ("classification.ply");
|
||||
f.precision(18);
|
||||
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)
|
||||
|
||||
// Color point set according to class
|
||||
UCmap red = pts.add_property_map<unsigned char>("red", 0).first;
|
||||
UCmap green = pts.add_property_map<unsigned char>("green", 0).first;
|
||||
UCmap blue = pts.add_property_map<unsigned char>("blue", 0).first;
|
||||
|
||||
for (std::size_t i = 0; i < label_indices.size(); ++ i)
|
||||
{
|
||||
f << pts[i] << " ";
|
||||
|
||||
label_map[i] = label_indices[i]; // update label map with computed classification
|
||||
|
||||
Label_handle label = labels[label_indices[i]];
|
||||
|
||||
if (label == ground)
|
||||
f << "245 180 0" << std::endl;
|
||||
else if (label == vegetation)
|
||||
f << "0 255 27" << std::endl;
|
||||
else if (label == roof)
|
||||
f << "255 0 170" << std::endl;
|
||||
else if (label == facade)
|
||||
f << "128 128 128" << std::endl;
|
||||
else
|
||||
{
|
||||
f << "0 0 0" << std::endl;
|
||||
std::cerr << "Error: unknown classification label" << std::endl;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
// Author(s) : Simon Giraudot
|
||||
|
||||
#ifndef CGAL_CLASSIFICATION_EVALUATION_H
|
||||
#define CGAL_CLASSIFICATION_EVALUATION_H_
|
||||
#define CGAL_CLASSIFICATION_EVALUATION_H
|
||||
|
||||
#include <CGAL/Classification/Label.h>
|
||||
#include <CGAL/Classification/Label_set.h>
|
||||
|
|
@ -60,15 +60,16 @@ public:
|
|||
\param ground_truth vector of label indices: it should contain 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 `std::size_t(-1)`.
|
||||
should be given the value `-1`.
|
||||
|
||||
\param result similar to `ground_truth` but contained the result of
|
||||
a classification.
|
||||
|
||||
*/
|
||||
template <typename LabelIndexRange>
|
||||
Evaluation (const Label_set& labels,
|
||||
const std::vector<std::size_t>& ground_truth,
|
||||
const std::vector<std::size_t>& result)
|
||||
const LabelIndexRange& ground_truth,
|
||||
const LabelIndexRange& result)
|
||||
: m_precision (labels.size()),
|
||||
m_recall (labels.size()),
|
||||
m_iou (labels.size())
|
||||
|
|
@ -85,9 +86,9 @@ public:
|
|||
|
||||
for (std::size_t j = 0; j < ground_truth.size(); ++ j)
|
||||
{
|
||||
std::size_t gt = ground_truth[j];
|
||||
std::size_t res = result[j];
|
||||
if (gt == std::size_t(-1) || res == std::size_t(-1))
|
||||
int gt = static_cast<int>(ground_truth[j]);
|
||||
int res = static_cast<int>(result[j]);
|
||||
if (gt == -1 || res == -1)
|
||||
continue;
|
||||
++ total;
|
||||
if (gt == res)
|
||||
|
|
@ -217,4 +218,5 @@ public:
|
|||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_CLASSIFICATION_EVALUATION_H_
|
||||
#endif // CGAL_CLASSIFICATION_EVALUATION_H
|
||||
|
||||
|
|
|
|||
|
|
@ -91,9 +91,10 @@ public:
|
|||
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 `std::size_t(-1)`.
|
||||
information should be given the value `-1`.
|
||||
*/
|
||||
void train (const std::vector<std::size_t>& ground_truth)
|
||||
template <typename LabelIndexRange>
|
||||
void train (const LabelIndexRange& ground_truth)
|
||||
{
|
||||
#if (CV_MAJOR_VERSION < 3)
|
||||
if (rtree != NULL)
|
||||
|
|
@ -102,15 +103,14 @@ public:
|
|||
|
||||
std::size_t nb_samples = 0;
|
||||
for (std::size_t i = 0; i < ground_truth.size(); ++ i)
|
||||
if (ground_truth[i] != std::size_t(-1))
|
||||
if (ground_truth[i] != -1)
|
||||
++ nb_samples;
|
||||
|
||||
|
||||
cv::Mat training_features (nb_samples, m_features.size(), CV_32FC1);
|
||||
cv::Mat training_labels (nb_samples, 1, CV_32FC1);
|
||||
|
||||
for (std::size_t i = 0, index = 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)
|
||||
training_features.at<float>(index, f) = m_features[f]->value(i);
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ public:
|
|||
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 `std::size_t(-1)`.
|
||||
information should be given the value `-1`.
|
||||
|
||||
\param nb_tests number of tests to perform. Higher values may
|
||||
provide the user with better results at the cost of a higher
|
||||
|
|
@ -295,16 +295,16 @@ public:
|
|||
provided ground truth and the best classification found by the
|
||||
training set.
|
||||
*/
|
||||
template <typename ConcurrencyTag>
|
||||
float train (const std::vector<std::size_t>& ground_truth,
|
||||
template <typename ConcurrencyTag, typename LabelIndexRange>
|
||||
float train (const LabelIndexRange& ground_truth,
|
||||
unsigned int nb_tests = 300)
|
||||
{
|
||||
std::vector<std::vector<std::size_t> > training_sets (m_labels.size());
|
||||
std::size_t nb_tot = 0;
|
||||
for (std::size_t i = 0; i < ground_truth.size(); ++ i)
|
||||
if (ground_truth[i] != std::size_t(-1))
|
||||
if (ground_truth[i] != -1)
|
||||
{
|
||||
training_sets[ground_truth[i]].push_back (i);
|
||||
training_sets[std::size_t(ground_truth[i])].push_back (i);
|
||||
++ nb_tot;
|
||||
}
|
||||
|
||||
|
|
@ -486,16 +486,16 @@ public:
|
|||
/// @}
|
||||
|
||||
/// \cond SKIP_IN_MANUAL
|
||||
template <typename ConcurrencyTag>
|
||||
float train_random (const std::vector<std::size_t>& ground_truth,
|
||||
template <typename ConcurrencyTag, typename LabelIndexRange>
|
||||
float train_random (const LabelIndexRange& ground_truth,
|
||||
unsigned int nb_tests = 300)
|
||||
{
|
||||
std::vector<std::vector<std::size_t> > training_sets (m_labels.size());
|
||||
std::size_t nb_tot = 0;
|
||||
for (std::size_t i = 0; i < ground_truth.size(); ++ i)
|
||||
if (ground_truth[i] != std::size_t(-1))
|
||||
if (ground_truth[i] != -1)
|
||||
{
|
||||
training_sets[ground_truth[i]].push_back (i);
|
||||
training_sets[std::size_t(ground_truth[i])].push_back (i);
|
||||
++ nb_tot;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,18 +40,18 @@ namespace Classification {
|
|||
/// \cond SKIP_IN_MANUAL
|
||||
namespace internal {
|
||||
|
||||
template <typename Classifier>
|
||||
template <typename Classifier, typename LabelIndexRange>
|
||||
class Classify_functor
|
||||
{
|
||||
const Label_set& m_labels;
|
||||
const Classifier& m_classifier;
|
||||
std::vector<std::size_t>& m_out;
|
||||
LabelIndexRange& m_out;
|
||||
|
||||
public:
|
||||
|
||||
Classify_functor (const Label_set& labels,
|
||||
const Classifier& classifier,
|
||||
std::vector<std::size_t>& out)
|
||||
LabelIndexRange& out)
|
||||
: m_labels (labels), m_classifier (classifier), m_out (out)
|
||||
{ }
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ namespace internal {
|
|||
}
|
||||
}
|
||||
|
||||
m_out[s] = nb_class_best;
|
||||
m_out[s] = static_cast<typename LabelIndexRange::iterator::value_type>(nb_class_best);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -117,7 +117,7 @@ namespace internal {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename ItemRange, typename ItemMap, typename NeighborQuery>
|
||||
template <typename ItemRange, typename ItemMap, typename NeighborQuery, typename LabelIndexRange>
|
||||
class Classify_functor_local_smoothing
|
||||
{
|
||||
const ItemRange& m_input;
|
||||
|
|
@ -125,7 +125,7 @@ namespace internal {
|
|||
const Label_set& m_labels;
|
||||
const std::vector<std::vector<float> >& m_values;
|
||||
const NeighborQuery& m_neighbor_query;
|
||||
std::vector<std::size_t>& m_out;
|
||||
LabelIndexRange& m_out;
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ namespace internal {
|
|||
const Label_set& labels,
|
||||
const std::vector<std::vector<float> >& values,
|
||||
const NeighborQuery& neighbor_query,
|
||||
std::vector<std::size_t>& out)
|
||||
LabelIndexRange& out)
|
||||
: m_input (input), m_item_map (item_map), m_labels (labels),
|
||||
m_values(values),
|
||||
m_neighbor_query (neighbor_query),
|
||||
|
|
@ -171,14 +171,15 @@ namespace internal {
|
|||
}
|
||||
}
|
||||
|
||||
m_out[s] = nb_class_best;
|
||||
m_out[s] = static_cast<typename LabelIndexRange::iterator::value_type>(nb_class_best);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
template <typename ItemRange, typename ItemMap,
|
||||
typename Classifier, typename NeighborQuery>
|
||||
typename Classifier, typename NeighborQuery,
|
||||
typename LabelIndexRange>
|
||||
class Classify_functor_graphcut
|
||||
{
|
||||
const ItemRange& m_input;
|
||||
|
|
@ -189,7 +190,7 @@ namespace internal {
|
|||
float m_strength;
|
||||
const std::vector<std::vector<std::size_t> >& m_indices;
|
||||
const std::vector<std::pair<std::size_t, std::size_t> >& m_input_to_indices;
|
||||
std::vector<std::size_t>& m_out;
|
||||
LabelIndexRange& m_out;
|
||||
|
||||
#ifdef CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE
|
||||
typedef CGAL::internal::Alpha_expansion_graph_cut_boost Alpha_expansion;
|
||||
|
|
@ -207,7 +208,7 @@ namespace internal {
|
|||
float strength,
|
||||
const std::vector<std::vector<std::size_t> >& indices,
|
||||
const std::vector<std::pair<std::size_t, std::size_t> >& input_to_indices,
|
||||
std::vector<std::size_t>& out)
|
||||
LabelIndexRange& out)
|
||||
: m_input (input), m_item_map (item_map), m_labels (labels),
|
||||
m_classifier (classifier), m_neighbor_query (neighbor_query),
|
||||
m_strength (strength), m_indices (indices), m_input_to_indices (input_to_indices), m_out (out)
|
||||
|
|
@ -271,7 +272,7 @@ namespace internal {
|
|||
graphcut(edges, edge_weights, probability_matrix, assigned_label);
|
||||
|
||||
for (std::size_t i = 0; i < assigned_label.size(); ++ i)
|
||||
m_out[m_indices[sub][i]] = assigned_label[i];
|
||||
m_out[m_indices[sub][i]] = static_cast<typename LabelIndexRange::iterator::value_type>(assigned_label[i]);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -299,6 +300,9 @@ namespace internal {
|
|||
|
||||
\tparam Classifier model of `Classifier`.
|
||||
|
||||
\tparam Model of `Range` with random access iterators whose value
|
||||
type is an integer type.
|
||||
|
||||
\param input input range.
|
||||
\param labels set of input labels.
|
||||
\param classifier input classifier.
|
||||
|
|
@ -309,15 +313,16 @@ namespace internal {
|
|||
*/
|
||||
template <typename ConcurrencyTag,
|
||||
typename ItemRange,
|
||||
typename Classifier>
|
||||
typename Classifier,
|
||||
typename LabelIndexRange>
|
||||
void classify (const ItemRange& input,
|
||||
const Label_set& labels,
|
||||
const Classifier& classifier,
|
||||
std::vector<std::size_t>& output)
|
||||
LabelIndexRange& output)
|
||||
{
|
||||
output.resize(input.size());
|
||||
|
||||
internal::Classify_functor<Classifier>
|
||||
internal::Classify_functor<Classifier, LabelIndexRange>
|
||||
f (labels, classifier, output);
|
||||
|
||||
#ifndef CGAL_LINKED_WITH_TBB
|
||||
|
|
@ -354,6 +359,8 @@ namespace internal {
|
|||
is the type of item to classify (for example, `CGAL::Point_3`).
|
||||
\tparam NeighborQuery model of `NeighborQuery`.
|
||||
\tparam Classifier model of `Classifier`.
|
||||
\tparam Model of `Range` with random access iterators whose value
|
||||
type is an integer type.
|
||||
|
||||
\param input input range.
|
||||
\param item_map property map to access the input items.
|
||||
|
|
@ -369,13 +376,14 @@ namespace internal {
|
|||
typename ItemRange,
|
||||
typename ItemMap,
|
||||
typename NeighborQuery,
|
||||
typename Classifier>
|
||||
typename Classifier,
|
||||
typename LabelIndexRange>
|
||||
void classify_with_local_smoothing (const ItemRange& input,
|
||||
const ItemMap item_map,
|
||||
const Label_set& labels,
|
||||
const Classifier& classifier,
|
||||
const NeighborQuery& neighbor_query,
|
||||
std::vector<std::size_t>& output)
|
||||
LabelIndexRange& output)
|
||||
{
|
||||
output.resize(input.size());
|
||||
|
||||
|
|
@ -383,7 +391,7 @@ namespace internal {
|
|||
(labels.size(), std::vector<float> (input.size(), -1.));
|
||||
internal::Classify_functor_local_smoothing_preprocessing<Classifier>
|
||||
f1 (labels, classifier, values);
|
||||
internal::Classify_functor_local_smoothing<ItemRange, ItemMap, NeighborQuery>
|
||||
internal::Classify_functor_local_smoothing<ItemRange, ItemMap, NeighborQuery, LabelIndexRange>
|
||||
f2 (input, item_map, labels, values, neighbor_query, output);
|
||||
|
||||
#ifndef CGAL_LINKED_WITH_TBB
|
||||
|
|
@ -431,6 +439,8 @@ namespace internal {
|
|||
is the type of item to classify (for example, `CGAL::Point_3`).
|
||||
\tparam NeighborQuery model of `NeighborQuery`.
|
||||
\tparam Classifier model of `Classifier`.
|
||||
\tparam Model of `Range` with random access iterators whose value
|
||||
type is an integer type.
|
||||
|
||||
\param input input range.
|
||||
\param item_map property map to access the input items.
|
||||
|
|
@ -452,7 +462,8 @@ namespace internal {
|
|||
typename ItemRange,
|
||||
typename ItemMap,
|
||||
typename NeighborQuery,
|
||||
typename Classifier>
|
||||
typename Classifier,
|
||||
typename LabelIndexRange>
|
||||
void classify_with_graphcut (const ItemRange& input,
|
||||
const ItemMap item_map,
|
||||
const Label_set& labels,
|
||||
|
|
@ -460,7 +471,7 @@ namespace internal {
|
|||
const NeighborQuery& neighbor_query,
|
||||
const float strength,
|
||||
const std::size_t min_number_of_subdivisions,
|
||||
std::vector<std::size_t>& output)
|
||||
LabelIndexRange& output)
|
||||
{
|
||||
CGAL::Bbox_3 bbox = CGAL::bbox_3
|
||||
(boost::make_transform_iterator (input.begin(), CGAL::Property_map_to_unary_function<ItemMap>(item_map)),
|
||||
|
|
@ -510,9 +521,7 @@ namespace internal {
|
|||
}
|
||||
}
|
||||
|
||||
output.resize (input.size());
|
||||
|
||||
internal::Classify_functor_graphcut<ItemRange, ItemMap, Classifier, NeighborQuery>
|
||||
internal::Classify_functor_graphcut<ItemRange, ItemMap, Classifier, NeighborQuery, LabelIndexRange>
|
||||
f (input, item_map, labels, classifier, neighbor_query, strength, indices, input_to_indices, output);
|
||||
|
||||
#ifndef CGAL_LINKED_WITH_TBB
|
||||
|
|
|
|||
|
|
@ -24,51 +24,45 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n
|
|||
reset_indices();
|
||||
|
||||
backup_existing_colors_and_add_new();
|
||||
m_training = m_points->point_set()->add_property_map<std::size_t>("training", std::size_t(-1)).first;
|
||||
m_classif = m_points->point_set()->add_property_map<std::size_t>("label", std::size_t(-1)).first;
|
||||
bool training_found = false;
|
||||
boost::tie (m_training, training_found) = m_points->point_set()->add_property_map<int>("training", -1);
|
||||
bool classif_found = false;
|
||||
boost::tie (m_classif, classif_found) = m_points->point_set()->add_property_map<int>("label", -1);
|
||||
|
||||
Point_set::Property_map<int> ps_labels;
|
||||
bool found;
|
||||
boost::tie (ps_labels, found) = m_points->point_set()->property_map<int>("label");
|
||||
Point_set::Property_map<signed char> ps_labels_c;
|
||||
bool found_c;
|
||||
boost::tie (ps_labels_c, found_c) = m_points->point_set()->property_map<signed char>("label");
|
||||
if (found || found_c)
|
||||
training_found = !training_found; // add_property_map returns false if
|
||||
classif_found = !classif_found; // property was already there
|
||||
|
||||
if (training_found || classif_found)
|
||||
{
|
||||
int max = 0;
|
||||
int lmax = 0;
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
{
|
||||
int l;
|
||||
if (found) l = ps_labels[*it];
|
||||
else l = int(ps_labels_c[*it] - 1);
|
||||
|
||||
m_classif[*it] = (std::size_t)l;
|
||||
m_training[*it] = (std::size_t)l;
|
||||
if (l > max)
|
||||
if (training_found)
|
||||
{
|
||||
max = l;
|
||||
int l = m_training[*it];
|
||||
lmax = (std::max)(l, lmax);
|
||||
}
|
||||
if (classif_found)
|
||||
{
|
||||
int l = m_classif[*it];
|
||||
lmax = (std::max)(l, lmax);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < max; ++ i)
|
||||
for (int i = 0; i <= lmax; ++ i)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "label_" << i;
|
||||
m_labels.add(oss.str().c_str());
|
||||
CGAL::Classification::HSV_Color hsv;
|
||||
hsv[0] = 360. * (i / double(max));
|
||||
hsv[0] = 360. * (i / double(lmax));
|
||||
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]));
|
||||
}
|
||||
|
||||
if (found)
|
||||
m_points->point_set()->remove_property_map(ps_labels);
|
||||
else
|
||||
m_points->point_set()->remove_property_map(ps_labels_c);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -235,11 +229,11 @@ void Point_set_item_classification::change_color (int index)
|
|||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
{
|
||||
QColor color (0, 0, 0);
|
||||
std::size_t c = m_training[*it];
|
||||
std::size_t c2 = m_classif[*it];
|
||||
int c = m_training[*it];
|
||||
int c2 = m_classif[*it];
|
||||
|
||||
if (c != std::size_t(-1))
|
||||
color = m_label_colors[c];
|
||||
if (c != -1)
|
||||
color = m_label_colors[std::size_t(c)];
|
||||
|
||||
float div = 1;
|
||||
if (c != c2)
|
||||
|
|
@ -363,15 +357,16 @@ void Point_set_item_classification::train(int classifier)
|
|||
}
|
||||
reset_indices();
|
||||
|
||||
std::vector<int> training (m_points->point_set()->size(), -1);
|
||||
std::vector<std::size_t> indices (m_points->point_set()->size(), std::size_t(-1));
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
indices[*it] = m_training[*it];
|
||||
training[*it] = m_training[*it];
|
||||
|
||||
if (classifier == 0)
|
||||
{
|
||||
m_sowf->train<Concurrency_tag>(indices, m_nb_trials);
|
||||
m_sowf->train<Concurrency_tag>(training, m_nb_trials);
|
||||
CGAL::Classification::classify<Concurrency_tag> (*(m_points->point_set()),
|
||||
m_labels, *m_sowf,
|
||||
indices);
|
||||
|
|
@ -379,7 +374,7 @@ void Point_set_item_classification::train(int classifier)
|
|||
else
|
||||
{
|
||||
#ifdef CGAL_LINKED_WITH_OPENCV
|
||||
m_random_forest->train (indices);
|
||||
m_random_forest->train (training);
|
||||
CGAL::Classification::classify<Concurrency_tag> (*(m_points->point_set()),
|
||||
m_labels, *m_random_forest,
|
||||
indices);
|
||||
|
|
@ -387,7 +382,7 @@ void Point_set_item_classification::train(int classifier)
|
|||
}
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
m_classif[*it] = indices[*it];
|
||||
m_classif[*it] = int(indices[*it]);
|
||||
|
||||
if (m_index_color == 1 || m_index_color == 2)
|
||||
change_color (m_index_color);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class Point_set_item_classification : public Item_classification_base
|
|||
|
||||
void add_selection_to_training_set (const char* name)
|
||||
{
|
||||
std::size_t label = get_label (name);
|
||||
int label = int(get_label (name));
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->first_selected();
|
||||
it != m_points->point_set()->end(); ++ it)
|
||||
|
|
@ -66,7 +66,7 @@ class Point_set_item_classification : public Item_classification_base
|
|||
{
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->end(); ++ it)
|
||||
m_training[*it] = std::size_t(-1);
|
||||
m_training[*it] = -1;
|
||||
}
|
||||
void validate_selection ()
|
||||
{
|
||||
|
|
@ -116,7 +116,7 @@ class Point_set_item_classification : public Item_classification_base
|
|||
template <typename Classifier>
|
||||
bool run (int method, const Classifier& classifier)
|
||||
{
|
||||
std::vector<std::size_t> indices;
|
||||
std::vector<int> indices (m_points->point_set()->size(), std::size_t(-1));
|
||||
|
||||
if (method == 0)
|
||||
CGAL::Classification::classify<Concurrency_tag> (*(m_points->point_set()),
|
||||
|
|
@ -134,7 +134,7 @@ class Point_set_item_classification : public Item_classification_base
|
|||
m_generator->neighborhood().k_neighbor_query(12),
|
||||
m_smoothing, m_subdivisions, indices);
|
||||
|
||||
std::vector<std::size_t> ground_truth(m_points->point_set()->size(), std::size_t(-1));
|
||||
std::vector<int> ground_truth(m_points->point_set()->size(), -1);
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
{
|
||||
|
|
@ -172,8 +172,8 @@ class Point_set_item_classification : public Item_classification_base
|
|||
Point_set::Property_map<unsigned char> m_green;
|
||||
Point_set::Property_map<unsigned char> m_blue;
|
||||
Point_set::Property_map<Color> m_color;
|
||||
Point_set::Property_map<std::size_t> m_training;
|
||||
Point_set::Property_map<std::size_t> m_classif;
|
||||
Point_set::Property_map<int> m_training;
|
||||
Point_set::Property_map<int> m_classif;
|
||||
|
||||
Generator* m_generator;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue