mirror of https://github.com/CGAL/cgal
Finalize API of alpha expansion + doc
This commit is contained in:
parent
f0df168096
commit
497c121e55
|
|
@ -653,6 +653,47 @@ can be done directly using `Face_filtered_graph`.
|
||||||
|
|
||||||
Using \ref BGLNamedParameters some of the many options of METIS can be customized,
|
Using \ref BGLNamedParameters some of the many options of METIS can be customized,
|
||||||
as shown in \ref BGL_polyhedron_3/polyhedron_partition.cpp "this example".
|
as shown in \ref BGL_polyhedron_3/polyhedron_partition.cpp "this example".
|
||||||
|
|
||||||
|
\section BGLGraphcut Graphcut
|
||||||
|
|
||||||
|
Optimal partition from a set of labels can be computed through a
|
||||||
|
graphcut approach called Alpha Expansion
|
||||||
|
\cgalCite{boykov2001fastapproximate}. \cgal provides
|
||||||
|
`CGAL::alpha_expansion_graphcut()` which, or a graph \f$(V,E)\f$, this
|
||||||
|
function seeks for the partioning `f` that minimizes the following
|
||||||
|
energy:
|
||||||
|
|
||||||
|
\f[
|
||||||
|
\mathrm{E}(f) = \sum_{\{v0,v1\} \in E} W(v0,v1) + \sum_{v \in V} C(f_v)
|
||||||
|
\f]
|
||||||
|
|
||||||
|
where \f$W(v0,v1)\f$ is the weight associated to the edge
|
||||||
|
\f$\{v0,v1\}\f$ and \f$C(f_v)\f$ is the cost of assigning the vertex
|
||||||
|
\f$v\f$ to the labeling \f$f\f$.
|
||||||
|
|
||||||
|
Three different implementations are provided and can be selected by
|
||||||
|
using one of the following tags:
|
||||||
|
|
||||||
|
- `CGAL::Alpha_expansion_boost_adjacency_list_tag` (default)
|
||||||
|
- `CGAL::Alpha_expansion_boost_compressed_sparse_raw_tag`
|
||||||
|
- `CGAL::Alpha_expansion_boost_MaxFlow_tag`
|
||||||
|
|
||||||
|
All these implementation produce the exact same result but behave
|
||||||
|
differently in terms of timing and memory (see
|
||||||
|
\cgalFigureRef{alpha_exp}). The _MaxFlow_ implementation is the
|
||||||
|
fastest, but it grows rapidly in memory when increasing the complexity
|
||||||
|
of the input graph and labeling; the _compressed sparse raw_ (CSR) is very
|
||||||
|
efficient from a memory point of view but becomes very slow as the
|
||||||
|
complexity of the input graph and labeling increases; the _adjacency
|
||||||
|
list_ version provides a good compromise and is therefore the default
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
\cgalFigureBegin{alpha_exp, alpha_expansion.png}
|
||||||
|
Comparison of time and memory consumed by the different Alpha
|
||||||
|
Expansion implementation.
|
||||||
|
\cgalFigureEnd
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
} /* namespace CGAL */
|
} /* namespace CGAL */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \
|
||||||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/io.h \
|
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/io.h \
|
||||||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/partition.h \
|
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/partition.h \
|
||||||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_graph.h \
|
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_graph.h \
|
||||||
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h
|
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/METIS/partition_dual_graph.h \
|
||||||
|
${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/alpha_expansion_graphcut.h
|
||||||
|
|
||||||
|
|
||||||
EXAMPLE_PATH = ${CGAL_Surface_mesh_skeletonization_EXAMPLE_DIR} \
|
EXAMPLE_PATH = ${CGAL_Surface_mesh_skeletonization_EXAMPLE_DIR} \
|
||||||
|
|
|
||||||
|
|
@ -710,6 +710,7 @@ user might encounter.
|
||||||
\cgalCRPSection{Partitioning Methods}
|
\cgalCRPSection{Partitioning Methods}
|
||||||
- `CGAL::METIS::partition_graph()`
|
- `CGAL::METIS::partition_graph()`
|
||||||
- `CGAL::METIS::partition_dual_graph()`
|
- `CGAL::METIS::partition_dual_graph()`
|
||||||
|
- `CGAL::alpha_expansion_graphcut()`
|
||||||
|
|
||||||
\cgalCRPSection{I/O Functions}
|
\cgalCRPSection{I/O Functions}
|
||||||
- \link PkgBGLIOFct CGAL::read_off() \endlink
|
- \link PkgBGLIOFct CGAL::read_off() \endlink
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef CGAL_SURFACE_MESH_SEGMENTATION_ALPHA_EXPANSION_GRAPH_CUT_H
|
#ifndef CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_H
|
||||||
// Copyright (c) 2014 GeometryFactory Sarl (France).
|
// Copyright (c) 2014 GeometryFactory Sarl (France).
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
@ -15,32 +15,13 @@
|
||||||
//
|
//
|
||||||
// $URL$
|
// $URL$
|
||||||
// $Id$
|
// $Id$
|
||||||
// SPDX-License-Identifier: GPL-3.0+
|
// SPDX-License-Identifier: LGPL-3.0+
|
||||||
//
|
//
|
||||||
// Author(s) : Ilker O. Yaz
|
// Author(s) : Ilker O. Yaz, Simon Giraudot
|
||||||
|
|
||||||
#define CGAL_SURFACE_MESH_SEGMENTATION_ALPHA_EXPANSION_GRAPH_CUT_H
|
#define CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_H
|
||||||
|
|
||||||
#include <CGAL/license/Surface_mesh_segmentation.h>
|
#include <CGAL/Iterator_range.h>
|
||||||
|
|
||||||
|
|
||||||
/// @cond CGAL_DOCUMENT_INTERNAL
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file Alpha_expansion_graph_cut.h
|
|
||||||
* @brief This file contains 3 graph-cut algorithms, which can be used as a template parameter for CGAL::internal::Surface_mesh_segmentation.
|
|
||||||
*
|
|
||||||
* Main differences between implementations are underlying max-flow algorithm and graph type (i.e. results are the same, performance differs).
|
|
||||||
*
|
|
||||||
* By default, we use MAXFLOW and the class Alpha_expansion_graph_cut_boykov_kolmogorov.
|
|
||||||
* For deactivating MAXFLOW software and using boost implementation instead, define CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE.
|
|
||||||
* It deactivates Alpha_expansion_graph_cut_boykov_kolmogorov, activate boost versions
|
|
||||||
* and makes CGAL::internal::Surface_mesh_segmentation using Alpha_expansion_graph_cut_boost
|
|
||||||
* as default implementation for the graph-cut.
|
|
||||||
*
|
|
||||||
* Also algorithms can be used by their-own for applying alpha-expansion graph-cut on any graph.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include <CGAL/assertions.h>
|
#include <CGAL/assertions.h>
|
||||||
#ifdef CGAL_SEGMENTATION_BENCH_GRAPHCUT
|
#ifdef CGAL_SEGMENTATION_BENCH_GRAPHCUT
|
||||||
#include <CGAL/Timer.h>
|
#include <CGAL/Timer.h>
|
||||||
|
|
@ -51,13 +32,6 @@
|
||||||
|
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.hpp>
|
||||||
|
|
||||||
#ifndef CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE
|
|
||||||
namespace MaxFlow
|
|
||||||
{
|
|
||||||
#include <CGAL/internal/auxiliary/graph.h>
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/graph/adjacency_list.hpp>
|
#include <boost/graph/adjacency_list.hpp>
|
||||||
#include <boost/graph/compressed_sparse_row_graph.hpp>
|
#include <boost/graph/compressed_sparse_row_graph.hpp>
|
||||||
|
|
||||||
|
|
@ -74,6 +48,8 @@ namespace MaxFlow
|
||||||
|
|
||||||
namespace CGAL
|
namespace CGAL
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// \cond SKIP_IN_MANUAL
|
||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -91,25 +67,25 @@ struct Alpha_expansion_old_API_wrapper_graph
|
||||||
typedef CGAL::Identity_property_map<std::size_t> Vertex_index_map;
|
typedef CGAL::Identity_property_map<std::size_t> Vertex_index_map;
|
||||||
typedef CGAL::Pointer_property_map<std::size_t>::type Vertex_label_map;
|
typedef CGAL::Pointer_property_map<std::size_t>::type Vertex_label_map;
|
||||||
|
|
||||||
struct Vertex_label_probability_map
|
struct Vertex_label_cost_map
|
||||||
{
|
{
|
||||||
typedef std::size_t key_type;
|
typedef std::size_t key_type;
|
||||||
typedef std::vector<double> value_type;
|
typedef std::vector<double> value_type;
|
||||||
typedef value_type reference;
|
typedef value_type reference;
|
||||||
typedef boost::readable_property_map_tag category;
|
typedef boost::readable_property_map_tag category;
|
||||||
|
|
||||||
const std::vector<std::vector<double> >* probability_matrix;
|
const std::vector<std::vector<double> >* cost_matrix;
|
||||||
|
|
||||||
Vertex_label_probability_map (const std::vector<std::vector<double> >* probability_matrix)
|
Vertex_label_cost_map (const std::vector<std::vector<double> >* cost_matrix)
|
||||||
: probability_matrix (probability_matrix)
|
: cost_matrix (cost_matrix)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
friend reference get (const Vertex_label_probability_map& pmap, key_type idx)
|
friend reference get (const Vertex_label_cost_map& pmap, key_type idx)
|
||||||
{
|
{
|
||||||
std::vector<double> out;
|
std::vector<double> out;
|
||||||
out.reserve (pmap.probability_matrix->size());
|
out.reserve (pmap.cost_matrix->size());
|
||||||
for (std::size_t i = 0; i < pmap.probability_matrix->size(); ++ i)
|
for (std::size_t i = 0; i < pmap.cost_matrix->size(); ++ i)
|
||||||
out.push_back ((*pmap.probability_matrix)[i][idx]);
|
out.push_back ((*pmap.cost_matrix)[i][idx]);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,14 +95,14 @@ struct Alpha_expansion_old_API_wrapper_graph
|
||||||
|
|
||||||
const std::vector<std::pair<std::size_t, std::size_t> >& edges;
|
const std::vector<std::pair<std::size_t, std::size_t> >& edges;
|
||||||
const std::vector<double>& edge_weights;
|
const std::vector<double>& edge_weights;
|
||||||
const std::vector<std::vector<double> >& probability_matrix;
|
const std::vector<std::vector<double> >& cost_matrix;
|
||||||
std::vector<std::size_t>& labels;
|
std::vector<std::size_t>& labels;
|
||||||
|
|
||||||
Alpha_expansion_old_API_wrapper_graph (const std::vector<std::pair<std::size_t, std::size_t> >& edges,
|
Alpha_expansion_old_API_wrapper_graph (const std::vector<std::pair<std::size_t, std::size_t> >& edges,
|
||||||
const std::vector<double>& edge_weights,
|
const std::vector<double>& edge_weights,
|
||||||
const std::vector<std::vector<double> >& probability_matrix,
|
const std::vector<std::vector<double> >& cost_matrix,
|
||||||
std::vector<std::size_t>& labels)
|
std::vector<std::size_t>& labels)
|
||||||
: edges (edges), edge_weights (edge_weights), probability_matrix (probability_matrix), labels (labels)
|
: edges (edges), edge_weights (edge_weights), cost_matrix (cost_matrix), labels (labels)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
friend counting_range vertices (const Alpha_expansion_old_API_wrapper_graph& graph)
|
friend counting_range vertices (const Alpha_expansion_old_API_wrapper_graph& graph)
|
||||||
|
|
@ -150,8 +126,8 @@ struct Alpha_expansion_old_API_wrapper_graph
|
||||||
|
|
||||||
Vertex_index_map vertex_index_map() const { return Vertex_index_map(); }
|
Vertex_index_map vertex_index_map() const { return Vertex_index_map(); }
|
||||||
Vertex_label_map vertex_label_map() { return CGAL::make_property_map(labels); }
|
Vertex_label_map vertex_label_map() { return CGAL::make_property_map(labels); }
|
||||||
Vertex_label_probability_map vertex_label_probability_map() const
|
Vertex_label_cost_map vertex_label_cost_map() const
|
||||||
{ return Vertex_label_probability_map(&probability_matrix); }
|
{ return Vertex_label_cost_map(&cost_matrix); }
|
||||||
Edge_weight_map edge_weight_map() const { return CGAL::make_property_map(edge_weights); }
|
Edge_weight_map edge_weight_map() const { return CGAL::make_property_map(edge_weights); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -206,7 +182,7 @@ struct Alpha_expansion_old_API_wrapper_graph
|
||||||
* For representing graph, it uses adjacency_list with OutEdgeList = vecS, VertexList = listS.
|
* For representing graph, it uses adjacency_list with OutEdgeList = vecS, VertexList = listS.
|
||||||
* Also no pre-allocation is made for vertex-list.
|
* Also no pre-allocation is made for vertex-list.
|
||||||
*/
|
*/
|
||||||
class Alpha_expansion_boost_adjacency_list
|
class Alpha_expansion_boost_adjacency_list_tag
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
typedef boost::adjacency_list_traits<boost::vecS, boost::listS, boost::directedS>
|
typedef boost::adjacency_list_traits<boost::vecS, boost::listS, boost::directedS>
|
||||||
|
|
@ -295,15 +271,6 @@ public:
|
||||||
put (vertex_label_map, vd, alpha);
|
put (vertex_label_map, vd, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds two directional edges between @a v1 and @a v2
|
|
||||||
* @param v1 first vertex
|
|
||||||
* @param v2 second vertex
|
|
||||||
* @param w1 weight for edge from v1 to v2 (v1->v2)
|
|
||||||
* @param w2 weight for edge from v2 to v1 (v2->v1)
|
|
||||||
* @param graph to be added
|
|
||||||
* @return pair of added edges, first: v1->v2 and second: v2->v1
|
|
||||||
*/
|
|
||||||
void add_edge (Vertex_descriptor& v1, Vertex_descriptor& v2, double w1, double w2)
|
void add_edge (Vertex_descriptor& v1, Vertex_descriptor& v2, double w1, double w2)
|
||||||
{
|
{
|
||||||
Edge_descriptor v1_v2, v2_v1;
|
Edge_descriptor v1_v2, v2_v1;
|
||||||
|
|
@ -327,7 +294,7 @@ public:
|
||||||
// another implementation using compressed_sparse_row_graph
|
// another implementation using compressed_sparse_row_graph
|
||||||
// for now there is a performance problem while setting reverse edges
|
// for now there is a performance problem while setting reverse edges
|
||||||
// if that can be solved, it is faster than Alpha_expansion_graph_cut_boost
|
// if that can be solved, it is faster than Alpha_expansion_graph_cut_boost
|
||||||
class Alpha_expansion_boost_compressed_sparse_row
|
class Alpha_expansion_boost_compressed_sparse_row_tag
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// CSR only accepts bundled props
|
// CSR only accepts bundled props
|
||||||
|
|
@ -475,98 +442,123 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE
|
// Default version using boost adjacency list
|
||||||
/**
|
|
||||||
* @brief Implements alpha-expansion graph cut algorithm.
|
|
||||||
*
|
|
||||||
* For underlying max-flow algorithm, it uses the MAXFLOW software implemented by Boykov & Kolmogorov.
|
|
||||||
* Also no pre-allocation is made.
|
|
||||||
*/
|
|
||||||
class Alpha_expansion_MaxFlow
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef MaxFlow::Graph::node_id Vertex_descriptor;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
MaxFlow::Graph graph;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
void clear_graph()
|
|
||||||
{
|
|
||||||
graph = MaxFlow::Graph();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vertex_descriptor add_vertex()
|
|
||||||
{
|
|
||||||
return graph.add_node();
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_tweight (Vertex_descriptor& v, double w1, double w2)
|
|
||||||
{
|
|
||||||
graph.add_tweights(v, w1, w2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_vertices()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
double max_flow()
|
|
||||||
{
|
|
||||||
return graph.maxflow();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename VertexLabelMap, typename InputVertexDescriptor>
|
|
||||||
void update(VertexLabelMap vertex_label_map,
|
|
||||||
const std::vector<Vertex_descriptor>& inserted_vertices,
|
|
||||||
InputVertexDescriptor vd,
|
|
||||||
std::size_t vertex_i,
|
|
||||||
std::size_t alpha)
|
|
||||||
{
|
|
||||||
if(get(vertex_label_map, vd) != alpha
|
|
||||||
&& graph.what_segment(inserted_vertices[vertex_i]) == MaxFlow::Graph::SINK)
|
|
||||||
put(vertex_label_map, vd, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds two directional edges between @a v1 and @a v2
|
|
||||||
* @param v1 first vertex
|
|
||||||
* @param v2 second vertex
|
|
||||||
* @param w1 weight for edge from v1 to v2 (v1->v2)
|
|
||||||
* @param w2 weight for edge from v2 to v1 (v2->v1)
|
|
||||||
* @param graph to be added
|
|
||||||
* @return pair of added edges, first: v1->v2 and second: v2->v1
|
|
||||||
*/
|
|
||||||
void add_edge (Vertex_descriptor& v1, Vertex_descriptor& v2, double w1, double w2)
|
|
||||||
{
|
|
||||||
graph.add_edge(v1, v2, w1, w2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif //CGAL_DO_NOT_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE
|
|
||||||
/// @endcond
|
|
||||||
|
|
||||||
template <typename InputGraph,
|
template <typename InputGraph,
|
||||||
typename Edge_weight_map,
|
typename EdgeWeightMap,
|
||||||
typename Vertex_index_map,
|
typename VertexIndexMap,
|
||||||
typename Vertex_label_map,
|
typename VertexLabelCostMap,
|
||||||
typename Vertex_label_probability_map,
|
typename VertexLabelMap>
|
||||||
typename AlphaExpansionImplementation>
|
double alpha_expansion_graphcut (const InputGraph& input_graph,
|
||||||
double alpha_expansion_graph_cut (const InputGraph& input_graph,
|
EdgeWeightMap edge_weight_map,
|
||||||
Edge_weight_map edge_weight_map,
|
VertexIndexMap vertex_index_map,
|
||||||
Vertex_index_map vertex_index_map,
|
VertexLabelCostMap vertex_label_cost_map,
|
||||||
Vertex_label_map vertex_label_map,
|
VertexLabelMap vertex_label_map)
|
||||||
Vertex_label_probability_map vertex_label_probability_map,
|
{
|
||||||
AlphaExpansionImplementation alpha_expansion = AlphaExpansionImplementation())
|
return alpha_expansion_graphcut
|
||||||
|
(input_graph, edge_weight_map, vertex_index_map, vertex_label_cost_map, vertex_label_map,
|
||||||
|
Alpha_expansion_boost_adjacency_list_tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
|
// NOTE: latest performances check (2019-07-22)
|
||||||
|
//
|
||||||
|
// Using a random graph with 50000 vertices, 100000 edges and 30 labels:
|
||||||
|
//
|
||||||
|
// METHOD TIMING MEMORY
|
||||||
|
// Boost Adjacency list 49s 122MiB
|
||||||
|
// Boost CSR 187s 77MiB
|
||||||
|
// MaxFlow 12s 717MiB
|
||||||
|
|
||||||
|
/**
|
||||||
|
\ingroup PkgBGLPartition
|
||||||
|
|
||||||
|
Regularizes a partition of a graph into `n` labels using the Alpha
|
||||||
|
Expansion algorithm \cgalCite{Boykov2001FastApproximate}.
|
||||||
|
|
||||||
|
For a graph \f$(V,E)\f$, this function seeks for the partioning `f`
|
||||||
|
that minimizes the following energy:
|
||||||
|
|
||||||
|
\f[
|
||||||
|
\mathrm{E}(f) = \sum_{\{v0,v1\} \in E} W(v0,v1) + \sum_{v \in V} C(f_v)
|
||||||
|
\f]
|
||||||
|
|
||||||
|
where \f$W(v0,v1)\f$ is the weight associated to the edge
|
||||||
|
\f$\{v0,v1\}\f$ and \f$C(f_v)\f$ is the cost of assigning the
|
||||||
|
vertex \f$v\f$ to the labeling \f$f\f$.
|
||||||
|
|
||||||
|
\tparam InputGraph a model of `Graph`
|
||||||
|
|
||||||
|
\tparam EdgeWeightMap a model of `ReadablePropertyMap` with
|
||||||
|
`boost::graph_traits<Graph>::%edge_descriptor` as key and `double`
|
||||||
|
as value.
|
||||||
|
|
||||||
|
\tparam VertexIndexMap a model of `ReadablePropertyMap` with
|
||||||
|
`boost::graph_traits<Graph>::%vertex_descriptor` as key and
|
||||||
|
`std::size_t` as value.
|
||||||
|
|
||||||
|
\tparam VertexLabelCostMap a model of `ReadablePropertyMap`
|
||||||
|
with `boost::graph_traits<Graph>::%vertex_descriptor` as key and
|
||||||
|
`std::vector<double>` as value.
|
||||||
|
|
||||||
|
\tparam VertexLabelMap a model of `ReadWritePropertyMap` with
|
||||||
|
`boost::graph_traits<Graph>::%vertex_descriptor` as key and
|
||||||
|
`std::size_t` as value.
|
||||||
|
|
||||||
|
\tparam AlphaExpansionImplementationTag optional tag used to select
|
||||||
|
which implementation of the Alpha Expansion should be
|
||||||
|
used. Available implementation tags are:
|
||||||
|
|
||||||
|
- `CGAL::Alpha_expansion_boost_adjacency_list` (default)
|
||||||
|
- `CGAL::Alpha_expansion_boost_compressed_sparse_row_tag`
|
||||||
|
- `CGAL::Alpha_expansion_MaxFlow_tag`
|
||||||
|
|
||||||
|
\note The `MaxFlow` implementation is provided separately under a
|
||||||
|
GPL license (whereas the rest of the package including this
|
||||||
|
function is under LGPL). The header
|
||||||
|
`<CGAL/boost/graph/alpha_shape_graphcut_maxflow_gpl.h>` should be
|
||||||
|
included if users want to use this implementation.
|
||||||
|
|
||||||
|
\param input_graph the input graph.
|
||||||
|
|
||||||
|
\param edge_weight_map a property map providing the weight of each
|
||||||
|
edge.
|
||||||
|
|
||||||
|
\param vertex_index_map a property map providing the index of each
|
||||||
|
vertex.
|
||||||
|
|
||||||
|
\param vertex_label_map a property map providing the label of each
|
||||||
|
vertex. This map will be updated by the algorithm with the
|
||||||
|
regularized version of the partitioning.
|
||||||
|
|
||||||
|
\param vertex_label_cost_map a property_map providing, for each
|
||||||
|
vertex, an `std::vector` containing the cost of this vertex to
|
||||||
|
belong to each label. For example,
|
||||||
|
`get(vertex_label_cost_map, vd)[label_idx]` returns the cost
|
||||||
|
of vertex `vd` to belong to the label `label_idx`.
|
||||||
|
*/
|
||||||
|
template <typename InputGraph,
|
||||||
|
typename EdgeWeightMap,
|
||||||
|
typename VertexIndexMap,
|
||||||
|
typename VertexLabelCostMap,
|
||||||
|
typename VertexLabelMap,
|
||||||
|
typename AlphaExpansionImplementationTag>
|
||||||
|
double alpha_expansion_graphcut (const InputGraph& input_graph,
|
||||||
|
EdgeWeightMap edge_weight_map,
|
||||||
|
VertexIndexMap vertex_index_map,
|
||||||
|
VertexLabelCostMap vertex_label_cost_map,
|
||||||
|
VertexLabelMap vertex_label_map,
|
||||||
|
const AlphaExpansionImplementationTag&)
|
||||||
{
|
{
|
||||||
typedef boost::graph_traits<InputGraph> GT;
|
typedef boost::graph_traits<InputGraph> GT;
|
||||||
typedef typename GT::edge_descriptor input_edge_descriptor;
|
typedef typename GT::edge_descriptor input_edge_descriptor;
|
||||||
typedef typename GT::vertex_descriptor input_vertex_descriptor;
|
typedef typename GT::vertex_descriptor input_vertex_descriptor;
|
||||||
|
|
||||||
typedef AlphaExpansionImplementation Alpha_expansion;
|
typedef AlphaExpansionImplementationTag Alpha_expansion;
|
||||||
typedef typename Alpha_expansion::Vertex_descriptor Vertex_descriptor;
|
typedef typename Alpha_expansion::Vertex_descriptor Vertex_descriptor;
|
||||||
|
|
||||||
|
Alpha_expansion alpha_expansion;
|
||||||
|
|
||||||
// TODO: check this hardcoded parameter
|
// TODO: check this hardcoded parameter
|
||||||
const double tolerance = 1e-10;
|
const double tolerance = 1e-10;
|
||||||
|
|
||||||
|
|
@ -580,7 +572,7 @@ double alpha_expansion_graph_cut (const InputGraph& input_graph,
|
||||||
std::vector<Vertex_descriptor> inserted_vertices;
|
std::vector<Vertex_descriptor> inserted_vertices;
|
||||||
inserted_vertices.resize(num_vertices (input_graph));
|
inserted_vertices.resize(num_vertices (input_graph));
|
||||||
|
|
||||||
std::size_t number_of_labels = get(vertex_label_probability_map, *std::begin(vertices(input_graph))).size();
|
std::size_t number_of_labels = get(vertex_label_cost_map, *std::begin(vertices(input_graph))).size();
|
||||||
|
|
||||||
bool success;
|
bool success;
|
||||||
do {
|
do {
|
||||||
|
|
@ -602,12 +594,12 @@ double alpha_expansion_graph_cut (const InputGraph& input_graph,
|
||||||
std::size_t vertex_i = get(vertex_index_map, vd);
|
std::size_t vertex_i = get(vertex_index_map, vd);
|
||||||
Vertex_descriptor new_vertex = alpha_expansion.add_vertex();
|
Vertex_descriptor new_vertex = alpha_expansion.add_vertex();
|
||||||
inserted_vertices[vertex_i] = new_vertex;
|
inserted_vertices[vertex_i] = new_vertex;
|
||||||
double source_weight = get(vertex_label_probability_map, vd)[alpha];
|
double source_weight = get(vertex_label_cost_map, vd)[alpha];
|
||||||
// since it is expansion move, current alpha labeled vertices will be assigned to alpha again,
|
// since it is expansion move, current alpha labeled vertices will be assigned to alpha again,
|
||||||
// making sink_weight 'infinity' guarantee this.
|
// making sink_weight 'infinity' guarantee this.
|
||||||
double sink_weight = (get(vertex_label_map, vd) == alpha ?
|
double sink_weight = (get(vertex_label_map, vd) == alpha ?
|
||||||
(std::numeric_limits<double>::max)()
|
(std::numeric_limits<double>::max)()
|
||||||
: get(vertex_label_probability_map, vd)[get(vertex_label_map, vd)]);
|
: get(vertex_label_cost_map, vd)[get(vertex_label_map, vd)]);
|
||||||
|
|
||||||
alpha_expansion.add_tweight(new_vertex, source_weight, sink_weight);
|
alpha_expansion.add_tweight(new_vertex, source_weight, sink_weight);
|
||||||
}
|
}
|
||||||
|
|
@ -686,40 +678,41 @@ double alpha_expansion_graph_cut (const InputGraph& input_graph,
|
||||||
return min_cut;
|
return min_cut;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputGraph,
|
|
||||||
typename Edge_weight_map,
|
|
||||||
typename Vertex_index_map,
|
|
||||||
typename Vertex_label_map,
|
|
||||||
typename Vertex_label_probability_map>
|
|
||||||
double alpha_expansion_graph_cut (const InputGraph& input_graph,
|
|
||||||
Edge_weight_map edge_weight_map,
|
|
||||||
Vertex_index_map vertex_index_map,
|
|
||||||
Vertex_label_map vertex_label_map,
|
|
||||||
Vertex_label_probability_map vertex_label_probability_map)
|
|
||||||
{
|
|
||||||
return alpha_expansion_graph_cut<InputGraph,
|
|
||||||
Edge_weight_map,
|
|
||||||
Vertex_index_map,
|
|
||||||
Vertex_label_map,
|
|
||||||
Vertex_label_probability_map,
|
|
||||||
Alpha_expansion_boost_adjacency_list>
|
|
||||||
(input_graph, edge_weight_map, vertex_index_map, vertex_label_map, vertex_label_probability_map);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// \cond SKIP_IN_MANUAL
|
||||||
// Old API
|
// Old API
|
||||||
inline double alpha_expansion_graph_cut (const std::vector<std::pair<std::size_t, std::size_t> >& edges,
|
inline double alpha_expansion_graphcut (const std::vector<std::pair<std::size_t, std::size_t> >& edges,
|
||||||
const std::vector<double>& edge_weights,
|
const std::vector<double>& edge_weights,
|
||||||
const std::vector<std::vector<double> >& probability_matrix,
|
const std::vector<std::vector<double> >& cost_matrix,
|
||||||
std::vector<std::size_t>& labels)
|
std::vector<std::size_t>& labels)
|
||||||
{
|
{
|
||||||
internal::Alpha_expansion_old_API_wrapper_graph graph (edges, edge_weights, probability_matrix, labels);
|
internal::Alpha_expansion_old_API_wrapper_graph graph (edges, edge_weights, cost_matrix, labels);
|
||||||
|
|
||||||
return alpha_expansion_graph_cut(graph,
|
return alpha_expansion_graphcut(graph,
|
||||||
graph.edge_weight_map(),
|
graph.edge_weight_map(),
|
||||||
graph.vertex_index_map(),
|
graph.vertex_index_map(),
|
||||||
graph.vertex_label_map(),
|
graph.vertex_label_cost_map(),
|
||||||
graph.vertex_label_probability_map());
|
graph.vertex_label_map());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename AlphaExpansionImplementationTag>
|
||||||
|
double alpha_expansion_graphcut (const std::vector<std::pair<std::size_t, std::size_t> >& edges,
|
||||||
|
const std::vector<double>& edge_weights,
|
||||||
|
const std::vector<std::vector<double> >& cost_matrix,
|
||||||
|
std::vector<std::size_t>& labels,
|
||||||
|
const AlphaExpansionImplementationTag&)
|
||||||
|
{
|
||||||
|
internal::Alpha_expansion_old_API_wrapper_graph graph (edges, edge_weights, cost_matrix, labels);
|
||||||
|
|
||||||
|
return alpha_expansion_graphcut(graph,
|
||||||
|
graph.edge_weight_map(),
|
||||||
|
graph.vertex_index_map(),
|
||||||
|
graph.vertex_label_cost_map(),
|
||||||
|
graph.vertex_label_map(),
|
||||||
|
AlphaExpansionImplementationTag());
|
||||||
|
}
|
||||||
|
/// \endcond
|
||||||
|
|
||||||
|
|
||||||
}//namespace CGAL
|
}//namespace CGAL
|
||||||
#endif //CGAL_SURFACE_MESH_SEGMENTATION_ALPHA_EXPANSION_GRAPH_CUT_H
|
#endif //CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_H
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
#ifndef CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_MAXFLOW_GPL_H
|
||||||
|
// Copyright (c) 2014 GeometryFactory Sarl (France).
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of CGAL (www.cgal.org).
|
||||||
|
// You can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
// General Public License as published by the Free Software Foundation,
|
||||||
|
// either version 3 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Licensees holding a valid commercial license may use this file in
|
||||||
|
// accordance with the commercial license agreement provided with the software.
|
||||||
|
//
|
||||||
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||||
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// $URL$
|
||||||
|
// $Id$
|
||||||
|
// SPDX-License-Identifier: GPL-3.0+
|
||||||
|
//
|
||||||
|
// Author(s) : Ilker O. Yaz, Simon Giraudot
|
||||||
|
|
||||||
|
#define CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_MAXFLOW_GPL_H
|
||||||
|
|
||||||
|
#include <CGAL/boost/graph/alpha_expansion_graphcut.h>
|
||||||
|
|
||||||
|
namespace MaxFlow
|
||||||
|
{
|
||||||
|
#include <CGAL/internal/auxiliary/graph.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace CGAL
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implements alpha-expansion graph cut algorithm.
|
||||||
|
*
|
||||||
|
* For underlying max-flow algorithm, it uses the MAXFLOW software implemented by Boykov & Kolmogorov.
|
||||||
|
* Also no pre-allocation is made.
|
||||||
|
*/
|
||||||
|
class Alpha_expansion_MaxFlow_tag
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef MaxFlow::Graph::node_id Vertex_descriptor;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
MaxFlow::Graph graph;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void clear_graph()
|
||||||
|
{
|
||||||
|
graph = MaxFlow::Graph();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertex_descriptor add_vertex()
|
||||||
|
{
|
||||||
|
return graph.add_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_tweight (Vertex_descriptor& v, double w1, double w2)
|
||||||
|
{
|
||||||
|
graph.add_tweights(v, w1, w2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_vertices()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
double max_flow()
|
||||||
|
{
|
||||||
|
return graph.maxflow();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VertexLabelMap, typename InputVertexDescriptor>
|
||||||
|
void update(VertexLabelMap vertex_label_map,
|
||||||
|
const std::vector<Vertex_descriptor>& inserted_vertices,
|
||||||
|
InputVertexDescriptor vd,
|
||||||
|
std::size_t vertex_i,
|
||||||
|
std::size_t alpha)
|
||||||
|
{
|
||||||
|
if(get(vertex_label_map, vd) != alpha
|
||||||
|
&& graph.what_segment(inserted_vertices[vertex_i]) == MaxFlow::Graph::SINK)
|
||||||
|
put(vertex_label_map, vd, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_edge (Vertex_descriptor& v1, Vertex_descriptor& v2, double w1, double w2)
|
||||||
|
{
|
||||||
|
graph.add_edge(v1, v2, w1, w2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}//namespace CGAL
|
||||||
|
|
||||||
|
#endif //CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_MAXFLOW_GPL_H
|
||||||
Loading…
Reference in New Issue