Update with reviews

This commit is contained in:
Simon Giraudot 2020-01-15 12:46:53 +01:00
parent 0bc24a42b7
commit 1b900e8b86
4 changed files with 178 additions and 12 deletions

View File

@ -654,9 +654,9 @@ can be done directly using `Face_filtered_graph`.
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".
\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
graph cut approach called Alpha Expansion
\cgalCite{boykov2001fastapproximate}. \cgal provides
`CGAL::alpha_expansion_graphcut()` which, or a graph \f$(V,E)\f$, this
@ -695,6 +695,33 @@ Comparison of time and memory consumed by the different Alpha
Expansion implementation.
\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 */

View File

@ -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" )

View File

@ -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;
}

View File

@ -473,7 +473,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
/**
\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}.
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
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
`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
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`.
belong to each label. Each `std::vector` should have the same size
`n` (which is the number of labels), each label being indexed from
`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,
typename EdgeWeightMap,
@ -571,7 +573,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
std::vector<Vertex_descriptor> inserted_vertices;
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;
do {
@ -588,7 +590,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
// For E-Data
// 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);
Vertex_descriptor new_vertex = alpha_expansion.add_vertex();
@ -609,7 +611,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
// For E-Smooth
// 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 vd2 = target(ed, input_graph);
@ -659,7 +661,7 @@ double alpha_expansion_graphcut (const InputGraph& input_graph,
min_cut = flow;
success = true;
//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);
alpha_expansion.update(vertex_label_map, inserted_vertices, vd, vertex_i, alpha);