1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
#if defined (_MSC_VER) && !defined (_WIN64)
#pragma warning(disable:4244) // boost::number_distance::distance()
// converts 64 to 32 bits integers
#endif
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <boost/iterator/function_output_iterator.hpp>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Classification.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Point_set_3/IO.h>
#include <CGAL/jet_estimate_normals.h>
#include <CGAL/Shape_detection/Region_growing.h>
#include <CGAL/Real_timer.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
typedef Kernel::Iso_cuboid_3 Iso_cuboid_3;
typedef CGAL::Point_set_3<Point> Point_set;
typedef Point_set::Point_map Pmap;
typedef Point_set::Vector_map Vmap;
typedef Point_set::Property_map<int> Imap;
typedef Point_set::Property_map<unsigned char> UCmap;
typedef CGAL::Shape_detection::Point_set::Sphere_neighbor_query_for_point_set<Point_set> Neighbor_query;
typedef CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region_for_point_set<Point_set> Region_type;
typedef CGAL::Shape_detection::Region_growing<Neighbor_query, Region_type> Region_growing;
namespace Classification = CGAL::Classification;
namespace Feature = CGAL::Classification::Feature;
typedef Classification::Label_handle Label_handle;
typedef Classification::Feature_handle Feature_handle;
typedef Classification::Label_set Label_set;
typedef Classification::Feature_set Feature_set;
typedef Classification::Local_eigen_analysis Local_eigen_analysis;
typedef Classification::Point_set_feature_generator<Kernel, Point_set, Pmap> Feature_generator;
typedef Classification::Cluster<Point_set, Pmap> Cluster;
int main (int argc, char** argv)
{
std::string filename = CGAL::data_file_path("points_3/b9.ply");
std::string filename_config = "data/b9_clusters_config.bin";
if (argc > 1)
filename = argv[1];
if (argc > 2)
filename_config = argv[2];
std::cerr << "Reading input" << std::endl;
Point_set pts;
if(!(CGAL::IO::read_point_set(filename, pts,
// the PLY reader expects a binary file by default
CGAL::parameters::use_binary_mode(true))))
{
std::cerr << "Error: cannot read " << filename << std::endl;
return EXIT_FAILURE;
}
std::cerr << "Estimating normals" << std::endl;
CGAL::Real_timer t;
t.start();
pts.add_normal_map();
CGAL::jet_estimate_normals<CGAL::Parallel_if_available_tag> (pts, 12);
t.stop();
std::cerr << "Done in " << t.time() << " second(s)" << std::endl;
t.reset();
Feature_set pointwise_features;
std::cerr << "Generating pointwise features" << std::endl;
t.start();
Feature_generator generator (pts, pts.point_map(), 5); // using 5 scales
#ifdef CGAL_LINKED_WITH_TBB
pointwise_features.begin_parallel_additions();
#endif
generator.generate_point_based_features (pointwise_features);
// Generator should only be used with variables defined at the scope
// of the generator object, thus we instantiate the normal map
// outside of the function
Vmap normal_map = pts.normal_map();
generator.generate_normal_based_features (pointwise_features, normal_map);
#ifdef CGAL_LINKED_WITH_TBB
pointwise_features.end_parallel_additions();
#endif
t.stop();
std::cerr << "Done in " << t.time() << " second(s)" << std::endl;
///////////////////////////////////////////////////////////////////
//! [Cluster]
std::cerr << "Detecting planes and creating clusters" << std::endl;
t.start();
const double search_sphere_radius = 1.0;
const double max_distance_to_plane = 1.0;
const double max_accepted_angle = 25.0;
const std::size_t min_region_size = 10;
Neighbor_query neighbor_query = CGAL::Shape_detection::Point_set::make_sphere_neighbor_query (
pts, CGAL::parameters::sphere_radius(search_sphere_radius)
.point_map(pts.point_map()));
Region_type region_type = CGAL::Shape_detection::Point_set::make_least_squares_plane_fit_region(
pts, CGAL::parameters::maximum_distance(max_distance_to_plane)
.maximum_angle(max_accepted_angle)
.minimum_region_size(min_region_size));
Region_growing region_growing (
pts, neighbor_query, region_type);
std::vector<Cluster> clusters;
region_growing.detect
(boost::make_function_output_iterator
([&](const std::pair<Kernel::Plane_3, std::vector<Point_set::Index>>& region) -> void {
// Create a new cluster.
Classification::Cluster<Point_set, Pmap> cluster (pts, pts.point_map());
for (Point_set::Index idx : region.second)
cluster.insert(idx);
clusters.push_back(cluster);
}));
t.stop();
std::cerr << clusters.size() << " clusters created in "
<< t.time() << " second(s)" << std::endl;
t.reset();
//! [Cluster]
///////////////////////////////////////////////////////////////////
std::cerr << "Computing cluster features" << std::endl;
///////////////////////////////////////////////////////////////////
//! [Eigen]
Local_eigen_analysis eigen = Local_eigen_analysis::create_from_point_clusters (clusters);
//! [Eigen]
///////////////////////////////////////////////////////////////////
t.start();
///////////////////////////////////////////////////////////////////
//! [Features]
Feature_set features;
// First, compute means of features.
features.begin_parallel_additions();
for (std::size_t i = 0; i < pointwise_features.size(); ++ i)
features.add<Feature::Cluster_mean_of_feature> (clusters, pointwise_features[i]);
features.end_parallel_additions();
// Then, compute variances of features (and remaining cluster features).
features.begin_parallel_additions();
for (std::size_t i = 0; i < pointwise_features.size(); ++ i)
features.add<Feature::Cluster_variance_of_feature> (clusters,
pointwise_features[i], // i^th feature
features[i]); // mean of i^th feature
features.add<Feature::Cluster_size> (clusters);
features.add<Feature::Cluster_vertical_extent> (clusters);
for (std::size_t i = 0; i < 3; ++ i)
features.add<Feature::Eigenvalue> (clusters, eigen, (unsigned int)(i));
features.end_parallel_additions();
//! [Features]
///////////////////////////////////////////////////////////////////
t.stop();
Label_set labels = { "ground", "vegetation", "roof" };
std::vector<int> label_indices(clusters.size(), -1);
std::cerr << "Using ETHZ Random Forest Classifier" << std::endl;
Classification::ETHZ::Random_forest_classifier classifier (labels, features);
std::cerr << "Loading configuration" << std::endl;
std::ifstream in_config (filename_config, std::ios_base::in | std::ios_base::binary);
classifier.load_configuration (in_config);
std::cerr << "Classifying" << std::endl;
t.reset();
t.start();
Classification::classify<CGAL::Parallel_if_available_tag> (clusters, labels, classifier, label_indices);
t.stop();
std::cerr << "Classification done in " << t.time() << " second(s)" << std::endl;
return EXIT_SUCCESS;
}
|