Make Boost Alpha Expansion use BGL API

This commit is contained in:
Simon Giraudot 2019-07-18 11:07:03 +02:00
parent 0dd30b1a68
commit 5ca8fcf47b
1 changed files with 143 additions and 26 deletions

View File

@ -75,6 +75,84 @@ namespace CGAL
namespace internal
{
struct Alpha_expansion_old_API_wrapper_graph
{
typedef std::size_t vertex_descriptor;
typedef std::size_t edge_descriptor;
typedef boost::directed_tag directed_category;
typedef boost::disallow_parallel_edge_tag edge_parallel_category;
typedef boost::edge_list_graph_tag traversal_category;
typedef boost::counting_iterator<std::size_t> counting_iterator;
typedef CGAL::Iterator_range<counting_iterator> counting_range;
typedef CGAL::Identity_property_map<std::size_t> Vertex_index_map;
typedef CGAL::Pointer_property_map<std::size_t>::type Vertex_label_map;
struct Vertex_label_probability_map
{
typedef std::size_t key_type;
typedef std::vector<double> value_type;
typedef value_type reference;
typedef boost::readable_property_map_tag category;
const std::vector<std::vector<double> >* probability_matrix;
Vertex_label_probability_map (const std::vector<std::vector<double> >* probability_matrix)
: probability_matrix (probability_matrix)
{ }
friend reference get (const Vertex_label_probability_map& pmap, key_type idx)
{
std::vector<double> out;
out.reserve (pmap.probability_matrix->size());
for (std::size_t i = 0; i < pmap.probability_matrix->size(); ++ i)
out.push_back ((*pmap.probability_matrix)[i][idx]);
return out;
}
};
typedef CGAL::Pointer_property_map<double>::const_type Edge_weight_map;
const std::vector<std::pair<std::size_t, std::size_t> >& edges;
const std::vector<double>& edge_weights;
const std::vector<std::vector<double> >& probability_matrix;
std::vector<std::size_t>& labels;
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<std::vector<double> >& probability_matrix,
std::vector<std::size_t>& labels)
: edges (edges), edge_weights (edge_weights), probability_matrix (probability_matrix), labels (labels)
{ }
friend counting_range vertices (const Alpha_expansion_old_API_wrapper_graph& graph)
{
return CGAL::make_range (boost::counting_iterator<std::size_t>(0),
boost::counting_iterator<std::size_t>(graph.labels.size()));
}
friend std::size_t num_vertices (const Alpha_expansion_old_API_wrapper_graph& graph) { return graph.labels.size(); }
friend counting_range edges (const Alpha_expansion_old_API_wrapper_graph& graph)
{
return CGAL::make_range (boost::counting_iterator<std::size_t>(0),
boost::counting_iterator<std::size_t>(graph.edges.size()));
}
friend vertex_descriptor source (edge_descriptor ed, const Alpha_expansion_old_API_wrapper_graph& graph)
{ return graph.edges[ed].first; }
friend vertex_descriptor target (edge_descriptor ed, const Alpha_expansion_old_API_wrapper_graph& graph)
{ return graph.edges[ed].second; }
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_probability_map vertex_label_probability_map() const
{ return Vertex_label_probability_map(&probability_matrix); }
Edge_weight_map edge_weight_map() const { return CGAL::make_property_map(edge_weights); }
};
////////////////////////////////////////////////////////////////////////////////////////
// Comments about performance:
//
@ -182,6 +260,8 @@ private:
return boost::make_tuple(v1_v2, v2_v1);
}
public:
/**
* Applies alpha-expansion graph-cut for energy minimization.
@ -196,7 +276,33 @@ public:
edges,
const std::vector<double>& edge_weights,
const std::vector<std::vector<double> >& probability_matrix,
std::vector<std::size_t>& labels) const {
std::vector<std::size_t>& labels) const
{
Alpha_expansion_old_API_wrapper_graph graph (edges, edge_weights, probability_matrix, labels);
return (*this)(graph,
graph.edge_weight_map(),
graph.vertex_index_map(),
graph.vertex_label_map(),
graph.vertex_label_probability_map());
}
template <typename InputGraph,
typename Edge_weight_map,
typename Vertex_index_map,
typename Vertex_label_map,
typename Vertex_label_probability_map>
double operator()(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) const
{
typedef boost::graph_traits<InputGraph> GT;
typedef typename GT::edge_descriptor input_edge_descriptor;
typedef typename GT::vertex_descriptor input_vertex_descriptor;
// TODO: check this hardcoded parameter
const double tolerance = 1e-10;
double min_cut = (std::numeric_limits<double>::max)();
@ -207,18 +313,18 @@ public:
#endif
std::vector<Vertex_descriptor> inserted_vertices;
inserted_vertices.resize(labels.size());
inserted_vertices.resize(num_vertices (input_graph));
std::size_t number_of_labels = get(vertex_label_probability_map, *std::begin(vertices(input_graph))).size();
Graph graph;
bool success;
do {
success = false;
std::size_t alpha = 0;
for(std::vector<std::vector<double> >::const_iterator it =
probability_matrix.begin();
it != probability_matrix.end(); ++it, ++alpha) {
for (std::size_t alpha = 0; alpha < number_of_labels; ++ alpha)
{
graph.clear();
Vertex_descriptor cluster_source = boost::add_vertex(graph);
@ -230,16 +336,18 @@ public:
#endif
// For E-Data
// add every facet as a vertex to the graph, put edges to source & sink vertices
for(std::size_t vertex_i = 0; vertex_i < labels.size(); ++vertex_i) {
// add every input vertex as a vertex to the graph, put edges to source & sink vertices
for (input_vertex_descriptor vd : vertices(input_graph))
{
std::size_t vertex_i = get(vertex_index_map, vd);
Vertex_descriptor new_vertex = boost::add_vertex(graph);
inserted_vertices[vertex_i] = new_vertex;
double source_weight = probability_matrix[alpha][vertex_i];
double source_weight = get(vertex_label_probability_map, vd)[alpha];
// since it is expansion move, current alpha labeled vertices will be assigned to alpha again,
// making sink_weight 'infinity' guarantee this.
double sink_weight = (labels[vertex_i] == alpha) ?
double sink_weight = (get(vertex_label_map, vd) == alpha ?
(std::numeric_limits<double>::max)()
: probability_matrix[labels[vertex_i]][vertex_i];
: get(vertex_label_probability_map, vd)[get(vertex_label_map, vd)]);
add_edge_and_reverse(cluster_source, new_vertex, source_weight, 0.0, graph);
add_edge_and_reverse(new_vertex, cluster_sink, sink_weight, 0.0, graph);
@ -251,25 +359,32 @@ public:
// For E-Smooth
// add edge between every vertex,
std::vector<double>::const_iterator weight_it = edge_weights.begin();
for(std::vector<std::pair<std::size_t, std::size_t> >::const_iterator edge_it =
edges.begin(); edge_it != edges.end();
++edge_it, ++weight_it) {
Vertex_descriptor v1 = inserted_vertices[edge_it->first],
v2 = inserted_vertices[edge_it->second];
std::size_t label_1 = labels[edge_it->first], label_2 = labels[edge_it->second];
for (input_edge_descriptor ed : edges(input_graph))
{
input_vertex_descriptor vd1 = source(ed, input_graph);
input_vertex_descriptor vd2 = target(ed, input_graph);
std::size_t idx1 = get (vertex_index_map, vd1);
std::size_t idx2 = get (vertex_index_map, vd2);
double weight = get (edge_weight_map, ed);
Vertex_descriptor v1 = inserted_vertices[idx1],
v2 = inserted_vertices[idx2];
std::size_t label_1 = get (vertex_label_map, vd1);
std::size_t label_2 = get (vertex_label_map, vd2);
if(label_1 == label_2) {
if(label_1 != alpha) {
add_edge_and_reverse(v1, v2, *weight_it, *weight_it, graph);
add_edge_and_reverse(v1, v2, weight, weight, graph);
}
} else {
Vertex_descriptor inbetween = boost::add_vertex(graph);
double w1 = (label_1 == alpha) ? 0 : *weight_it;
double w2 = (label_2 == alpha) ? 0 : *weight_it;
double w1 = (label_1 == alpha) ? 0 : weight;
double w2 = (label_2 == alpha) ? 0 : weight;
add_edge_and_reverse(inbetween, v1, w1, w1, graph);
add_edge_and_reverse(inbetween, v2, w2, w2, graph);
add_edge_and_reverse(inbetween, cluster_sink, *weight_it, 0.0, graph);
add_edge_and_reverse(inbetween, cluster_sink, weight, 0.0, graph);
}
}
#ifdef CGAL_SEGMENTATION_BENCH_GRAPHCUT
@ -302,12 +417,14 @@ public:
min_cut = flow;
success = true;
//update labeling
for(std::size_t vertex_i = 0; vertex_i < inserted_vertices.size(); ++vertex_i) {
for (input_vertex_descriptor vd : vertices (input_graph))
{
std::size_t vertex_i = get (vertex_index_map, vd);
boost::default_color_type color = boost::get(boost::vertex_color, graph,
inserted_vertices[vertex_i]);
if(labels[vertex_i] != alpha
if(get (vertex_label_map, vd) != alpha
&& color == ColorTraits::white()) { //new comers (expansion occurs)
labels[vertex_i] = alpha;
put (vertex_label_map, vd, alpha);
}
}
}