mirror of https://github.com/CGAL/cgal
Extended labels with indices and colors
This commit is contained in:
parent
a51ce12aa5
commit
39ca0f3bf7
|
|
@ -83,7 +83,7 @@ int main (int argc, char** argv)
|
|||
std::cerr << "Computing features" << std::endl;
|
||||
Feature_set features;
|
||||
|
||||
features.begin_parallel_additions();
|
||||
features.begin_parallel_additions(); // No effect in sequential mode
|
||||
|
||||
Feature_handle distance_to_plane = features.add<Distance_to_plane> (pts, Pmap(), eigen);
|
||||
Feature_handle dispersion = features.add<Dispersion> (pts, Pmap(), grid,
|
||||
|
|
@ -91,7 +91,7 @@ int main (int argc, char** argv)
|
|||
Feature_handle elevation = features.add<Elevation> (pts, Pmap(), grid,
|
||||
radius_dtm);
|
||||
|
||||
features.end_parallel_additions();
|
||||
features.end_parallel_additions(); // No effect in sequential mode
|
||||
|
||||
//! [Features]
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
|
@ -100,9 +100,15 @@ int main (int argc, char** argv)
|
|||
//! [Labels]
|
||||
|
||||
Label_set labels;
|
||||
|
||||
// Init name only
|
||||
Label_handle ground = labels.add ("ground");
|
||||
Label_handle vegetation = labels.add ("vegetation");
|
||||
Label_handle roof = labels.add ("roof");
|
||||
|
||||
// Init name and color
|
||||
Label_handle vegetation = labels.add ("vegetation", CGAL::Color(0,255,0));
|
||||
|
||||
// Init name, Color and standard index (here, ASPRS building index)
|
||||
Label_handle roof = labels.add ("roof", CGAL::Color (255, 0, 0), 6);
|
||||
|
||||
//! [Labels]
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ typedef Classification::Point_set_feature_generator<Kernel, Point_set, Pmap>
|
|||
int main (int argc, char** argv)
|
||||
{
|
||||
std::string filename = "data/b9_training.ply";
|
||||
|
||||
|
||||
if (argc > 1)
|
||||
filename = argv[1];
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ int main (int argc, char** argv)
|
|||
|
||||
std::cerr << "Reading input" << std::endl;
|
||||
in >> pts;
|
||||
|
||||
|
||||
Imap label_map;
|
||||
bool lm_found = false;
|
||||
std::tie (label_map, lm_found) = pts.property_map<int> ("label");
|
||||
|
|
@ -57,17 +57,17 @@ int main (int argc, char** argv)
|
|||
}
|
||||
|
||||
Feature_set features;
|
||||
|
||||
|
||||
std::cerr << "Generating features" << std::endl;
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
Feature_generator generator (pts, pts.point_map(),
|
||||
5); // using 5 scales
|
||||
|
||||
|
||||
features.begin_parallel_additions();
|
||||
generator.generate_point_based_features (features);
|
||||
features.end_parallel_additions();
|
||||
|
||||
|
||||
t.stop();
|
||||
std::cerr << "Done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
|
|
@ -78,10 +78,10 @@ int main (int argc, char** argv)
|
|||
Label_handle roof = labels.add ("roof");
|
||||
|
||||
std::vector<int> label_indices(pts.size(), -1);
|
||||
|
||||
|
||||
std::cerr << "Using ETHZ Random Forest Classifier" << std::endl;
|
||||
Classification::ETHZ::Random_forest_classifier classifier (labels, features);
|
||||
|
||||
|
||||
std::cerr << "Training" << std::endl;
|
||||
t.reset();
|
||||
t.start();
|
||||
|
|
@ -96,7 +96,7 @@ int main (int argc, char** argv)
|
|||
generator.neighborhood().k_neighbor_query(12),
|
||||
0.2f, 1, label_indices);
|
||||
t.stop();
|
||||
|
||||
|
||||
std::cerr << "Classification with graphcut done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
std::cerr << "Precision, recall, F1 scores and IoU:" << std::endl;
|
||||
|
|
@ -123,21 +123,12 @@ int main (int argc, char** argv)
|
|||
for (std::size_t i = 0; i < label_indices.size(); ++ i)
|
||||
{
|
||||
label_map[i] = label_indices[i]; // update label map with computed classification
|
||||
|
||||
Label_handle label = labels[label_indices[i]];
|
||||
|
||||
if (label == ground)
|
||||
{
|
||||
red[i] = 245; green[i] = 180; blue[i] = 0;
|
||||
}
|
||||
else if (label == vegetation)
|
||||
{
|
||||
red[i] = 0; green[i] = 255; blue[i] = 27;
|
||||
}
|
||||
else if (label == roof)
|
||||
{
|
||||
red[i] = 255; green[i] = 0; blue[i] = 170;
|
||||
}
|
||||
Label_handle label = labels[label_indices[i]];
|
||||
const CGAL::Color& color = label->color();
|
||||
red[i] = color.red();
|
||||
green[i] = color.green();
|
||||
blue[i] = color.blue();
|
||||
}
|
||||
|
||||
// Save configuration for later use
|
||||
|
|
@ -150,6 +141,6 @@ int main (int argc, char** argv)
|
|||
f << pts;
|
||||
|
||||
std::cerr << "All done" << std::endl;
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ typedef Classification::Point_set_feature_generator<Kernel, Point_set, Pmap>
|
|||
int main (int argc, char** argv)
|
||||
{
|
||||
std::string filename = "data/b9_training.ply";
|
||||
|
||||
|
||||
if (argc > 1)
|
||||
filename = argv[1];
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ int main (int argc, char** argv)
|
|||
|
||||
std::cerr << "Reading input" << std::endl;
|
||||
in >> pts;
|
||||
|
||||
|
||||
Imap label_map;
|
||||
bool lm_found = false;
|
||||
std::tie (label_map, lm_found) = pts.property_map<int> ("label");
|
||||
|
|
@ -57,7 +57,7 @@ int main (int argc, char** argv)
|
|||
}
|
||||
|
||||
Feature_set features;
|
||||
|
||||
|
||||
std::cerr << "Generating features" << std::endl;
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
|
|
@ -67,7 +67,7 @@ int main (int argc, char** argv)
|
|||
features.begin_parallel_additions();
|
||||
generator.generate_point_based_features (features);
|
||||
features.end_parallel_additions();
|
||||
|
||||
|
||||
t.stop();
|
||||
std::cerr << "Done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
|
|
@ -78,10 +78,10 @@ int main (int argc, char** argv)
|
|||
Label_handle roof = labels.add ("roof");
|
||||
|
||||
std::vector<int> label_indices(pts.size(), -1);
|
||||
|
||||
|
||||
std::cerr << "Using OpenCV Random Forest Classifier" << std::endl;
|
||||
Classification::OpenCV::Random_forest_classifier classifier (labels, features);
|
||||
|
||||
|
||||
std::cerr << "Training" << std::endl;
|
||||
t.reset();
|
||||
t.start();
|
||||
|
|
@ -96,12 +96,12 @@ int main (int argc, char** argv)
|
|||
generator.neighborhood().k_neighbor_query(12),
|
||||
0.2f, 1, label_indices);
|
||||
t.stop();
|
||||
|
||||
|
||||
std::cerr << "Classification with graphcut done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
std::cerr << "Precision, recall, F1 scores and IoU:" << std::endl;
|
||||
Classification::Evaluation evaluation (labels, pts.range(label_map), label_indices);
|
||||
|
||||
|
||||
for (Label_handle l : labels)
|
||||
{
|
||||
std::cerr << " * " << l->name() << ": "
|
||||
|
|
@ -123,21 +123,12 @@ int main (int argc, char** argv)
|
|||
for (std::size_t i = 0; i < label_indices.size(); ++ i)
|
||||
{
|
||||
label_map[i] = label_indices[i]; // update label map with computed classification
|
||||
|
||||
Label_handle label = labels[label_indices[i]];
|
||||
|
||||
if (label == ground)
|
||||
{
|
||||
red[i] = 245; green[i] = 180; blue[i] = 0;
|
||||
}
|
||||
else if (label == vegetation)
|
||||
{
|
||||
red[i] = 0; green[i] = 255; blue[i] = 27;
|
||||
}
|
||||
else if (label == roof)
|
||||
{
|
||||
red[i] = 255; green[i] = 0; blue[i] = 170;
|
||||
}
|
||||
Label_handle label = labels[label_indices[i]];
|
||||
const CGAL::Color& color = label->color();
|
||||
red[i] = color.red();
|
||||
green[i] = color.green();
|
||||
blue[i] = color.blue();
|
||||
}
|
||||
|
||||
// Write result
|
||||
|
|
@ -146,6 +137,6 @@ int main (int argc, char** argv)
|
|||
f << pts;
|
||||
|
||||
std::cerr << "All done" << std::endl;
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ typedef Classification::Point_set_feature_generator<Kernel, Point_set, Pmap>
|
|||
int main (int argc, char** argv)
|
||||
{
|
||||
std::string filename = "data/b9_training.ply";
|
||||
|
||||
|
||||
if (argc > 1)
|
||||
filename = argv[1];
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ int main (int argc, char** argv)
|
|||
|
||||
std::cerr << "Reading input" << std::endl;
|
||||
in >> pts;
|
||||
|
||||
|
||||
Imap label_map;
|
||||
bool lm_found = false;
|
||||
std::tie (label_map, lm_found) = pts.property_map<int> ("label");
|
||||
|
|
@ -57,17 +57,17 @@ int main (int argc, char** argv)
|
|||
}
|
||||
|
||||
Feature_set features;
|
||||
|
||||
|
||||
std::cerr << "Generating features" << std::endl;
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
Feature_generator generator (pts, pts.point_map(),
|
||||
5); // using 5 scales
|
||||
|
||||
|
||||
features.begin_parallel_additions();
|
||||
generator.generate_point_based_features (features);
|
||||
features.end_parallel_additions();
|
||||
|
||||
|
||||
t.stop();
|
||||
std::cerr << "Done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
|
|
@ -78,10 +78,10 @@ int main (int argc, char** argv)
|
|||
Label_handle roof = labels.add ("roof");
|
||||
|
||||
std::vector<int> label_indices(pts.size(), -1);
|
||||
|
||||
|
||||
std::cerr << "Using TensorFlow neural network Classifier" << std::endl;
|
||||
Classification::TensorFlow::Neural_network_classifier<> classifier (labels, features);
|
||||
|
||||
|
||||
std::cerr << "Training" << std::endl;
|
||||
t.reset();
|
||||
t.start();
|
||||
|
|
@ -98,12 +98,12 @@ int main (int argc, char** argv)
|
|||
generator.neighborhood().k_neighbor_query(12),
|
||||
0.2f, 1, label_indices);
|
||||
t.stop();
|
||||
|
||||
|
||||
std::cerr << "Classification with graphcut done in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
std::cerr << "Precision, recall, F1 scores and IoU:" << std::endl;
|
||||
Classification::Evaluation evaluation (labels, pts.range(ground_truth), label_indices);
|
||||
|
||||
|
||||
for (Label_handle l : labels)
|
||||
{
|
||||
std::cerr << " * " << l->name() << ": "
|
||||
|
|
@ -125,21 +125,12 @@ int main (int argc, char** argv)
|
|||
for (std::size_t i = 0; i < label_indices.size(); ++ i)
|
||||
{
|
||||
label_map[i] = label_indices[i]; // update label map with computed classification
|
||||
|
||||
Label_handle label = labels[label_indices[i]];
|
||||
|
||||
if (label == ground)
|
||||
{
|
||||
red[i] = 245; green[i] = 180; blue[i] = 0;
|
||||
}
|
||||
else if (label == vegetation)
|
||||
{
|
||||
red[i] = 0; green[i] = 255; blue[i] = 27;
|
||||
}
|
||||
else if (label == roof)
|
||||
{
|
||||
red[i] = 255; green[i] = 0; blue[i] = 170;
|
||||
}
|
||||
Label_handle label = labels[label_indices[i]];
|
||||
const CGAL::Color& color = label->color();
|
||||
red[i] = color.red();
|
||||
green[i] = color.green();
|
||||
blue[i] = color.blue();
|
||||
}
|
||||
|
||||
// Write result
|
||||
|
|
@ -148,6 +139,6 @@ int main (int argc, char** argv)
|
|||
f << pts;
|
||||
|
||||
std::cerr << "All done" << std::endl;
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ namespace Classification {
|
|||
class Evaluation
|
||||
{
|
||||
const Label_set& m_labels;
|
||||
mutable std::map<Label_handle, std::size_t> m_map_labels;
|
||||
std::vector<std::vector<std::size_t> > m_confusion; // confusion matrix
|
||||
|
||||
public:
|
||||
|
|
@ -56,7 +55,7 @@ public:
|
|||
{
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
|
||||
\brief Instantiates an evaluation object and computes all
|
||||
|
|
@ -86,9 +85,6 @@ public:
|
|||
/// \cond SKIP_IN_MANUAL
|
||||
void init()
|
||||
{
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
m_map_labels[m_labels[i]] = i;
|
||||
|
||||
m_confusion.resize (m_labels.size());
|
||||
for (std::size_t i = 0; i < m_confusion.size(); ++ i)
|
||||
m_confusion[i].resize (m_labels.size(), 0);
|
||||
|
|
@ -103,7 +99,7 @@ public:
|
|||
}
|
||||
/// \endcond
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief Append more items to the evaluation object.
|
||||
|
||||
|
|
@ -129,11 +125,11 @@ public:
|
|||
int res = static_cast<int>(get<1>(p));
|
||||
if (gt == -1 || res == -1)
|
||||
continue;
|
||||
|
||||
|
||||
++ m_confusion[std::size_t(res)][std::size_t(gt)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Label Evaluation
|
||||
|
|
@ -149,17 +145,17 @@ public:
|
|||
*/
|
||||
float precision (Label_handle label) const
|
||||
{
|
||||
std::size_t idx = m_map_labels[label];
|
||||
std::size_t idx = label->index();
|
||||
if (!label_has_ground_truth(idx))
|
||||
return std::numeric_limits<float>::quiet_NaN();
|
||||
|
||||
|
||||
std::size_t total = 0;
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
total += m_confusion[idx][i];
|
||||
|
||||
if (total == 0)
|
||||
return 0.f;
|
||||
|
||||
|
||||
return m_confusion[idx][idx] / float(total);
|
||||
}
|
||||
|
||||
|
|
@ -173,10 +169,10 @@ public:
|
|||
*/
|
||||
float recall (Label_handle label) const
|
||||
{
|
||||
std::size_t idx = m_map_labels[label];
|
||||
std::size_t idx = label->index();
|
||||
if (!label_has_ground_truth(idx))
|
||||
return std::numeric_limits<float>::quiet_NaN();
|
||||
|
||||
|
||||
std::size_t total = 0;
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
total += m_confusion[i][idx];
|
||||
|
|
@ -201,7 +197,7 @@ public:
|
|||
|
||||
if (p == 0.f && r == 0.f)
|
||||
return 0.f;
|
||||
|
||||
|
||||
return 2.f * p * r / (p + r);
|
||||
}
|
||||
|
||||
|
|
@ -215,8 +211,8 @@ public:
|
|||
*/
|
||||
float intersection_over_union (Label_handle label) const
|
||||
{
|
||||
std::size_t idx = m_map_labels[label];
|
||||
|
||||
std::size_t idx = label->index();
|
||||
|
||||
std::size_t total = 0;
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
{
|
||||
|
|
@ -229,7 +225,7 @@ public:
|
|||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Global Evaluation
|
||||
/// @{
|
||||
|
||||
|
|
@ -239,11 +235,11 @@ public:
|
|||
*/
|
||||
std::size_t confusion (Label_handle ground_truth, Label_handle result)
|
||||
{
|
||||
std::size_t idx_gt = m_map_labels[ground_truth];
|
||||
std::size_t idx_r = m_map_labels[result];
|
||||
std::size_t idx_gt = ground_truth->index();
|
||||
std::size_t idx_r = result->index();
|
||||
return m_confusion[idx_gt][idx_r];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Returns the number of misclassified items.
|
||||
*/
|
||||
|
|
@ -287,7 +283,7 @@ public:
|
|||
}
|
||||
return true_positives / float(total);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Returns the mean \f$F_1\f$ score of the training over all
|
||||
labels (see `f1_score()`).
|
||||
|
|
@ -304,7 +300,7 @@ public:
|
|||
}
|
||||
return mean / nb;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Returns the mean intersection over union of the training
|
||||
over all labels (see `intersection_over_union()`).
|
||||
|
|
@ -329,7 +325,7 @@ public:
|
|||
|
||||
/// \name Output Formatting Functions
|
||||
/// @{
|
||||
|
||||
|
||||
/*!
|
||||
\brief Outputs the evaluation in a simple ASCII format to the stream `os`.
|
||||
*/
|
||||
|
|
@ -387,7 +383,7 @@ public:
|
|||
<< "</ul>" << std::endl;
|
||||
|
||||
const Label_set& labels = evaluation.m_labels;
|
||||
|
||||
|
||||
os << "<h2>Detailed Results</h2>" << std::endl
|
||||
<< "<table>" << std::endl
|
||||
<< " <tr>" << std::endl
|
||||
|
|
@ -414,7 +410,7 @@ public:
|
|||
<< " <td></td>" << std::endl
|
||||
<< " <td></td>" << std::endl
|
||||
<< " </tr>" << std::endl;
|
||||
|
||||
|
||||
os << "</table>" << std::endl;
|
||||
|
||||
os << "<h2>Confusion Matrix</h2>" << std::endl
|
||||
|
|
@ -444,7 +440,7 @@ public:
|
|||
os << " <td><strong>" << sum << "</strong></td>" << std::endl;
|
||||
os << " </tr>" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
os << " <tr>" << std::endl
|
||||
<< " <td><strong>GROUND TRUTH</strong></td>" << std::endl;
|
||||
std::size_t total = 0;
|
||||
|
|
@ -461,18 +457,17 @@ href=\"https://doc.cgal.org/latest/Classification/index.html\">CGAL \
|
|||
Classification package</a>.</em></p>" << std::endl
|
||||
<< "</body>" << std::endl
|
||||
<< "</html>" << std::endl;
|
||||
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace Classification
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_CLASSIFICATION_EVALUATION_H
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#define CGAL_CLASSIFICATION_LABEL_H
|
||||
|
||||
#include <CGAL/license/Classification.h>
|
||||
#include <CGAL/IO/Color.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -20,6 +21,10 @@ namespace CGAL {
|
|||
|
||||
namespace Classification {
|
||||
|
||||
/// \cond SKIP_IN_MANUAL
|
||||
class Label_set;
|
||||
/// \endcond
|
||||
|
||||
/*!
|
||||
\ingroup PkgClassificationLabel
|
||||
|
||||
|
|
@ -32,19 +37,56 @@ class Label
|
|||
private:
|
||||
|
||||
std::string m_name;
|
||||
std::size_t m_index;
|
||||
std::size_t m_standard_index;
|
||||
CGAL::Color m_color;
|
||||
|
||||
friend Label_set;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
\param name name of the classification label (e.g. vegetation).
|
||||
*/
|
||||
Label (std::string name) : m_name (name) { }
|
||||
/// \cond SKIP_IN_MANUAL
|
||||
// Undocumented: Labels should be created by the set
|
||||
Label (std::string name, std::size_t index, std::size_t standard_index,
|
||||
const CGAL::Color& color)
|
||||
: m_name (name), m_index (index), m_standard_index (standard_index)
|
||||
, m_color (color)
|
||||
{ }
|
||||
/// \endcond
|
||||
|
||||
/*!
|
||||
returns the name of the classification label (e.g. vegetation).
|
||||
*/
|
||||
const std::string& name() const { return m_name; }
|
||||
|
||||
/// \cond SKIP_IN_MANUAL
|
||||
void set_name (const std::string& name) { m_name = name; }
|
||||
/// \endcond
|
||||
|
||||
/*!
|
||||
returns the index of the classification label in the label set.
|
||||
|
||||
\note This index cannot be changed by the user and is handled directly by the label set.
|
||||
*/
|
||||
std::size_t index() const { return m_index; }
|
||||
|
||||
/*!
|
||||
returns the standard index of the classification label (i.e. index in the ASPRS standard).
|
||||
|
||||
\note This index is purely user-oriented and is not used by the classification algorithms.
|
||||
*/
|
||||
std::size_t standard_index() const { return m_standard_index; }
|
||||
|
||||
void set_standard_index(std::size_t idx) { m_standard_index = idx; }
|
||||
|
||||
/*!
|
||||
returns the color used to represent the label.
|
||||
|
||||
\note The color is purely user-oriented and is not used by the
|
||||
classification algorithms. It is not to be confused with a color
|
||||
attribute embedded in a data set which _can_ be used (see
|
||||
`Color_channel`).
|
||||
*/
|
||||
const CGAL::Color& color() const { return m_color; }
|
||||
void set_color (const Color& color) { m_color = color; }
|
||||
};
|
||||
|
||||
#ifdef DOXYGEN_RUNNING
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include <CGAL/Classification/Label.h>
|
||||
|
||||
#include <CGAL/Random.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace CGAL {
|
||||
|
|
@ -32,6 +34,8 @@ algorithms.
|
|||
class Label_set
|
||||
{
|
||||
using Base = std::vector<Label_handle>;
|
||||
|
||||
CGAL::Random m_random;
|
||||
Base m_labels;
|
||||
|
||||
public:
|
||||
|
|
@ -52,14 +56,69 @@ public:
|
|||
Label_set(std::initializer_list<const char*> labels)
|
||||
{
|
||||
for (const char* l : labels)
|
||||
m_labels.push_back (std::make_shared<Classification::Label>(l));
|
||||
add (l);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Adds a label.
|
||||
|
||||
\note Names, standard indices and colors are not used for
|
||||
identification: two labels in the same set can have the same name,
|
||||
standard index or color, but not the same handle. Each call to
|
||||
`add()` generates a new distinct label.
|
||||
|
||||
\param name name of the label.
|
||||
|
||||
\param color used to represent the label.
|
||||
|
||||
\param standard_index standard index of the classification label
|
||||
(i.e. index in the ASPRS standard).
|
||||
|
||||
\return a handle to the newly added label.
|
||||
*/
|
||||
Label_handle add (const char* name,
|
||||
CGAL::Color color,
|
||||
std::size_t standard_index = -1)
|
||||
{
|
||||
Label_handle out = std::make_shared<Classification::Label>
|
||||
(name, m_labels.size(), standard_index, color);
|
||||
m_labels.push_back (out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Adds a label with default standard index and color.
|
||||
|
||||
This functions tries to map label names to standard ASPRS labels
|
||||
and automatically picks the `standard_index` and `color` of the
|
||||
label:
|
||||
|
||||
- \"unassigned\" is given standard index 2 and color `(0, 0, 0)`
|
||||
- \"ground\" is given standard index 2 and color `(186, 189, 182)`
|
||||
- \"low_vegetation\" is given standard index 3 and color `(78, 154, 6)`
|
||||
- \"medium_vegetation\" is given standard index 4 and color `(138, 226, 52)`
|
||||
- \"high_vegetation\" is given standard index 5 and color `(204, 255, 201)`
|
||||
- \"building\" is given standard index 6 and color `(245, 121, 0)`
|
||||
- \"noise\" is given standard index 7 and color `(128, 0, 0)`
|
||||
- \"reserved\" is given standard index 8 and color `(233, 185, 110)`
|
||||
- \"water\" is given standard index 9 and color `(114, 159, 207)`
|
||||
- \"rail\" is given standard index 10 and color `(136, 46, 25)`
|
||||
- \"road_surface\" is given standard index 11 and color `(56, 56, 56)`
|
||||
- \"reserved_2\" is given standard index 12 and color `(193, 138, 51)`
|
||||
- \"wire_guard\" is given standard index 13 and color `(37, 61, 136)`
|
||||
- \"wire_conductor\" is given standard index 14 and color `(173, 127, 168)`
|
||||
- \"transmission_tower\" is given standard index 15 and color `(136, 138, 133)`
|
||||
- \"wire_connect\" is given standard index 16 and color `(145, 64, 236)`
|
||||
- \"bridge_deck\" is given standard index 17 and color `(213, 93, 93)`
|
||||
- \"high_noise\" is given standard index 18 and color `(255, 0, 0)`
|
||||
|
||||
If the name is not found, the label is given standard index
|
||||
`std::size_t(-1)` and a random color.
|
||||
|
||||
\note Names are not used for identification: two labels in the
|
||||
same set can have the same name (but not the same handle).
|
||||
same set can have the same name but not the same handle. Each call
|
||||
to `add()` generates a new distinct label.
|
||||
|
||||
\param name name of the label.
|
||||
|
||||
|
|
@ -67,10 +126,77 @@ public:
|
|||
*/
|
||||
Label_handle add (const char* name)
|
||||
{
|
||||
Label_handle out = std::make_shared<Classification::Label> (name);
|
||||
m_labels.push_back (out);
|
||||
return out;
|
||||
static std::unordered_map<std::string, std::pair<std::size_t, CGAL::Color> > init_map;
|
||||
if (init_map.empty())
|
||||
{
|
||||
init_map.insert (std::make_pair ("unassigned",
|
||||
std::make_pair (2, CGAL::Color (0, 0, 0))));
|
||||
init_map.insert (std::make_pair ("ground",
|
||||
std::make_pair (2, CGAL::Color (186, 189, 182))));
|
||||
init_map.insert (std::make_pair ("low_vegetation",
|
||||
std::make_pair (3, CGAL::Color (78, 154, 6))));
|
||||
init_map.insert (std::make_pair ("medium_vegetation",
|
||||
std::make_pair (4, CGAL::Color (138, 226, 52))));
|
||||
init_map.insert (std::make_pair ("high_vegetation",
|
||||
std::make_pair (5, CGAL::Color (204, 255, 201))));
|
||||
init_map.insert (std::make_pair ("building",
|
||||
std::make_pair (6, CGAL::Color (245, 121, 0))));
|
||||
init_map.insert (std::make_pair ("noise",
|
||||
std::make_pair (7, CGAL::Color (128, 0, 0))));
|
||||
init_map.insert (std::make_pair ("reserved",
|
||||
std::make_pair (8, CGAL::Color (233, 185, 110))));
|
||||
init_map.insert (std::make_pair ("water",
|
||||
std::make_pair (9, CGAL::Color (114, 159, 207))));
|
||||
init_map.insert (std::make_pair ("rail",
|
||||
std::make_pair (10, CGAL::Color (136, 46, 25))));
|
||||
init_map.insert (std::make_pair ("road_surface",
|
||||
std::make_pair (11, CGAL::Color (56, 56, 56))));
|
||||
init_map.insert (std::make_pair ("reserved_2",
|
||||
std::make_pair (12, CGAL::Color (193, 138, 51))));
|
||||
init_map.insert (std::make_pair ("wire_guard",
|
||||
std::make_pair (13, CGAL::Color (37, 61, 136))));
|
||||
init_map.insert (std::make_pair ("wire_conductor",
|
||||
std::make_pair (14, CGAL::Color (173, 127, 168))));
|
||||
init_map.insert (std::make_pair ("wire_conduct",
|
||||
std::make_pair (14, CGAL::Color (173, 127, 168))));
|
||||
init_map.insert (std::make_pair ("transmission_tower",
|
||||
std::make_pair (15, CGAL::Color (136, 138, 133))));
|
||||
init_map.insert (std::make_pair ("trans_tower",
|
||||
std::make_pair (15, CGAL::Color (136, 138, 133))));
|
||||
init_map.insert (std::make_pair ("wire_connect",
|
||||
std::make_pair (16, CGAL::Color (145, 64, 236))));
|
||||
init_map.insert (std::make_pair ("bridge_deck",
|
||||
std::make_pair (17, CGAL::Color (213, 93, 93))));
|
||||
init_map.insert (std::make_pair ("high_noise",
|
||||
std::make_pair (18, CGAL::Color (255, 0, 0))));
|
||||
|
||||
// Undocumented additions
|
||||
init_map.insert (std::make_pair ("low_veget",
|
||||
std::make_pair (3, CGAL::Color (78, 154, 6))));
|
||||
init_map.insert (std::make_pair ("medium_veget",
|
||||
std::make_pair (4, CGAL::Color (138, 226, 52))));
|
||||
init_map.insert (std::make_pair ("vegetation",
|
||||
std::make_pair (4, CGAL::Color (138, 226, 52))));
|
||||
init_map.insert (std::make_pair ("high_veget",
|
||||
std::make_pair (5, CGAL::Color (204, 255, 201))));
|
||||
init_map.insert (std::make_pair ("roof",
|
||||
std::make_pair (6, CGAL::Color (245, 121, 0))));
|
||||
init_map.insert (std::make_pair ("facade",
|
||||
std::make_pair (-1, CGAL::Color (77, 131, 186))));
|
||||
}
|
||||
|
||||
std::string sname (name);
|
||||
auto found = init_map.find (sname);
|
||||
if (found == init_map.end())
|
||||
return add (name,
|
||||
CGAL::Color ((unsigned char)(m_random.get_int(64, 192)),
|
||||
(unsigned char)(m_random.get_int(64, 192)),
|
||||
(unsigned char)(m_random.get_int(64, 192))));
|
||||
|
||||
// else
|
||||
return add (name, found->second.second, found->second.first);
|
||||
}
|
||||
/// \endcond
|
||||
|
||||
/*!
|
||||
\brief Removes a label.
|
||||
|
|
@ -82,17 +208,14 @@ public:
|
|||
*/
|
||||
bool remove (Label_handle label)
|
||||
{
|
||||
std::size_t idx = (std::size_t)(-1);
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
if (m_labels[i] == label)
|
||||
{
|
||||
m_labels.erase (m_labels.begin() + i);
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
if (idx == (std::size_t)(-1))
|
||||
if (label->index() >= m_labels.size()
|
||||
|| m_labels[label->index()] != label)
|
||||
return false;
|
||||
|
||||
for (std::size_t i = label->index() + 1; i < m_labels.size(); ++ i)
|
||||
m_labels[i]->m_index --;
|
||||
m_labels.erase (m_labels.begin() + label->index());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +240,6 @@ public:
|
|||
return m_labels[i];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Removes all labels.
|
||||
*/
|
||||
|
|
@ -125,8 +247,6 @@ public:
|
|||
{
|
||||
m_labels.clear();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -34,19 +34,7 @@
|
|||
|
||||
#include <CGAL/bounding_box.h>
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/xml_parser.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/demangle.h>
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
#include <tbb/task_group.h>
|
||||
#include <mutex>
|
||||
#endif // CGAL_LINKED_WITH_TBB
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
|
|||
|
|
@ -34,14 +34,7 @@
|
|||
#include <CGAL/Classification/Feature_set.h>
|
||||
#include <CGAL/bounding_box.h>
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/xml_parser.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/demangle.h>
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po
|
|||
bool classif_found = false;
|
||||
boost::tie (m_classif, classif_found) = m_points->point_set()->add_property_map<int>("label", -1);
|
||||
|
||||
training_found = !training_found; // add_property_map returns false if
|
||||
training_found = !training_found; // add_property_map returns false if
|
||||
classif_found = !classif_found; // property was already there
|
||||
|
||||
bool las_found = false;
|
||||
|
|
@ -76,11 +76,11 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po
|
|||
training_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (training_found || classif_found)
|
||||
{
|
||||
std::vector<int> used_indices;
|
||||
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
{
|
||||
|
|
@ -122,12 +122,12 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po
|
|||
++ current_idx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
{
|
||||
int c = m_cluster_id[*it];
|
||||
|
||||
|
||||
if (training_found)
|
||||
{
|
||||
if (std::size_t(current_idx) != used_indices.size()) // Empty indices -> reorder indices in point set
|
||||
|
|
@ -153,7 +153,7 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po
|
|||
m_clusters[c].label() = m_classif[*it];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::map<int, std::string> label_names;
|
||||
if (las_found) // Use LAS standard
|
||||
{
|
||||
|
|
@ -196,7 +196,7 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < used_indices.size(); ++ i)
|
||||
{
|
||||
if (used_indices[i] == -1)
|
||||
|
|
@ -213,8 +213,6 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po
|
|||
oss << "label_" << i;
|
||||
new_label = m_labels.add(oss.str().c_str());
|
||||
}
|
||||
|
||||
m_label_colors.push_back (this->get_new_label_color (new_label->name()));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -223,11 +221,8 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po
|
|||
m_labels.add("vegetation");
|
||||
m_labels.add("roof");
|
||||
m_labels.add("facade");
|
||||
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
m_label_colors.push_back (this->get_new_label_color (m_labels[i]->name()));
|
||||
}
|
||||
|
||||
|
||||
update_comments_of_point_set_item();
|
||||
|
||||
m_sowf = new Sum_of_weighted_features (m_labels, m_features);
|
||||
|
|
@ -256,7 +251,7 @@ Cluster_classification::Cluster_classification(Scene_points_with_normal_item* po
|
|||
m_cluster_id)));
|
||||
|
||||
std::set<std::pair<int, int> > adjacencies;
|
||||
|
||||
|
||||
for (Delaunay::Finite_edges_iterator it = dt.finite_edges_begin();
|
||||
it != dt.finite_edges_end(); ++ it)
|
||||
{
|
||||
|
|
@ -315,13 +310,13 @@ Cluster_classification::~Cluster_classification()
|
|||
m_classif[*it] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For LAS saving, convert classification info in the LAS standard
|
||||
// if (m_input_is_las)
|
||||
{
|
||||
Point_set::Property_map<unsigned char> las_classif
|
||||
= m_points->point_set()->add_property_map<unsigned char>("classification", 0).first;
|
||||
|
||||
|
||||
std::vector<unsigned char> label_indices;
|
||||
|
||||
unsigned char custom = 19;
|
||||
|
|
@ -372,14 +367,14 @@ Cluster_classification::~Cluster_classification()
|
|||
unsigned char lc = 1; // unclassified in LAS standard
|
||||
if (c != -1)
|
||||
lc = label_indices[std::size_t(c)];
|
||||
|
||||
|
||||
las_classif[*it] = lc;
|
||||
|
||||
int t = m_training[*it];
|
||||
unsigned char lt = 1; // unclassified in LAS standard
|
||||
if (t != -1)
|
||||
lt = label_indices[std::size_t(t)];
|
||||
|
||||
|
||||
m_training[*it] = int(lt);
|
||||
}
|
||||
|
||||
|
|
@ -406,7 +401,7 @@ void Cluster_classification::backup_existing_colors_and_add_new()
|
|||
|
||||
m_points->point_set()->remove_colors();
|
||||
}
|
||||
|
||||
|
||||
m_points->point_set()->add_colors();
|
||||
}
|
||||
|
||||
|
|
@ -419,7 +414,7 @@ void Cluster_classification::reset_colors()
|
|||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
m_points->point_set()->set_color(*it, m_color[*it]);
|
||||
|
||||
|
||||
m_points->point_set()->remove_property_map(m_color);
|
||||
}
|
||||
}
|
||||
|
|
@ -429,19 +424,19 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax)
|
|||
m_index_color = index;
|
||||
|
||||
int index_color = real_index_color();
|
||||
|
||||
|
||||
// Colors
|
||||
static Color_ramp ramp;
|
||||
ramp.build_rainbow();
|
||||
reset_indices();
|
||||
|
||||
|
||||
if (index_color == -1) // item color
|
||||
m_points->point_set()->remove_colors();
|
||||
else
|
||||
{
|
||||
if (!m_points->point_set()->has_colors())
|
||||
m_points->point_set()->add_colors();
|
||||
|
||||
|
||||
if (index_color == 0) // real colors
|
||||
{
|
||||
|
||||
|
|
@ -459,11 +454,11 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax)
|
|||
if (cid != -1)
|
||||
{
|
||||
std::size_t c = m_clusters[cid].label();
|
||||
|
||||
|
||||
if (c != std::size_t(-1))
|
||||
color = m_label_colors[c];
|
||||
color = label_qcolor (m_labels[std::size_t(c)]);
|
||||
}
|
||||
|
||||
|
||||
m_points->point_set()->set_color(*it, color);
|
||||
}
|
||||
}
|
||||
|
|
@ -475,18 +470,18 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax)
|
|||
QColor color (0, 0, 0);
|
||||
int cid = m_cluster_id[*it];
|
||||
float div = 1;
|
||||
|
||||
|
||||
if (cid != -1)
|
||||
{
|
||||
int c = m_clusters[cid].training();
|
||||
int c2 = m_clusters[cid].label();
|
||||
|
||||
|
||||
if (c != -1)
|
||||
color = m_label_colors[std::size_t(c)];
|
||||
|
||||
color = label_qcolor (m_labels[std::size_t(c)]);
|
||||
|
||||
if (c != c2)
|
||||
div = 2;
|
||||
}
|
||||
}
|
||||
m_points->point_set()->set_color(*it, color.red() / div, color.green() / div, color.blue() / div);
|
||||
}
|
||||
}
|
||||
|
|
@ -496,7 +491,7 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax)
|
|||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
{
|
||||
int cid = m_cluster_id[*it];
|
||||
|
||||
|
||||
if (cid != -1)
|
||||
{
|
||||
srand(cid);
|
||||
|
|
@ -549,7 +544,7 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax)
|
|||
|
||||
float min = std::numeric_limits<float>::max();
|
||||
float max = -std::numeric_limits<float>::max();
|
||||
|
||||
|
||||
if (vmin != NULL && vmax != NULL
|
||||
&& *vmin != std::numeric_limits<float>::infinity()
|
||||
&& *vmax != std::numeric_limits<float>::infinity())
|
||||
|
|
@ -572,7 +567,7 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
{
|
||||
|
|
@ -582,7 +577,7 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax)
|
|||
float v = (feature->value(cid) - min) / (max - min);
|
||||
if (v < 0.f) v = 0.f;
|
||||
if (v > 1.f) v = 1.f;
|
||||
|
||||
|
||||
m_points->point_set()->set_color(*it, ramp.r(v) * 255, ramp.g(v) * 255, ramp.b(v) * 255);
|
||||
}
|
||||
else
|
||||
|
|
@ -597,7 +592,7 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->first_selected();
|
||||
it != m_points->point_set()->end(); ++ it)
|
||||
m_points->point_set()->set_color(*it, 255, 0, 0);
|
||||
|
|
@ -606,7 +601,7 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax)
|
|||
int Cluster_classification::real_index_color() const
|
||||
{
|
||||
int out = m_index_color;
|
||||
|
||||
|
||||
if (out == 0 && m_color == Point_set::Property_map<CGAL::Color>())
|
||||
out = -1;
|
||||
return out;
|
||||
|
|
@ -629,7 +624,7 @@ void Cluster_classification::compute_features (std::size_t nb_scales, float voxe
|
|||
CGAL_assertion (!(m_points->point_set()->empty()));
|
||||
|
||||
reset_indices();
|
||||
|
||||
|
||||
std::cerr << "Computing pointwise features with " << nb_scales << " scale(s) and ";
|
||||
if (voxel_size == -1)
|
||||
std::cerr << "automatic voxel size" << std::endl;
|
||||
|
|
@ -642,9 +637,9 @@ void Cluster_classification::compute_features (std::size_t nb_scales, float voxe
|
|||
bool normals = m_points->point_set()->has_normal_map();
|
||||
if (normals)
|
||||
normal_map = m_points->point_set()->normal_map();
|
||||
|
||||
|
||||
bool colors = (m_color != Point_set::Property_map<CGAL::Color>());
|
||||
|
||||
|
||||
Point_set::Property_map<boost::uint8_t> echo_map;
|
||||
bool echo;
|
||||
boost::tie (echo_map, echo) = m_points->point_set()->template property_map<boost::uint8_t>("echo");
|
||||
|
|
@ -654,10 +649,10 @@ void Cluster_classification::compute_features (std::size_t nb_scales, float voxe
|
|||
Feature_set pointwise_features;
|
||||
|
||||
Generator generator (*(m_points->point_set()), m_points->point_set()->point_map(), nb_scales, voxel_size);
|
||||
|
||||
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
pointwise_features.begin_parallel_additions();
|
||||
#endif
|
||||
|
|
@ -669,11 +664,11 @@ void Cluster_classification::compute_features (std::size_t nb_scales, float voxe
|
|||
generator.generate_color_based_features (pointwise_features, m_color);
|
||||
if (echo)
|
||||
generator.generate_echo_based_features (pointwise_features, echo_map);
|
||||
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
pointwise_features.end_parallel_additions();
|
||||
#endif
|
||||
|
||||
|
||||
add_remaining_point_set_properties_as_features(pointwise_features);
|
||||
|
||||
t.stop();
|
||||
|
|
@ -692,29 +687,29 @@ void Cluster_classification::compute_features (std::size_t nb_scales, float voxe
|
|||
m_features.template add<Mean_of_feature> (m_clusters,
|
||||
pointwise_features[i]);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
m_features.end_parallel_additions();
|
||||
m_features.begin_parallel_additions();
|
||||
#endif
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < pointwise_features.size(); ++ i)
|
||||
{
|
||||
m_features.template add<Variance_of_feature> (m_clusters,
|
||||
pointwise_features[i],
|
||||
m_features[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
add_cluster_features();
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
m_features.end_parallel_additions();
|
||||
#endif
|
||||
|
||||
|
||||
t.stop();
|
||||
std::cerr << m_features.size() << " feature(s) computed in " << t.time() << " second(s)" << std::endl;
|
||||
|
||||
|
||||
|
||||
delete m_sowf;
|
||||
m_sowf = new Sum_of_weighted_features (m_labels, m_features);
|
||||
if (m_ethz != NULL)
|
||||
|
|
@ -756,7 +751,7 @@ void Cluster_classification::select_random_region()
|
|||
selected.push_back (*it);
|
||||
else
|
||||
unselected.push_back (*it);
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < unselected.size(); ++ i)
|
||||
*(m_points->point_set()->begin() + i) = unselected[i];
|
||||
for (std::size_t i = 0; i < selected.size(); ++ i)
|
||||
|
|
@ -764,13 +759,13 @@ void Cluster_classification::select_random_region()
|
|||
|
||||
m_points->point_set()->set_first_selected
|
||||
(m_points->point_set()->begin() + unselected.size());
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Cluster_classification::add_remaining_point_set_properties_as_features(Feature_set& feature_set)
|
||||
{
|
||||
const std::vector<std::string>& prop = m_points->point_set()->base().properties();
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < prop.size(); ++ i)
|
||||
{
|
||||
if (prop[i] == "index" ||
|
||||
|
|
@ -823,7 +818,7 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d
|
|||
|
||||
std::vector<std::size_t> nb_label (m_labels.size(), 0);
|
||||
std::size_t nb_total = 0;
|
||||
|
||||
|
||||
std::vector<int> training;
|
||||
training.reserve (m_clusters.size());
|
||||
for (std::size_t i = 0; i < m_clusters.size(); ++ i)
|
||||
|
|
@ -835,12 +830,12 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d
|
|||
++ nb_total;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::cerr << nb_total << " cluster(s) used for training ("
|
||||
<< 100. * (nb_total / double(m_clusters.size())) << "% of the total):" << std::endl;
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
std::cerr << " * " << m_labels[i]->name() << ": " << nb_label[i] << " clusters(s)" << std::endl;
|
||||
|
||||
|
||||
std::vector<int> indices (m_clusters.size(), -1);
|
||||
|
||||
if (classifier == CGAL_CLASSIFICATION_SOWF_NUMBER)
|
||||
|
|
@ -908,14 +903,14 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d
|
|||
while (iss >> s)
|
||||
hidden_layers.push_back (std::size_t(s));
|
||||
}
|
||||
|
||||
|
||||
m_neural_network->train (training,
|
||||
dialog.get<QCheckBox>("restart")->isChecked(),
|
||||
dialog.get<QSpinBox>("trials")->value(),
|
||||
dialog.get<DoubleEdit>("learning_rate")->value(),
|
||||
dialog.get<QSpinBox>("batch_size")->value(),
|
||||
hidden_layers);
|
||||
|
||||
|
||||
CGAL::Classification::classify<Concurrency_tag> (m_clusters,
|
||||
m_labels, *m_neural_network,
|
||||
indices, m_label_probabilities);
|
||||
|
|
@ -924,7 +919,7 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d
|
|||
|
||||
for (std::size_t i = 0; i < m_clusters.size(); ++ i)
|
||||
m_clusters[i].label() = indices[i];
|
||||
|
||||
|
||||
if (m_index_color == 1 || m_index_color == 2)
|
||||
change_color (m_index_color);
|
||||
}
|
||||
|
|
@ -973,7 +968,6 @@ bool Cluster_classification::run (int method, int classifier,
|
|||
run (method, *m_neural_network, subdivisions, smoothing);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ class Cluster_classification : public Item_classification_base
|
|||
= new Scene_points_with_normal_item;
|
||||
|
||||
points_item->setName (QString("%1 (%2)").arg(name).arg(m_labels[label]->name().c_str()));
|
||||
points_item->setColor (m_label_colors[label]);
|
||||
points_item->setColor (label_qcolor (m_labels[label]));
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->end(); ++ it)
|
||||
{
|
||||
|
|
@ -231,7 +231,7 @@ class Cluster_classification : public Item_classification_base
|
|||
{
|
||||
points_item[i] = new Scene_points_with_normal_item;
|
||||
points_item[i]->setName (QString("%1 (%2)").arg(name).arg(m_labels[i]->name().c_str()));
|
||||
points_item[i]->setColor (m_label_colors[i]);
|
||||
points_item[i]->setColor (label_qcolor (m_labels[i]));
|
||||
items.push_back (points_item[i]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ public:
|
|||
#ifdef CGAL_LINKED_WITH_TENSORFLOW
|
||||
typedef CGAL::Classification::TensorFlow::Neural_network_classifier<> Neural_network;
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
Item_classification_base() { }
|
||||
virtual ~Item_classification_base() { }
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ public:
|
|||
virtual void compute_features (std::size_t nb_scales, float voxel_size) = 0;
|
||||
|
||||
virtual std::string feature_statistics () const { return std::string(); }
|
||||
|
||||
|
||||
virtual void add_selection_to_training_set (std::size_t label) = 0;
|
||||
virtual void reset_training_set (std::size_t label) = 0;
|
||||
virtual void reset_training_set_of_selection() = 0;
|
||||
|
|
@ -76,7 +76,7 @@ public:
|
|||
virtual void validate_selection () = 0;
|
||||
virtual void train(int classifier, const QMultipleInputDialog&) = 0;
|
||||
virtual bool run (int method, int classifier, std::size_t subdivisions, double smoothing) = 0;
|
||||
|
||||
|
||||
virtual void update_color () = 0;
|
||||
virtual void change_color (int index, float* vmin = NULL, float* vmax = NULL) = 0;
|
||||
virtual CGAL::Three::Scene_item* generate_one_item (const char* name,
|
||||
|
|
@ -85,19 +85,23 @@ public:
|
|||
const char* name) const = 0;
|
||||
|
||||
bool features_computed() const { return (m_features.size() != 0); }
|
||||
std::size_t number_of_features() const { return m_features.size(); }
|
||||
std::size_t number_of_features() const { return m_features.size(); }
|
||||
Feature_handle feature(std::size_t i) { return m_features[i]; }
|
||||
float weight (Feature_handle f) const { return m_sowf->weight(f); }
|
||||
void set_weight (Feature_handle f, float w) const { m_sowf->set_weight(f,w); }
|
||||
Sum_of_weighted_features::Effect effect (Label_handle l, Feature_handle f) const { return m_sowf->effect(l,f); }
|
||||
void set_effect (Label_handle l, Feature_handle f, Sum_of_weighted_features::Effect e)
|
||||
{ m_sowf->set_effect (l, f, e); }
|
||||
|
||||
|
||||
QColor label_qcolor (Label_handle l) const
|
||||
{
|
||||
return QColor (l->color().red(), l->color().green(), l->color().blue());
|
||||
}
|
||||
|
||||
virtual QColor add_new_label (const char* name)
|
||||
{
|
||||
m_labels.add(name);
|
||||
m_label_colors.push_back (get_new_label_color (name));
|
||||
|
||||
|
||||
delete m_sowf;
|
||||
m_sowf = new Sum_of_weighted_features (m_labels, m_features);
|
||||
|
||||
|
|
@ -113,13 +117,12 @@ public:
|
|||
delete m_neural_network;
|
||||
m_neural_network = new Neural_network (m_labels, m_features);
|
||||
#endif
|
||||
|
||||
return m_label_colors.back();
|
||||
|
||||
return label_qcolor (m_labels[m_labels.size() - 1]);
|
||||
}
|
||||
virtual void remove_label (std::size_t position)
|
||||
{
|
||||
m_labels.remove(m_labels[position]);
|
||||
m_label_colors.erase (m_label_colors.begin() + position);
|
||||
|
||||
delete m_sowf;
|
||||
m_sowf = new Sum_of_weighted_features (m_labels, m_features);
|
||||
|
|
@ -137,11 +140,10 @@ public:
|
|||
m_neural_network = new Neural_network (m_labels, m_features);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
virtual void clear_labels ()
|
||||
{
|
||||
m_labels.clear();
|
||||
m_label_colors.clear();
|
||||
|
||||
delete m_sowf;
|
||||
m_sowf = new Sum_of_weighted_features (m_labels, m_features);
|
||||
|
|
@ -256,69 +258,24 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const QColor& label_color(std::size_t i) const { return m_label_colors[i]; }
|
||||
QColor label_color(std::size_t i) const
|
||||
{
|
||||
return label_qcolor (m_labels[i]);
|
||||
}
|
||||
void change_label_color (std::size_t position, const QColor& color)
|
||||
{
|
||||
m_label_colors[position] = color;
|
||||
m_labels[position]->set_color
|
||||
(CGAL::Color (color.red(), color.green(), color.blue()));
|
||||
}
|
||||
void change_label_name (std::size_t position, const std::string& name)
|
||||
{
|
||||
m_labels[position]->set_name (name);
|
||||
}
|
||||
|
||||
QColor get_new_label_color (const std::string& name)
|
||||
{
|
||||
QColor color (64 + rand() % 192,
|
||||
64 + rand() % 192,
|
||||
64 + rand() % 192);
|
||||
|
||||
if (name == "ground")
|
||||
color = QColor (186, 189, 182);
|
||||
else if (name == "low_veget")
|
||||
color = QColor (78, 154, 6);
|
||||
else if (name == "med_veget"
|
||||
|| name == "vegetation")
|
||||
color = QColor (138, 226, 52);
|
||||
else if (name == "high_veget")
|
||||
color = QColor (204, 255, 201);
|
||||
else if (name == "building"
|
||||
|| name == "roof")
|
||||
color = QColor (245, 121, 0);
|
||||
else if (name == "noise")
|
||||
color = QColor (0, 0, 0);
|
||||
else if (name == "reserved")
|
||||
color = QColor (233, 185, 110);
|
||||
else if (name == "water")
|
||||
color = QColor (114, 159, 207);
|
||||
else if (name == "rail")
|
||||
color = QColor (136, 46, 25);
|
||||
else if (name == "road_surface")
|
||||
color = QColor (56, 56, 56);
|
||||
else if (name == "reserved_2")
|
||||
color = QColor (193, 138, 51);
|
||||
else if (name == "wire_guard")
|
||||
color = QColor (37, 61, 136);
|
||||
else if (name == "wire_conduct")
|
||||
color = QColor (173, 127, 168);
|
||||
else if (name == "trans_tower")
|
||||
color = QColor (136, 138, 133);
|
||||
else if (name == "wire_connect")
|
||||
color = QColor (145, 64, 236);
|
||||
else if (name == "bridge_deck")
|
||||
color = QColor (213, 93, 93);
|
||||
else if (name == "high_noise")
|
||||
color = QColor (255, 0, 0);
|
||||
else if (name == "facade")
|
||||
color = QColor (77, 131, 186);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Label_set m_labels;
|
||||
Feature_set m_features;
|
||||
std::vector<QColor> m_label_colors;
|
||||
Sum_of_weighted_features* m_sowf;
|
||||
ETHZ_random_forest* m_ethz;
|
||||
#ifdef CGAL_LINKED_WITH_OPENCV
|
||||
|
|
@ -327,7 +284,7 @@ protected:
|
|||
#ifdef CGAL_LINKED_WITH_TENSORFLOW
|
||||
Neural_network* m_neural_network;
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n
|
|||
bool classif_found = false;
|
||||
boost::tie (m_classif, classif_found) = m_points->point_set()->add_property_map<int>("label", -1);
|
||||
|
||||
training_found = !training_found; // add_property_map returns false if
|
||||
training_found = !training_found; // add_property_map returns false if
|
||||
classif_found = !classif_found; // property was already there
|
||||
|
||||
bool las_found = false;
|
||||
|
|
@ -73,11 +73,11 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n
|
|||
training_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (training_found || classif_found)
|
||||
{
|
||||
std::vector<int> used_indices;
|
||||
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
{
|
||||
|
|
@ -140,7 +140,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::map<int, std::string> label_names;
|
||||
if (las_found) // Use LAS standard
|
||||
{
|
||||
|
|
@ -183,7 +183,7 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < used_indices.size(); ++ i)
|
||||
{
|
||||
if (used_indices[i] == -1)
|
||||
|
|
@ -200,8 +200,6 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n
|
|||
oss << "label_" << i;
|
||||
new_label = m_labels.add(oss.str().c_str());
|
||||
}
|
||||
|
||||
m_label_colors.push_back (this->get_new_label_color (new_label->name()));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -210,11 +208,8 @@ Point_set_item_classification::Point_set_item_classification(Scene_points_with_n
|
|||
m_labels.add("vegetation");
|
||||
m_labels.add("roof");
|
||||
m_labels.add("facade");
|
||||
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
m_label_colors.push_back (this->get_new_label_color (m_labels[i]->name()));
|
||||
}
|
||||
|
||||
|
||||
update_comments_of_point_set_item();
|
||||
|
||||
m_sowf = new Sum_of_weighted_features (m_labels, m_features);
|
||||
|
|
@ -257,7 +252,7 @@ Point_set_item_classification::~Point_set_item_classification()
|
|||
{
|
||||
Point_set::Property_map<unsigned char> las_classif
|
||||
= m_points->point_set()->add_property_map<unsigned char>("classification", 0).first;
|
||||
|
||||
|
||||
std::vector<unsigned char> label_indices;
|
||||
|
||||
unsigned char custom = 19;
|
||||
|
|
@ -308,14 +303,14 @@ Point_set_item_classification::~Point_set_item_classification()
|
|||
unsigned char lc = 1; // unclassified in LAS standard
|
||||
if (c != -1)
|
||||
lc = label_indices[std::size_t(c)];
|
||||
|
||||
|
||||
las_classif[*it] = lc;
|
||||
|
||||
int t = m_training[*it];
|
||||
unsigned char lt = 1; // unclassified in LAS standard
|
||||
if (t != -1)
|
||||
lt = label_indices[std::size_t(t)];
|
||||
|
||||
|
||||
m_training[*it] = int(lt);
|
||||
}
|
||||
|
||||
|
|
@ -365,19 +360,19 @@ void Point_set_item_classification::change_color (int index, float* vmin, float*
|
|||
m_index_color = index;
|
||||
|
||||
int index_color = real_index_color();
|
||||
|
||||
|
||||
// Colors
|
||||
static Color_ramp ramp;
|
||||
ramp.build_rainbow();
|
||||
reset_indices();
|
||||
|
||||
|
||||
if (index_color == -1) // item color
|
||||
m_points->point_set()->remove_colors();
|
||||
else
|
||||
{
|
||||
if (!m_points->point_set()->has_colors())
|
||||
m_points->point_set()->add_colors();
|
||||
|
||||
|
||||
if (index_color == 0) // real colors
|
||||
{
|
||||
|
||||
|
|
@ -392,9 +387,9 @@ void Point_set_item_classification::change_color (int index, float* vmin, float*
|
|||
{
|
||||
QColor color (0, 0, 0);
|
||||
std::size_t c = m_classif[*it];
|
||||
|
||||
|
||||
if (c != std::size_t(-1))
|
||||
color = m_label_colors[c];
|
||||
color = label_qcolor (m_labels[c]);
|
||||
|
||||
m_points->point_set()->set_color(*it, color);
|
||||
}
|
||||
|
|
@ -407,10 +402,10 @@ void Point_set_item_classification::change_color (int index, float* vmin, float*
|
|||
QColor color (0, 0, 0);
|
||||
int c = m_training[*it];
|
||||
int c2 = m_classif[*it];
|
||||
|
||||
|
||||
if (c != -1)
|
||||
color = m_label_colors[std::size_t(c)];
|
||||
|
||||
color = label_qcolor (m_labels[std::size_t(c)]);
|
||||
|
||||
float div = 1;
|
||||
if (c != c2)
|
||||
div = 2;
|
||||
|
|
@ -449,7 +444,7 @@ void Point_set_item_classification::change_color (int index, float* vmin, float*
|
|||
return;
|
||||
}
|
||||
Feature_handle feature = m_features[corrected_index];
|
||||
|
||||
|
||||
float min = std::numeric_limits<float>::max();
|
||||
float max = -std::numeric_limits<float>::max();
|
||||
|
||||
|
|
@ -477,7 +472,7 @@ void Point_set_item_classification::change_color (int index, float* vmin, float*
|
|||
float v = (feature->value(*it) - min) / (max - min);
|
||||
if (v < 0.f) v = 0.f;
|
||||
if (v > 1.f) v = 1.f;
|
||||
|
||||
|
||||
m_points->point_set()->set_color(*it, ramp.r(v) * 255, ramp.g(v) * 255, ramp.b(v) * 255);
|
||||
}
|
||||
|
||||
|
|
@ -489,7 +484,7 @@ void Point_set_item_classification::change_color (int index, float* vmin, float*
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->first_selected();
|
||||
it != m_points->point_set()->end(); ++ it)
|
||||
m_points->point_set()->set_color(*it, 255, 0, 0);
|
||||
|
|
@ -498,7 +493,7 @@ void Point_set_item_classification::change_color (int index, float* vmin, float*
|
|||
int Point_set_item_classification::real_index_color() const
|
||||
{
|
||||
int out = m_index_color;
|
||||
|
||||
|
||||
if (out == 0 && m_color == Point_set::Property_map<CGAL::Color>())
|
||||
out = -1;
|
||||
return out;
|
||||
|
|
@ -524,7 +519,7 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales, flo
|
|||
delete m_generator;
|
||||
|
||||
reset_indices();
|
||||
|
||||
|
||||
std::cerr << "Computing features with " << nb_scales << " scale(s) and ";
|
||||
if (voxel_size == -1)
|
||||
std::cerr << "automatic voxel size" << std::endl;
|
||||
|
|
@ -537,9 +532,9 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales, flo
|
|||
bool normals = m_points->point_set()->has_normal_map();
|
||||
if (normals)
|
||||
normal_map = m_points->point_set()->normal_map();
|
||||
|
||||
|
||||
bool colors = (m_color != Point_set::Property_map<CGAL::Color>());
|
||||
|
||||
|
||||
Point_set::Property_map<boost::uint8_t> echo_map;
|
||||
bool echo;
|
||||
boost::tie (echo_map, echo) = m_points->point_set()->template property_map<boost::uint8_t>("echo");
|
||||
|
|
@ -550,7 +545,7 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales, flo
|
|||
|
||||
CGAL::Real_timer t;
|
||||
t.start();
|
||||
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
m_features.begin_parallel_additions();
|
||||
#endif
|
||||
|
|
@ -562,7 +557,7 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales, flo
|
|||
m_generator->generate_color_based_features (m_features, m_color);
|
||||
if (echo)
|
||||
m_generator->generate_echo_based_features (m_features, echo_map);
|
||||
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
m_features.end_parallel_additions();
|
||||
#endif
|
||||
|
|
@ -635,7 +630,7 @@ void Point_set_item_classification::select_random_region()
|
|||
current_idx ++;
|
||||
else
|
||||
unselected.push_back (*it);
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -651,7 +646,7 @@ void Point_set_item_classification::select_random_region()
|
|||
else
|
||||
unselected.push_back (*it);
|
||||
}
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < unselected.size(); ++ i)
|
||||
*(m_points->point_set()->begin() + i) = unselected[i];
|
||||
for (std::size_t i = 0; i < selected.size(); ++ i)
|
||||
|
|
@ -665,7 +660,7 @@ void Point_set_item_classification::select_random_region()
|
|||
void Point_set_item_classification::add_remaining_point_set_properties_as_features()
|
||||
{
|
||||
const std::vector<std::string>& prop = m_points->point_set()->base().properties();
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < prop.size(); ++ i)
|
||||
{
|
||||
if (prop[i] == "index" ||
|
||||
|
|
@ -715,13 +710,13 @@ void Point_set_item_classification::train(int classifier, const QMultipleInputDi
|
|||
m_label_probabilities.resize (m_labels.size());
|
||||
for (std::size_t i = 0; i < m_label_probabilities.size(); ++ i)
|
||||
m_label_probabilities[i].resize (m_points->point_set()->size(), -1);
|
||||
|
||||
|
||||
std::vector<int> training (m_points->point_set()->size(), -1);
|
||||
std::vector<int> indices (m_points->point_set()->size(), -1);
|
||||
|
||||
std::vector<std::size_t> nb_label (m_labels.size(), 0);
|
||||
std::size_t nb_total = 0;
|
||||
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
{
|
||||
|
|
@ -803,24 +798,24 @@ void Point_set_item_classification::train(int classifier, const QMultipleInputDi
|
|||
while (iss >> s)
|
||||
hidden_layers.push_back (std::size_t(s));
|
||||
}
|
||||
|
||||
|
||||
m_neural_network->train (training,
|
||||
dialog.get<QCheckBox>("restart")->isChecked(),
|
||||
dialog.get<QSpinBox>("trials")->value(),
|
||||
dialog.get<DoubleEdit>("learning_rate")->value(),
|
||||
dialog.get<QSpinBox>("batch_size")->value(),
|
||||
hidden_layers);
|
||||
|
||||
|
||||
CGAL::Classification::classify<Concurrency_tag> (*(m_points->point_set()),
|
||||
m_labels, *m_neural_network,
|
||||
indices, m_label_probabilities);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->first_selected(); ++ it)
|
||||
m_classif[*it] = indices[*it];
|
||||
|
||||
|
||||
if (m_index_color == 1 || m_index_color == 2)
|
||||
change_color (m_index_color);
|
||||
}
|
||||
|
|
@ -869,7 +864,6 @@ bool Point_set_item_classification::run (int method, int classifier,
|
|||
run (method, *m_neural_network, subdivisions, smoothing);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,8 @@ class Point_set_item_classification : public Item_classification_base
|
|||
= new Scene_points_with_normal_item;
|
||||
|
||||
points_item->setName (QString("%1 (%2)").arg(name).arg(m_labels[label]->name().c_str()));
|
||||
points_item->setColor (m_label_colors[label]);
|
||||
points_item->setColor (label_qcolor (m_labels[label]));
|
||||
|
||||
for (Point_set::const_iterator it = m_points->point_set()->begin();
|
||||
it != m_points->point_set()->end(); ++ it)
|
||||
{
|
||||
|
|
@ -243,7 +244,7 @@ class Point_set_item_classification : public Item_classification_base
|
|||
{
|
||||
points_item[i] = new Scene_points_with_normal_item;
|
||||
points_item[i]->setName (QString("%1 (%2)").arg(name).arg(m_labels[i]->name().c_str()));
|
||||
points_item[i]->setColor (m_label_colors[i]);
|
||||
points_item[i]->setColor (label_qcolor (m_labels[i]));
|
||||
items.push_back (points_item[i]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,10 +28,7 @@ Surface_mesh_item_classification::Surface_mesh_item_classification(Scene_surface
|
|||
m_labels.add("vegetation");
|
||||
m_labels.add("roof");
|
||||
m_labels.add("facade");
|
||||
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
m_label_colors.push_back (this->get_new_label_color (m_labels[i]->name()));
|
||||
|
||||
|
||||
m_sowf = new Sum_of_weighted_features (m_labels, m_features);
|
||||
m_ethz = NULL;
|
||||
#ifdef CGAL_LINKED_WITH_OPENCV
|
||||
|
|
@ -106,9 +103,9 @@ void Surface_mesh_item_classification::change_color (int index, float* vmin, flo
|
|||
{
|
||||
QColor color (128, 128, 128);
|
||||
std::size_t c = m_classif[fd];
|
||||
|
||||
|
||||
if (c != std::size_t(-1))
|
||||
color = m_label_colors[c];
|
||||
color = label_qcolor (m_labels[c]);
|
||||
|
||||
m_color[fd] = CGAL::Color(color.red(), color.green(), color.blue());
|
||||
}
|
||||
|
|
@ -120,10 +117,10 @@ void Surface_mesh_item_classification::change_color (int index, float* vmin, flo
|
|||
QColor color (128, 128, 128);
|
||||
std::size_t c = m_training[fd];
|
||||
std::size_t c2 = m_classif[fd];
|
||||
|
||||
|
||||
if (c != std::size_t(-1))
|
||||
color = m_label_colors[c];
|
||||
|
||||
color = label_qcolor(m_labels[c]);
|
||||
|
||||
float div = 1;
|
||||
if (c != c2)
|
||||
div = 2;
|
||||
|
|
@ -166,12 +163,12 @@ void Surface_mesh_item_classification::change_color (int index, float* vmin, flo
|
|||
std::cerr << "Error: trying to access feature " << corrected_index << " out of " << m_features.size() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Feature_handle feature = m_features[corrected_index];
|
||||
|
||||
float min = std::numeric_limits<float>::max();
|
||||
float max = -std::numeric_limits<float>::max();
|
||||
|
||||
|
||||
if (vmin != NULL && vmax != NULL
|
||||
&& *vmin != std::numeric_limits<float>::infinity()
|
||||
&& *vmax != std::numeric_limits<float>::infinity())
|
||||
|
|
@ -189,18 +186,18 @@ void Surface_mesh_item_classification::change_color (int index, float* vmin, flo
|
|||
min = feature->value(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(face_descriptor fd : faces(*(m_mesh->polyhedron())))
|
||||
{
|
||||
float v = (feature->value(fd) - min) / (max - min);
|
||||
if (v < 0.f) v = 0.f;
|
||||
if (v > 1.f) v = 1.f;
|
||||
|
||||
|
||||
m_color[fd] = CGAL::Color((unsigned char)(ramp.r(v) * 255),
|
||||
(unsigned char)(ramp.g(v) * 255),
|
||||
(unsigned char)(ramp.b(v) * 255));
|
||||
}
|
||||
|
||||
|
||||
if (vmin != NULL && vmax != NULL)
|
||||
{
|
||||
*vmin = min;
|
||||
|
|
@ -217,16 +214,16 @@ void Surface_mesh_item_classification::compute_features (std::size_t nb_scales,
|
|||
std::cerr << "automatic voxel size" << std::endl;
|
||||
else
|
||||
std::cerr << "voxel size = " << voxel_size << std::endl;
|
||||
|
||||
|
||||
m_features.clear();
|
||||
|
||||
if (m_generator != NULL)
|
||||
delete m_generator;
|
||||
|
||||
Face_center_map fc_map (m_mesh->polyhedron());
|
||||
|
||||
|
||||
m_generator = new Generator (*(m_mesh->polyhedron()), fc_map, nb_scales, voxel_size);
|
||||
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
m_features.begin_parallel_additions();
|
||||
#endif
|
||||
|
|
@ -237,7 +234,7 @@ void Surface_mesh_item_classification::compute_features (std::size_t nb_scales,
|
|||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
m_features.end_parallel_additions();
|
||||
#endif
|
||||
|
||||
|
||||
delete m_sowf;
|
||||
m_sowf = new Sum_of_weighted_features (m_labels, m_features);
|
||||
if (m_ethz != NULL)
|
||||
|
|
@ -280,7 +277,7 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp
|
|||
|
||||
std::vector<std::size_t> nb_label (m_labels.size(), 0);
|
||||
std::size_t nb_total = 0;
|
||||
|
||||
|
||||
for(face_descriptor fd : faces(*(m_mesh->polyhedron())))
|
||||
{
|
||||
training[fd] = m_training[fd];
|
||||
|
|
@ -290,12 +287,12 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp
|
|||
++ nb_total;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::cerr << nb_total << " face(s) used for training ("
|
||||
<< 100. * (nb_total / double(m_mesh->polyhedron()->faces().size())) << "% of the total):" << std::endl;
|
||||
for (std::size_t i = 0; i < m_labels.size(); ++ i)
|
||||
std::cerr << " * " << m_labels[i]->name() << ": " << nb_label[i] << " face(s)" << std::endl;
|
||||
|
||||
|
||||
if (classifier == CGAL_CLASSIFICATION_SOWF_NUMBER)
|
||||
{
|
||||
m_sowf->train<Concurrency_tag>(training, dialog.get<QSpinBox>("trials")->value());
|
||||
|
|
@ -362,14 +359,14 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp
|
|||
while (iss >> s)
|
||||
hidden_layers.push_back (std::size_t(s));
|
||||
}
|
||||
|
||||
|
||||
m_neural_network->train (training,
|
||||
dialog.get<QCheckBox>("restart")->isChecked(),
|
||||
dialog.get<QSpinBox>("trials")->value(),
|
||||
dialog.get<DoubleEdit>("learning_rate")->value(),
|
||||
dialog.get<QSpinBox>("batch_size")->value(),
|
||||
hidden_layers);
|
||||
|
||||
|
||||
CGAL::Classification::classify<Concurrency_tag> (m_mesh->polyhedron()->faces(),
|
||||
m_labels, *m_neural_network,
|
||||
indices, m_label_probabilities);
|
||||
|
|
@ -425,6 +422,6 @@ bool Surface_mesh_item_classification::run (int method, int classifier,
|
|||
run (method, *m_neural_network, subdivisions, smoothing);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue