mirror of https://github.com/CGAL/cgal
Update with reviews
This commit is contained in:
parent
0bc24a42b7
commit
1b900e8b86
|
|
@ -654,10 +654,10 @@ 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
|
\section BGLGraphcut Graph Cut
|
||||||
|
|
||||||
Optimal partition from a set of labels can be computed through a
|
An optimal partition from a set of labels can be computed through a
|
||||||
graphcut approach called Alpha Expansion
|
graph cut approach called Alpha Expansion
|
||||||
\cgalCite{boykov2001fastapproximate}. \cgal provides
|
\cgalCite{boykov2001fastapproximate}. \cgal provides
|
||||||
`CGAL::alpha_expansion_graphcut()` which, or a graph \f$(V,E)\f$, this
|
`CGAL::alpha_expansion_graphcut()` which, or a graph \f$(V,E)\f$, this
|
||||||
function seeks for the partioning `f` that minimizes the following
|
function seeks for the partioning `f` that minimizes the following
|
||||||
|
|
@ -695,6 +695,33 @@ Comparison of time and memory consumed by the different Alpha
|
||||||
Expansion implementation.
|
Expansion implementation.
|
||||||
\cgalFigureEnd
|
\cgalFigureEnd
|
||||||
|
|
||||||
|
The following example shows how to apply the Alpha Expansion algorithm
|
||||||
|
to a `boost::adjacency_list` describing a 2D array with 3 labels "X",
|
||||||
|
" " and "O":
|
||||||
|
|
||||||
|
\cgalExample{BGL_graphcut/alpha_expansion_example.cpp}
|
||||||
|
|
||||||
|
The output of this program shows how the initial 2D array is
|
||||||
|
regularized spatially:
|
||||||
|
|
||||||
|
```
|
||||||
|
Input:
|
||||||
|
XOX
|
||||||
|
XX X O
|
||||||
|
OX OO
|
||||||
|
X OOX
|
||||||
|
OXOO
|
||||||
|
|
||||||
|
Alpha expansion...
|
||||||
|
|
||||||
|
Output:
|
||||||
|
XXX
|
||||||
|
XX O
|
||||||
|
XX OO
|
||||||
|
X OOO
|
||||||
|
OOOO
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
} /* namespace CGAL */
|
} /* namespace CGAL */
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Created by the script cgal_create_CMakeLists
|
||||||
|
# This is the CMake script for compiling a set of CGAL applications.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.1...3.15)
|
||||||
|
|
||||||
|
project( BGL_graphcut )
|
||||||
|
|
||||||
|
|
||||||
|
# CGAL and its components
|
||||||
|
find_package( CGAL QUIET COMPONENTS )
|
||||||
|
|
||||||
|
if ( NOT CGAL_FOUND )
|
||||||
|
|
||||||
|
message(STATUS "This project requires the CGAL library, and will not be compiled.")
|
||||||
|
return()
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Boost and its components
|
||||||
|
find_package( Boost REQUIRED )
|
||||||
|
|
||||||
|
if ( NOT Boost_FOUND )
|
||||||
|
|
||||||
|
message(STATUS "This project requires the Boost library, and will not be compiled.")
|
||||||
|
|
||||||
|
return()
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# include for local directory
|
||||||
|
|
||||||
|
# include for local package
|
||||||
|
|
||||||
|
|
||||||
|
# Creating entries for all C++ files with "main" routine
|
||||||
|
# ##########################################################
|
||||||
|
|
||||||
|
|
||||||
|
create_single_source_cgal_program( "alpha_expansion_example.cpp" )
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
#include <CGAL/boost/graph/alpha_expansion_graphcut.h>
|
||||||
|
#include <boost/graph/adjacency_list.hpp>
|
||||||
|
|
||||||
|
struct Vertex_property
|
||||||
|
{
|
||||||
|
int label;
|
||||||
|
std::vector<double> cost;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Edge_property
|
||||||
|
{
|
||||||
|
double weight;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Graph = boost::adjacency_list <boost::setS,
|
||||||
|
boost::vecS,
|
||||||
|
boost::undirectedS,
|
||||||
|
Vertex_property,
|
||||||
|
Edge_property>;
|
||||||
|
using GT = boost::graph_traits<Graph>;
|
||||||
|
using vertex_descriptor = GT::vertex_descriptor;
|
||||||
|
using edge_descriptor = GT::edge_descriptor;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::array<char, 3> labels = { 'X', ' ', 'O' };
|
||||||
|
|
||||||
|
std::array<std::array<int, 6>, 5> input
|
||||||
|
= { { { 0, 2, 0, 1, 1, 1 },
|
||||||
|
{ 0, 0, 1, 0, 1, 2 },
|
||||||
|
{ 2, 0, 1, 1, 2, 2 },
|
||||||
|
{ 0, 1, 1, 2, 2, 0 },
|
||||||
|
{ 1, 1, 2, 0, 2, 2 } } };
|
||||||
|
|
||||||
|
std::array<std::array<vertex_descriptor, 6>, 5> vertices;
|
||||||
|
|
||||||
|
// Init vertices from values
|
||||||
|
Graph g;
|
||||||
|
for (std::size_t i = 0; i < input.size(); ++ i)
|
||||||
|
for (std::size_t j = 0; j < input[i].size(); ++ j)
|
||||||
|
{
|
||||||
|
vertices[i][j] = boost::add_vertex(g);
|
||||||
|
g[vertices[i][j]].label = input[i][j];
|
||||||
|
|
||||||
|
// Cost of assigning this vertex to any label is positive except
|
||||||
|
// for current label which is 0 (favor init solution)
|
||||||
|
g[vertices[i][j]].cost.resize(3, 1);
|
||||||
|
g[vertices[i][j]].cost[std::size_t(input[i][j])] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display input values
|
||||||
|
std::cerr << "Input:" << std::endl;
|
||||||
|
for (std::size_t i = 0; i < vertices.size(); ++ i)
|
||||||
|
{
|
||||||
|
for (std::size_t j = 0; j < vertices[i].size(); ++ j)
|
||||||
|
std::cerr << labels[std::size_t(g[vertices[i][j]].label)];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init adjacency
|
||||||
|
double weight = 0.5;
|
||||||
|
for (std::size_t i = 0; i < vertices.size(); ++ i)
|
||||||
|
for (std::size_t j = 0; j < vertices[i].size(); ++ j)
|
||||||
|
{
|
||||||
|
// Neighbor vertices are connected
|
||||||
|
if (i < vertices.size() - 1)
|
||||||
|
{
|
||||||
|
edge_descriptor ed = boost::add_edge (vertices[i][j], vertices[i+1][j], g).first;
|
||||||
|
g[ed].weight = weight;
|
||||||
|
}
|
||||||
|
if (j < vertices[i].size() - 1)
|
||||||
|
{
|
||||||
|
edge_descriptor ed = boost::add_edge (vertices[i][j], vertices[i][j+1], g).first;
|
||||||
|
g[ed].weight = weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << std::endl << "Alpha expansion..." << std::endl << std::endl;
|
||||||
|
CGAL::alpha_expansion_graphcut (g,
|
||||||
|
get (&Edge_property::weight, g),
|
||||||
|
get (boost::vertex_index, g),
|
||||||
|
get (&Vertex_property::cost, g),
|
||||||
|
get (&Vertex_property::label, g));
|
||||||
|
|
||||||
|
// Display output graph
|
||||||
|
std::cerr << "Output:" << std::endl;
|
||||||
|
for (std::size_t i = 0; i < vertices.size(); ++ i)
|
||||||
|
{
|
||||||
|
for (std::size_t j = 0; j < vertices[i].size(); ++ j)
|
||||||
|
std::cerr << labels[std::size_t(g[vertices[i][j]].label)];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -473,7 +473,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
|
||||||
/**
|
/**
|
||||||
\ingroup PkgBGLPartition
|
\ingroup PkgBGLPartition
|
||||||
|
|
||||||
Regularizes a partition of a graph into `n` labels using the Alpha
|
regularizes a partition of a graph into `n` labels using the Alpha
|
||||||
Expansion algorithm \cgalCite{Boykov2001FastApproximate}.
|
Expansion algorithm \cgalCite{Boykov2001FastApproximate}.
|
||||||
|
|
||||||
For a graph \f$(V,E)\f$, this function seeks for the partioning `f`
|
For a graph \f$(V,E)\f$, this function seeks for the partioning `f`
|
||||||
|
|
@ -487,7 +487,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
|
||||||
\f$\{v0,v1\}\f$ and \f$C(f_v)\f$ is the cost of assigning the
|
\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$.
|
vertex \f$v\f$ to the labeling \f$f\f$.
|
||||||
|
|
||||||
\tparam InputGraph a model of `Graph`
|
\tparam InputGraph a model of `VertexAndEdgeListGraph`
|
||||||
|
|
||||||
\tparam EdgeWeightMap a model of `ReadablePropertyMap` with
|
\tparam EdgeWeightMap a model of `ReadablePropertyMap` with
|
||||||
`boost::graph_traits<InputGraph>::%edge_descriptor` as key and `double`
|
`boost::graph_traits<InputGraph>::%edge_descriptor` as key and `double`
|
||||||
|
|
@ -532,9 +532,11 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
|
||||||
|
|
||||||
\param vertex_label_cost_map a property map providing, for each
|
\param vertex_label_cost_map a property map providing, for each
|
||||||
vertex, an `std::vector` containing the cost of this vertex to
|
vertex, an `std::vector` containing the cost of this vertex to
|
||||||
belong to each label. For example,
|
belong to each label. Each `std::vector` should have the same size
|
||||||
`get(vertex_label_cost_map, vd)[label_idx]` returns the cost
|
`n` (which is the number of labels), each label being indexed from
|
||||||
of vertex `vd` to belong to the label `label_idx`.
|
`0` to `n-1`. 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,
|
template <typename InputGraph,
|
||||||
typename EdgeWeightMap,
|
typename EdgeWeightMap,
|
||||||
|
|
@ -571,7 +573,7 @@ double alpha_expansion_graphcut (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_cost_map, *std::begin(vertices(input_graph))).size();
|
std::size_t number_of_labels = get(vertex_label_cost_map, *(vertices(input_graph).first)).size();
|
||||||
|
|
||||||
bool success;
|
bool success;
|
||||||
do {
|
do {
|
||||||
|
|
@ -588,7 +590,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
|
||||||
|
|
||||||
// For E-Data
|
// For E-Data
|
||||||
// add every input vertex as a vertex to the graph, put edges to source & sink vertices
|
// add every input vertex as a vertex to the graph, put edges to source & sink vertices
|
||||||
for (input_vertex_descriptor vd : vertices(input_graph))
|
for (input_vertex_descriptor vd : CGAL::make_range(vertices(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();
|
||||||
|
|
@ -609,7 +611,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
|
||||||
|
|
||||||
// For E-Smooth
|
// For E-Smooth
|
||||||
// add edge between every vertex,
|
// add edge between every vertex,
|
||||||
for (input_edge_descriptor ed : edges(input_graph))
|
for (input_edge_descriptor ed : CGAL::make_range(edges(input_graph)))
|
||||||
{
|
{
|
||||||
input_vertex_descriptor vd1 = source(ed, input_graph);
|
input_vertex_descriptor vd1 = source(ed, input_graph);
|
||||||
input_vertex_descriptor vd2 = target(ed, input_graph);
|
input_vertex_descriptor vd2 = target(ed, input_graph);
|
||||||
|
|
@ -659,7 +661,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
|
||||||
min_cut = flow;
|
min_cut = flow;
|
||||||
success = true;
|
success = true;
|
||||||
//update labeling
|
//update labeling
|
||||||
for (input_vertex_descriptor vd : vertices (input_graph))
|
for (input_vertex_descriptor vd : CGAL::make_range(vertices (input_graph)))
|
||||||
{
|
{
|
||||||
std::size_t vertex_i = get (vertex_index_map, vd);
|
std::size_t vertex_i = get (vertex_index_map, vd);
|
||||||
alpha_expansion.update(vertex_label_map, inserted_vertices, vd, vertex_i, alpha);
|
alpha_expansion.update(vertex_label_map, inserted_vertices, vd, vertex_i, alpha);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue