1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
42 #ifndef _CV_GCGRAPH_H_
43 #define _CV_GCGRAPH_H_
45 template <class TWeight> class GCGraph
49 GCGraph( unsigned int vtxCount, unsigned int edgeCount );
51 void create( unsigned int vtxCount, unsigned int edgeCount );
53 void addEdges( int i, int j, TWeight w, TWeight revw );
54 void addTermWeights( int i, TWeight sourceW, TWeight sinkW );
56 bool inSourceSegment( int i );
61 Vtx *next; // initialized and used in maxFlow() only
77 std::vector<Vtx> vtcs;
78 std::vector<Edge> edges;
82 template <class TWeight>
83 GCGraph<TWeight>::GCGraph()
87 template <class TWeight>
88 GCGraph<TWeight>::GCGraph( unsigned int vtxCount, unsigned int edgeCount )
90 create( vtxCount, edgeCount );
92 template <class TWeight>
93 GCGraph<TWeight>::~GCGraph()
96 template <class TWeight>
97 void GCGraph<TWeight>::create( unsigned int vtxCount, unsigned int edgeCount )
99 vtcs.reserve( vtxCount );
100 edges.reserve( edgeCount + 2 );
104 template <class TWeight>
105 int GCGraph<TWeight>::addVtx()
108 memset( &v, 0, sizeof(Vtx));
110 return (int)vtcs.size() - 1;
113 template <class TWeight>
114 void GCGraph<TWeight>::addEdges( int i, int j, TWeight w, TWeight revw )
116 CV_Assert( i>=0 && i<(int)vtcs.size() );
117 CV_Assert( j>=0 && j<(int)vtcs.size() );
118 CV_Assert( w>=0 && revw>=0 );
126 fromI.next = vtcs[i].first;
128 vtcs[i].first = (int)edges.size();
129 edges.push_back( fromI );
132 toI.next = vtcs[j].first;
134 vtcs[j].first = (int)edges.size();
135 edges.push_back( toI );
138 template <class TWeight>
139 void GCGraph<TWeight>::addTermWeights( int i, TWeight sourceW, TWeight sinkW )
141 CV_Assert( i>=0 && i<(int)vtcs.size() );
143 TWeight dw = vtcs[i].weight;
148 flow += (sourceW < sinkW) ? sourceW : sinkW;
149 vtcs[i].weight = sourceW - sinkW;
152 template <class TWeight>
153 TWeight GCGraph<TWeight>::maxFlow()
155 const int TERMINAL = -1, ORPHAN = -2;
156 Vtx stub, *nilNode = &stub, *first = nilNode, *last = nilNode;
159 Vtx *vtxPtr = &vtcs[0];
160 Edge *edgePtr = &edges[0];
162 std::vector<Vtx*> orphans;
164 // initialize the active queue and the graph vertices
165 for( int i = 0; i < (int)vtcs.size(); i++ )
171 last = last->next = v;
173 v->parent = TERMINAL;
174 v->t = v->weight < 0;
180 last->next = nilNode;
183 // run the search-path -> augment-graph -> restore-trees loop
187 int e0 = -1, ei = 0, ej = 0;
188 TWeight minWeight, weight;
191 // grow S & T search trees, find an edge connecting them
192 while( first != nilNode )
198 for( ei = v->first; ei != 0; ei = edgePtr[ei].next )
200 if( edgePtr[ei^vt].weight == 0 )
202 u = vtxPtr+edgePtr[ei].dst;
208 u->dist = v->dist + 1;
212 last = last->next = u;
223 if( u->dist > v->dist+1 && u->ts <= v->ts )
225 // reassign the parent
228 u->dist = v->dist + 1;
234 // exclude the vertex from the active list
242 // find the minimum edge weight along the path
243 minWeight = edgePtr[e0].weight;
244 CV_Assert( minWeight > 0 );
245 // k = 1: source tree, k = 0: destination tree
246 for( int k = 1; k >= 0; k-- )
248 for( v = vtxPtr+edgePtr[e0^k].dst;; v = vtxPtr+edgePtr[ei].dst )
250 if( (ei = v->parent) < 0 )
252 weight = edgePtr[ei^k].weight;
253 minWeight = MIN(minWeight, weight);
254 CV_Assert( minWeight > 0 );
256 weight = fabs(v->weight);
257 minWeight = MIN(minWeight, weight);
258 CV_Assert( minWeight > 0 );
261 // modify weights of the edges along the path and collect orphans
262 edgePtr[e0].weight -= minWeight;
263 edgePtr[e0^1].weight += minWeight;
266 // k = 1: source tree, k = 0: destination tree
267 for( int k = 1; k >= 0; k-- )
269 for( v = vtxPtr+edgePtr[e0^k].dst;; v = vtxPtr+edgePtr[ei].dst )
271 if( (ei = v->parent) < 0 )
273 edgePtr[ei^(k^1)].weight += minWeight;
274 if( (edgePtr[ei^k].weight -= minWeight) == 0 )
276 orphans.push_back(v);
281 v->weight = v->weight + minWeight*(1-k*2);
284 orphans.push_back(v);
289 // restore the search trees by finding new parents for the orphans
291 while( !orphans.empty() )
293 Vtx* v2 = orphans.back();
296 int d, minDist = INT_MAX;
300 for( ei = v2->first; ei != 0; ei = edgePtr[ei].next )
302 if( edgePtr[ei^(vt^1)].weight == 0 )
304 u = vtxPtr+edgePtr[ei].dst;
305 if( u->t != vt || u->parent == 0 )
307 // compute the distance to the tree root
310 if( u->ts == curr_ts )
328 u = vtxPtr+edgePtr[ej].dst;
331 // update the distance
339 for( u = vtxPtr+edgePtr[ei].dst; u->ts != curr_ts; u = vtxPtr+edgePtr[u->parent].dst )
347 if( (v2->parent = e0) > 0 )
354 /* no parent is found */
356 for( ei = v2->first; ei != 0; ei = edgePtr[ei].next )
358 u = vtxPtr+edgePtr[ei].dst;
360 if( u->t != vt || !ej )
362 if( edgePtr[ei^(vt^1)].weight && !u->next )
365 last = last->next = u;
367 if( ej > 0 && vtxPtr+edgePtr[ej].dst == v2 )
369 orphans.push_back(u);
378 template <class TWeight>
379 bool GCGraph<TWeight>::inSourceSegment( int i )
381 CV_Assert( i>=0 && i<(int)vtcs.size() );
382 return vtcs[i].t == 0;