1 #ifndef CGAL_SURFACE_MESH_SEGMENTATION_ALPHA_EXPANSION_GRAPH_CUT_H
2 #define CGAL_SURFACE_MESH_SEGMENTATION_ALPHA_EXPANSION_GRAPH_CUT_H
14 #include <CGAL/assertions.h>
16 #include <boost/version.hpp>
17 #include <boost/graph/adjacency_list.hpp>
18 #if BOOST_VERSION >= 104400 // at this version kolmogorov_max_flow become depricated.
19 #include <boost/graph/boykov_kolmogorov_max_flow.hpp>
21 #include <boost/graph/kolmogorov_max_flow.hpp>
28 #ifdef CGAL_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE
29 #include <CGAL/internal/auxiliary/graph.h>
78 class Alpha_expansion_graph_cut_boost
81 typedef boost::adjacency_list_traits<boost::vecS, boost::listS, boost::directedS> Adjacency_list_traits;
83 typedef boost::adjacency_list<boost::vecS, boost::listS, boost::directedS,
85 boost::property<boost::vertex_index_t, std::size_t,
86 boost::property<boost::vertex_color_t, boost::default_color_type,
87 boost::property<boost::vertex_distance_t, double,
88 boost::property<boost::vertex_predecessor_t, Adjacency_list_traits::edge_descriptor > > > >,
90 boost::property<boost::edge_capacity_t, double,
91 boost::property<boost::edge_residual_capacity_t, double,
92 boost::property<boost::edge_reverse_t, Adjacency_list_traits::edge_descriptor> > > > Graph;
94 typedef boost::graph_traits<Graph> Traits;
95 typedef boost::color_traits<boost::default_color_type> ColorTraits;
97 typedef Traits::vertex_descriptor Vertex_descriptor;
98 typedef Traits::vertex_iterator Vertex_iterator;
99 typedef Traits::edge_descriptor Edge_descriptor;
100 typedef Traits::edge_iterator Edge_iterator;
111 boost::tuple<Edge_descriptor, Edge_descriptor>
112 add_edge_and_reverse(Vertex_descriptor& v1, Vertex_descriptor& v2,
double w1,
double w2, Graph& graph)
const
114 Edge_descriptor v1_v2, v2_v1;
115 bool v1_v2_added, v2_v1_added;
117 tie(v1_v2, v1_v2_added) = boost::add_edge(v1, v2, graph);
118 tie(v2_v1, v2_v1_added) = boost::add_edge(v2, v1, graph);
120 CGAL_assertion(v1_v2_added && v2_v1_added);
122 boost::put(boost::edge_reverse, graph, v1_v2, v2_v1);
123 boost::put(boost::edge_reverse, graph, v2_v1, v1_v2);
126 boost::put(boost::edge_capacity, graph, v1_v2, w1);
127 boost::put(boost::edge_capacity, graph, v2_v1, w2);
129 return boost::make_tuple(v1_v2, v2_v1);
142 double operator()(
const std::vector<std::pair<int, int> >& edges,
143 const std::vector<double>& edge_weights,
144 const std::vector<std::vector<double> >& probability_matrix,
145 std::vector<int>& labels)
const
147 double min_cut = (std::numeric_limits<double>::max)();
152 for(std::vector<std::vector<double> >::const_iterator it = probability_matrix.begin();
153 it != probability_matrix.end(); ++it, ++alpha)
156 Vertex_descriptor cluster_source = boost::add_vertex(graph);
157 Vertex_descriptor cluster_sink = boost::add_vertex(graph);
158 std::vector<Vertex_descriptor> inserted_vertices;
159 inserted_vertices.reserve(labels.size());
163 for(std::size_t vertex_i = 0; vertex_i < labels.size(); ++vertex_i)
165 Vertex_descriptor new_vertex = boost::add_vertex(graph);
166 inserted_vertices.push_back(new_vertex);
167 double source_weight = probability_matrix[alpha][vertex_i];
170 double sink_weight = (labels[vertex_i] == alpha) ? (std::numeric_limits<double>::max)()
171 : probability_matrix[labels[vertex_i]][vertex_i];
173 add_edge_and_reverse(cluster_source, new_vertex, source_weight, 0.0, graph);
174 add_edge_and_reverse(new_vertex, cluster_sink, sink_weight, 0.0, graph);
179 std::vector<double>::const_iterator weight_it = edge_weights.begin();
180 for(std::vector<std::pair<int, int> >::const_iterator edge_it = edges.begin(); edge_it != edges.end();
181 ++edge_it, ++weight_it)
183 Vertex_descriptor v1 = inserted_vertices[edge_it->first], v2 = inserted_vertices[edge_it->second];
184 int label_1 = labels[edge_it->first], label_2 = labels[edge_it->second];
185 if(label_1 == label_2)
188 { add_edge_and_reverse(v1, v2, *weight_it, *weight_it, graph); }
192 Vertex_descriptor inbetween = boost::add_vertex(graph);
194 double w1 = (label_1 == alpha) ? 0 : *weight_it;
195 double w2 = (label_2 == alpha) ? 0 : *weight_it;
196 add_edge_and_reverse(inbetween, v1, w1, w1, graph);
197 add_edge_and_reverse(inbetween, v2, w2, w2, graph);
198 add_edge_and_reverse(inbetween, cluster_sink, *weight_it, 0.0, graph);
202 Vertex_iterator v_begin, v_end;
203 Traits::vertices_size_type index = 0;
204 for(boost::tie(v_begin, v_end) = vertices(graph); v_begin != v_end; ++v_begin)
206 boost::put(boost::vertex_index, graph, *v_begin, index++);
209 #if BOOST_VERSION >= 104400
210 double flow = boost::boykov_kolmogorov_max_flow(graph, cluster_source, cluster_sink);
212 double flow = boost::kolmogorov_max_flow(graph, cluster_source, cluster_sink);
215 if(min_cut - flow < flow * 1e-10) {
continue; }
219 for(std::size_t vertex_i = 0; vertex_i < inserted_vertices.size(); ++vertex_i)
221 boost::default_color_type color = boost::get(boost::vertex_color, graph, inserted_vertices[vertex_i]);
222 if(labels[vertex_i] != alpha && color == ColorTraits::white())
224 labels[vertex_i] = alpha;
234 #ifdef CGAL_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE
241 class Alpha_expansion_graph_cut_boykov_kolmogorov
253 double operator()(
const std::vector<std::pair<int, int> >& edges,
254 const std::vector<double>& edge_weights,
255 const std::vector<std::vector<double> >& probability_matrix,
256 std::vector<int>& labels)
const
258 double min_cut = (std::numeric_limits<double>::max)();
263 for(std::vector<std::vector<double> >::const_iterator it = probability_matrix.begin();
264 it != probability_matrix.end(); ++it, ++alpha)
267 std::vector<Graph::node_id> inserted_vertices;
268 inserted_vertices.reserve(labels.size());
271 for(std::size_t vertex_i = 0; vertex_i < probability_matrix[0].size(); ++vertex_i)
273 Graph::node_id new_vertex = graph.add_node();
274 inserted_vertices.push_back(new_vertex);
276 double source_weight = probability_matrix[alpha][vertex_i];
279 double sink_weight = (labels[vertex_i] == alpha) ? (std::numeric_limits<double>::max)()
280 : probability_matrix[labels[vertex_i]][vertex_i];
281 graph.add_tweights(new_vertex, source_weight, sink_weight);
285 std::vector<double>::const_iterator weight_it = edge_weights.begin();
286 for(std::vector<std::pair<int, int> >::const_iterator edge_it = edges.begin(); edge_it != edges.end();
287 ++edge_it, ++weight_it)
289 Graph::node_id v1 = inserted_vertices[edge_it->first];
290 Graph::node_id v2 = inserted_vertices[edge_it->second];
291 int label_1 = labels[edge_it->first], label_2 = labels[edge_it->second];
292 if(label_1 == label_2)
295 { graph.add_edge(v1, v2, *weight_it, *weight_it); }
299 Graph::node_id inbetween = graph.add_node();
301 double w1 = (label_1 == alpha) ? 0 : *weight_it;
302 double w2 = (label_2 == alpha) ? 0 : *weight_it;
303 graph.add_edge(inbetween, v1, w1, w1);
304 graph.add_edge(inbetween, v2, w2, w2);
306 graph.add_tweights(inbetween, 0.0, *weight_it);
309 double flow = graph.maxflow();
310 if(min_cut - flow < flow * 1e-10) {
continue; }
315 for(std::size_t vertex_i = 0; vertex_i < labels.size(); ++vertex_i)
317 if(labels[vertex_i] != alpha && graph.what_segment(inserted_vertices[vertex_i]) == Graph::SINK)
319 labels[vertex_i] = alpha;
327 #endif //CGAL_USE_BOYKOV_KOLMOGOROV_MAXFLOW_SOFTWARE
331 #endif //CGAL_SURFACE_MESH_SEGMENTATION_ALPHA_EXPANSION_GRAPH_CUT_H