Change neighborhood API, using a Concept + models

This commit is contained in:
Simon Giraudot 2016-11-03 12:03:45 +01:00
parent 31278c59cb
commit ed583ac6e9
7 changed files with 123 additions and 95 deletions

View File

@ -29,13 +29,16 @@
\cgalClassifedRefPages \cgalClassifedRefPages
## Concepts ##
- `CGAL::NeighborQuery`
## Classification ## ## Classification ##
- `CGAL::Classifier<RandomAccessIterator, ItemMap>` - `CGAL::Classifier<RandomAccessIterator, ItemMap>`
## Data Structures ## ## Data Structures ##
- `CGAL::Classification::Helper<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Helper<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Neighborhood<Kernel, RandomAccessIterator, PointMap>` - `CGAL::Classification::Point_set_neighborhood<Kernel, RandomAccessIterator, PointMap>`
- `CGAL::Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>` - `CGAL::Classification::Local_eigen_analysis<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits>`
- `CGAL::Classification::Planimetric_grid<Kernel, RandomAccessIterator, PointMap>` - `CGAL::Classification::Planimetric_grid<Kernel, RandomAccessIterator, PointMap>`

View File

@ -114,7 +114,7 @@ int main (int argc, char** argv)
std::cerr << "Training" << std::endl; std::cerr << "Training" << std::endl;
psc.training(800); // 800 trials psc.training(800); // 800 trials
psc.run_with_graphcut (helper.neighborhood(), 0.5); psc.run_with_graphcut (helper.neighborhood().k_neighbor_query(12), 0.5);
// Save the output in a colored PLY format // Save the output in a colored PLY format
std::ofstream f ("classification.ply"); std::ofstream f ("classification.ply");

View File

@ -5,6 +5,7 @@
#include <CGAL/Simple_cartesian.h> #include <CGAL/Simple_cartesian.h>
#include <CGAL/Classifier.h> #include <CGAL/Classifier.h>
#include <CGAL/Classification/Point_set_neighborhood.h>
#include <CGAL/Classification/Planimetric_grid.h> #include <CGAL/Classification/Planimetric_grid.h>
#include <CGAL/Classification/Attribute.h> #include <CGAL/Classification/Attribute.h>
#include <CGAL/Classification/Attributes_eigen.h> #include <CGAL/Classification/Attributes_eigen.h>
@ -22,9 +23,9 @@ typedef CGAL::Identity_property_map<Point> Pmap;
typedef CGAL::Classifier<Iterator, Pmap> Classification; typedef CGAL::Classifier<Iterator, Pmap> Classification;
typedef CGAL::Classification::Planimetric_grid<Kernel, Iterator, Pmap> Planimetric_grid; typedef CGAL::Classification::Planimetric_grid<Kernel, Iterator, Pmap> Planimetric_grid;
typedef CGAL::Classification::Neighborhood<Kernel, Iterator, Pmap> Neighborhood; typedef CGAL::Classification::Point_set_neighborhood<Kernel, Iterator, Pmap> Neighborhood;
typedef CGAL::Classification::Local_eigen_analysis<Kernel, Iterator, Pmap> Local_eigen_analysis; typedef CGAL::Classification::Local_eigen_analysis<Kernel, Iterator, Pmap> Local_eigen_analysis;
typedef CGAL::Classification::Type_handle Type_handle; typedef CGAL::Classification::Type_handle Type_handle;
typedef CGAL::Classification::Attribute_handle Attribute_handle; typedef CGAL::Classification::Attribute_handle Attribute_handle;
@ -66,7 +67,7 @@ int main (int argc, char** argv)
Planimetric_grid grid (pts.begin(), pts.end(), Pmap(), bbox, grid_resolution); Planimetric_grid grid (pts.begin(), pts.end(), Pmap(), bbox, grid_resolution);
Neighborhood neighborhood (pts.begin(), pts.end(), Pmap()); Neighborhood neighborhood (pts.begin(), pts.end(), Pmap());
double garbage; double garbage;
Local_eigen_analysis eigen (pts.begin(), pts.end(), Pmap(), neighborhood, 6, garbage); Local_eigen_analysis eigen (pts.begin(), pts.end(), Pmap(), neighborhood.k_neighbor_query(6), garbage);
//! [Analysis] //! [Analysis]
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
@ -147,7 +148,7 @@ int main (int argc, char** argv)
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// Run classification // Run classification
psc.run_with_graphcut (neighborhood, 0.2); psc.run_with_graphcut (neighborhood.k_neighbor_query(12), 0.2);
// Save the output in a colored PLY format // Save the output in a colored PLY format

View File

@ -22,6 +22,7 @@
#include <CGAL/property_map.h> #include <CGAL/property_map.h>
#include <CGAL/Classifier.h> #include <CGAL/Classifier.h>
#include <CGAL/Classification/Point_set_neighborhood.h>
#include <CGAL/Classification/Planimetric_grid.h> #include <CGAL/Classification/Planimetric_grid.h>
#include <CGAL/Classification/Local_eigen_analysis.h> #include <CGAL/Classification/Local_eigen_analysis.h>
#include <CGAL/Classification/Attribute.h> #include <CGAL/Classification/Attribute.h>
@ -88,7 +89,7 @@ public:
<RandomAccessIterator, PointMap> Classifier; <RandomAccessIterator, PointMap> Classifier;
typedef CGAL::Classification::Planimetric_grid typedef CGAL::Classification::Planimetric_grid
<Kernel, RandomAccessIterator, PointMap> Planimetric_grid; <Kernel, RandomAccessIterator, PointMap> Planimetric_grid;
typedef CGAL::Classification::Neighborhood typedef CGAL::Classification::Point_set_neighborhood
<Kernel, RandomAccessIterator, PointMap> Neighborhood; <Kernel, RandomAccessIterator, PointMap> Neighborhood;
typedef CGAL::Classification::Local_eigen_analysis typedef CGAL::Classification::Local_eigen_analysis
<Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Local_eigen_analysis; <Kernel, RandomAccessIterator, PointMap, DiagonalizeTraits> Local_eigen_analysis;
@ -157,7 +158,7 @@ private:
t.reset(); t.reset();
t.start(); t.start();
double range; double range;
eigen = new Local_eigen_analysis (begin, end, point_map, *neighborhood, (std::size_t)6, range); eigen = new Local_eigen_analysis (begin, end, point_map, neighborhood->k_neighbor_query(6), range);
if (this->voxel_size < 0) if (this->voxel_size < 0)
this->voxel_size = range / 3; this->voxel_size = range / 3;
t.stop(); t.stop();

View File

@ -9,8 +9,6 @@
#include <CGAL/Default_diagonalize_traits.h> #include <CGAL/Default_diagonalize_traits.h>
#include <CGAL/centroid.h> #include <CGAL/centroid.h>
#include <CGAL/Classification/Neighborhood.h>
namespace CGAL { namespace CGAL {
namespace Classification { namespace Classification {
@ -37,7 +35,6 @@ public:
typedef typename Kernel::Point_3 Point; typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Vector_3 Vector; typedef typename Kernel::Vector_3 Vector;
typedef typename Kernel::Plane_3 Plane; typedef typename Kernel::Plane_3 Plane;
typedef Classification::Neighborhood<Kernel, RandomAccessIterator, PointMap> Neighborhood;
/// \endcond /// \endcond
typedef CGAL::cpp11::array<double, 3> Eigenvalues; ///< Eigenvalues (sorted in ascending order) typedef CGAL::cpp11::array<double, 3> Eigenvalues; ///< Eigenvalues (sorted in ascending order)
@ -60,63 +57,25 @@ public:
/// \endcond /// \endcond
/*! /*!
\brief Computes the local eigen analysis of an input range based
on a fixed number of local neighbors.
\brief Computes the local eigen analysis of an input range based
on a local neighborhood.
\tparam NeighborQuery is a model of `NeighborQuery`
\param begin Iterator to the first input object \param begin Iterator to the first input object
\param end Past-the-end iterator \param end Past-the-end iterator
\param point_map Property map to access the input points \param point_map Property map to access the input points
\param neighborhood Object used to access neighborhoods of points \param neighbor_query Object used to access neighborhoods of points
\param radius_neighbors Radius of the local neighborhood
*/
Local_eigen_analysis (RandomAccessIterator begin,
RandomAccessIterator end,
PointMap point_map,
Neighborhood& neighborhood,
double radius_neighbors)
{
std::size_t size = end - begin;
m_eigenvalues.reserve (size);
m_centroids.reserve (size);
m_smallest_eigenvectors.reserve (size);
m_middle_eigenvectors.reserve (size);
m_largest_eigenvectors.reserve (size);
double nb = 0.;
for (std::size_t i = 0; i < size; i++)
{
std::vector<std::size_t> neighbors;
neighborhood.range_neighbors (get(point_map, begin[i]), radius_neighbors, std::back_inserter (neighbors));
nb += neighbors.size();
std::vector<Point> neighbor_points;
for (std::size_t j = 0; j < neighbors.size(); ++ j)
neighbor_points.push_back (get(point_map, begin[neighbors[j]]));
compute (get(point_map, begin[i]), neighbor_points);
}
std::cerr << "Mean number of nearest neighbors: " << nb / size << std::endl;
}
/*!
\brief Computes the local eigen analysis of an input range based
on a fixed radius local neighborhood.
\param begin Iterator to the first input object
\param end Past-the-end iterator
\param point_map Property map to access the input points
\param neighborhood Object used to access neighborhoods of points
\param knn Number of nearest neighbors used
\param mean_range The mean value of the range corresponding to the \param mean_range The mean value of the range corresponding to the
`knn` number of neighbors is returned by the constructor through `knn` number of neighbors is returned by the constructor through
this reference. this reference.
*/ */
template <typename NeighborQuery>
Local_eigen_analysis (RandomAccessIterator begin, Local_eigen_analysis (RandomAccessIterator begin,
RandomAccessIterator end, RandomAccessIterator end,
PointMap point_map, PointMap point_map,
Neighborhood& neighborhood, const NeighborQuery& neighbor_query,
std::size_t knn,
double& mean_range) double& mean_range)
{ {
std::size_t size = end - begin; std::size_t size = end - begin;
@ -131,7 +90,7 @@ public:
for (std::size_t i = 0; i < size; i++) for (std::size_t i = 0; i < size; i++)
{ {
std::vector<std::size_t> neighbors; std::vector<std::size_t> neighbors;
neighborhood.k_neighbors (get(point_map, begin[i]), knn, std::back_inserter (neighbors)); neighbor_query (get(point_map, begin[i]), std::back_inserter (neighbors));
std::vector<Point> neighbor_points; std::vector<Point> neighbor_points;
for (std::size_t j = 0; j < neighbors.size(); ++ j) for (std::size_t j = 0; j < neighbors.size(); ++ j)

View File

@ -1,5 +1,5 @@
#ifndef CGAL_CLASSIFICATION_NEIGHBORHOOD_H #ifndef CGAL_CLASSIFICATION_POINT_SET_NEIGHBORHOOD_H
#define CGAL_CLASSIFICATION_NEIGHBORHOOD_H #define CGAL_CLASSIFICATION_POINT_SET_NEIGHBORHOOD_H
#include <vector> #include <vector>
@ -29,8 +29,9 @@ namespace Classification {
\tparam PointMap is a model of `ReadablePropertyMap` with value type `Point_3<Kernel>`. \tparam PointMap is a model of `ReadablePropertyMap` with value type `Point_3<Kernel>`.
*/ */
template <typename Kernel, typename RandomAccessIterator, typename PointMap> template <typename Kernel, typename RandomAccessIterator, typename PointMap>
class Neighborhood class Point_set_neighborhood
{ {
typedef typename Kernel::FT FT; typedef typename Kernel::FT FT;
typedef typename Kernel::Point_3 Point; typedef typename Kernel::Point_3 Point;
@ -67,8 +68,71 @@ class Neighborhood
public: public:
/// \cond SKIP_IN_MANUAL /*!
Neighborhood () : m_tree (NULL) { } Functor that returns a neighborhood with a fixed number of points.
\cgalModels NeighborQuery
*/
class K_neighbor_query
{
public:
typedef Point_set_neighborhood::Point value_type; ///<
private:
const Point_set_neighborhood& neighborhood;
std::size_t k;
public:
/*!
\brief Constructs a K neighbor query object.
\param neighborhood The point set neighborhood structure.
\param k The number of neighbors per query.
*/
K_neighbor_query (const Point_set_neighborhood& neighborhood, std::size_t k)
: neighborhood (neighborhood), k(k) { }
/// \cond SKIP_IN_MANUAL
template <typename OutputIterator>
void operator() (const value_type& query, OutputIterator output) const
{
neighborhood.k_neighbors (query, k, output);
}
/// \endcond
};
/*!
Functor that returns a neighborhood with a fixed radius.
\cgalModels NeighborQuery
*/
class Range_neighbor_query
{
public:
typedef Point_set_neighborhood::Point value_type; ///<
private:
const Point_set_neighborhood& neighborhood;
double radius;
public:
/*!
\brief Constructs a range neighbor query object.
\param neighborhood The point set neighborhood structure.
\param radius The radius of the neighbor query.
*/
Range_neighbor_query (const Point_set_neighborhood& neighborhood, double radius)
: neighborhood (neighborhood), radius(radius) { }
/// \cond SKIP_IN_MANUAL
template <typename OutputIterator>
void operator() (const value_type& query, OutputIterator output) const
{
neighborhood.range_neighbors (query, radius, output);
}
/// \endcond
};
friend class K_neighbor_query;
friend class Range_neighbor_query;
/// \cond SKIP_IN_MANUAL
Point_set_neighborhood () : m_tree (NULL) { }
/// \endcond /// \endcond
/*! /*!
@ -78,7 +142,7 @@ public:
\param end Past-the-end iterator \param end Past-the-end iterator
\param point_map Property map to access the input points \param point_map Property map to access the input points
*/ */
Neighborhood (const RandomAccessIterator& begin, Point_set_neighborhood (const RandomAccessIterator& begin,
const RandomAccessIterator& end, const RandomAccessIterator& end,
PointMap point_map) PointMap point_map)
: m_tree (NULL) : m_tree (NULL)
@ -107,7 +171,7 @@ public:
\param point_map Property map to access the input points \param point_map Property map to access the input points
\param voxel_size \param voxel_size
*/ */
Neighborhood (const RandomAccessIterator& begin, Point_set_neighborhood (const RandomAccessIterator& begin,
const RandomAccessIterator& end, const RandomAccessIterator& end,
PointMap point_map, PointMap point_map,
double voxel_size) double voxel_size)
@ -130,7 +194,7 @@ public:
} }
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
~Neighborhood () ~Point_set_neighborhood ()
{ {
if (m_tree != NULL) if (m_tree != NULL)
delete m_tree; delete m_tree;
@ -138,13 +202,23 @@ public:
/// \endcond /// \endcond
/*! /*!
\brief Gets the nearest neighbors computed in a local sphere of user defined radius. \brief Returns a neighbor query object with fixed number of neighbors `k`.
\tparam OutputIterator Iterator that must point to values of type `std::size_t`.
\param query The query point.
\param radius_neighbors Radius of the query sphere.
\param output Where the indices of found neighbor points are stored.
*/ */
K_neighbor_query k_neighbor_query (const std::size_t k) const
{
return K_neighbor_query (*this, k);
}
/*!
\brief Returns a neighbor query object with fixed radius `radius`.
*/
Range_neighbor_query range_neighbor_query (const double radius) const
{
return Range_neighbor_query (*this, radius);
}
private:
template <typename OutputIterator> template <typename OutputIterator>
void range_neighbors (const Point& query, const FT radius_neighbors, OutputIterator output) const void range_neighbors (const Point& query, const FT radius_neighbors, OutputIterator output) const
{ {
@ -153,14 +227,6 @@ public:
m_tree->search (output, fs); m_tree->search (output, fs);
} }
/*!
\brief Gets the K nearest neighbors.
\tparam OutputIterator Iterator that must point to values of type `std::size_t`.
\param query The query point.
\param k Number of nearest neighbors.
\param output Where the indices of found neighbor points are stored.
*/
template <typename OutputIterator> template <typename OutputIterator>
void k_neighbors (const Point& query, const std::size_t k, OutputIterator output) const void k_neighbors (const Point& query, const std::size_t k, OutputIterator output) const
{ {
@ -170,7 +236,6 @@ public:
*(output ++) = it->first; *(output ++) = it->first;
} }
private:
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
template <typename Map> template <typename Map>
void voxelize_point_set (std::vector<std::size_t>& indices, Map point_map, void voxelize_point_set (std::vector<std::size_t>& indices, Map point_map,
@ -223,4 +288,4 @@ private:
} }
#endif // CGAL_CLASSIFICATION_NEIGHBORHOOD_H #endif // CGAL_CLASSIFICATION_POINT_SET_POINT_SET_NEIGHBORHOOD_H

View File

@ -231,12 +231,11 @@ public:
local neighborhood of items. This method is a compromise between local neighborhood of items. This method is a compromise between
efficiency and reliability. efficiency and reliability.
\param neighborhood Object used to access neighborhoods of items \tparam NeighborQuery is a model of `NeighborQuery`
\param radius_neighbors Radius used for smoothing \param neighbor_query is used to access neighborhoods of items
*/ */
template <typename Neighborhood> template <typename NeighborQuery>
void run_with_local_smoothing (const Neighborhood& neighborhood, void run_with_local_smoothing (const NeighborQuery& neighbor_query)
const double radius_neighbors)
{ {
prepare_classification (); prepare_classification ();
@ -250,8 +249,7 @@ public:
for (std::size_t s=0; s < m_input.size(); ++ s) for (std::size_t s=0; s < m_input.size(); ++ s)
{ {
std::vector<std::size_t> neighbors; std::vector<std::size_t> neighbors;
neighborhood.range_neighbors (m_input[s], radius_neighbors, neighbor_query (m_input[s], std::back_inserter (neighbors));
std::back_inserter (neighbors));
std::vector<double> mean (values.size(), 0.); std::vector<double> mean (values.size(), 0.);
for (std::size_t n = 0; n < neighbors.size(); ++ n) for (std::size_t n = 0; n < neighbors.size(); ++ n)
@ -296,15 +294,16 @@ public:
and alpha-expansion algorithm. This method is slow but provides and alpha-expansion algorithm. This method is slow but provides
the user with good quality results. the user with good quality results.
\param neighborhood Object used to access neighborhoods of items \tparam NeighborQuery is a model of `NeighborQuery`
\param neighbor_query is used to access neighborhoods of items
\param weight Weight of the regularization with respect to the \param weight Weight of the regularization with respect to the
classification energy. Higher values produce more regularized classification energy. Higher values produce more regularized
output but may result in a loss of details. output but may result in a loss of details.
*/ */
template <typename Neighborhood> template <typename NeighborQuery>
void run_with_graphcut (const Neighborhood& neighborhood, void run_with_graphcut (const NeighborQuery& neighbor_query,
const double weight = 0.5) const double& weight)
{ {
prepare_classification (); prepare_classification ();
@ -321,7 +320,7 @@ public:
{ {
std::vector<std::size_t> neighbors; std::vector<std::size_t> neighbors;
neighborhood.k_neighbors (m_input[s], 12, std::back_inserter (neighbors)); neighbor_query (m_input[s], std::back_inserter (neighbors));
for (std::size_t i = 0; i < neighbors.size(); ++ i) for (std::size_t i = 0; i < neighbors.size(); ++ i)
if (s != neighbors[i]) if (s != neighbors[i])