mirror of https://github.com/CGAL/cgal
Update with reviews
This commit is contained in:
parent
0bc24a42b7
commit
1b900e8b86
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue