#if defined (_MSC_VER) && !defined (_WIN64) #pragma warning(disable:4244) // boost::number_distance::distance() // converts 64 to 32 bits integers #endif #include #include #include #include #include #include #include #include #include typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point; typedef CGAL::Point_set_3 Point_set; typedef Kernel::Iso_cuboid_3 Iso_cuboid_3; typedef Point_set::Point_map Pmap; typedef Point_set::Property_map Imap; typedef Point_set::Property_map UCmap; namespace Classification = CGAL::Classification; 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::Point_set_feature_generator Feature_generator; int main (int argc, char** argv) { std::string filename = "data/b9_training.ply"; if (argc > 1) filename = argv[1]; std::ifstream in (filename.c_str(), std::ios::binary); Point_set pts; std::cerr << "Reading input" << std::endl; in >> pts; Imap label_map; bool lm_found = false; boost::tie (label_map, lm_found) = pts.property_map ("label"); if (!lm_found) { std::cerr << "Error: \"label\" property not found in input file." << std::endl; return EXIT_FAILURE; } std::vector 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 (pts, pts.point_map(), 5); // using 5 scales #ifdef CGAL_LINKED_WITH_TBB features.begin_parallel_additions(); #endif generator.generate_point_based_features (features); #ifdef CGAL_LINKED_WITH_TBB features.end_parallel_additions(); #endif t.stop(); std::cerr << "Done in " << t.time() << " second(s)" << std::endl; // Add types Label_set labels; Label_handle ground = labels.add ("ground"); Label_handle vegetation = labels.add ("vegetation"); Label_handle roof = labels.add ("roof"); std::vector 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(); classifier.train (ground_truth); t.stop(); std::cerr << "Done in " << t.time() << " second(s)" << std::endl; t.reset(); t.start(); Classification::classify_with_graphcut (pts, pts.point_map(), labels, classifier, 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, ground_truth, label_indices); for (std::size_t i = 0; i < labels.size(); ++ i) { std::cerr << " * " << labels[i]->name() << ": " << evaluation.precision(labels[i]) << " ; " << evaluation.recall(labels[i]) << " ; " << evaluation.f1_score(labels[i]) << " ; " << evaluation.intersection_over_union(labels[i]) << std::endl; } 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; // Color point set according to class UCmap red = pts.add_property_map("red", 0).first; UCmap green = pts.add_property_map("green", 0).first; UCmap blue = pts.add_property_map("blue", 0).first; 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; } } // Write result std::ofstream f ("classification.ply"); f.precision(18); f << pts; std::cerr << "All done" << std::endl; return EXIT_SUCCESS; }