EstervQrCode 2.0.0
Library for qr code manipulation
Loading...
Searching...
No Matches
gcgraph.hpp
1/*M///////////////////////////////////////////////////////////////////////////////////////
2//
3// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4//
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.
8//
9//
10// Intel License Agreement
11// For Open Source Computer Vision Library
12//
13// Copyright (C) 2000, Intel Corporation, all rights reserved.
14// Third party copyrights are property of their respective owners.
15//
16// Redistribution and use in source and binary forms, with or without modification,
17// are permitted provided that the following conditions are met:
18//
19// * Redistribution's of source code must retain the above copyright notice,
20// this list of conditions and the following disclaimer.
21//
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.
25//
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.
28//
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.
39//
40//M*/
41
42#ifndef OPENCV_IMGPROC_DETAIL_GCGRAPH_HPP
43#define OPENCV_IMGPROC_DETAIL_GCGRAPH_HPP
44
46
47namespace cv { namespace detail {
48template <class TWeight> class GCGraph
49{
50public:
51 GCGraph();
52 GCGraph( unsigned int vtxCount, unsigned int edgeCount );
53 ~GCGraph();
54 void create( unsigned int vtxCount, unsigned int edgeCount );
55 int addVtx();
56 void addEdges( int i, int j, TWeight w, TWeight revw );
57 void addTermWeights( int i, TWeight sourceW, TWeight sinkW );
58 TWeight maxFlow();
59 bool inSourceSegment( int i );
60private:
61 class Vtx
62 {
63 public:
64 Vtx *next; // initialized and used in maxFlow() only
65 int parent;
66 int first;
67 int ts;
68 int dist;
69 TWeight weight;
70 uchar t;
71 };
72 class Edge
73 {
74 public:
75 int dst;
76 int next;
77 TWeight weight;
78 };
79
82 TWeight flow;
83};
84
85template <class TWeight>
86GCGraph<TWeight>::GCGraph()
87{
88 flow = 0;
89}
90template <class TWeight>
91GCGraph<TWeight>::GCGraph( unsigned int vtxCount, unsigned int edgeCount )
92{
93 create( vtxCount, edgeCount );
94}
95template <class TWeight>
96GCGraph<TWeight>::~GCGraph()
97{
98}
99template <class TWeight>
100void GCGraph<TWeight>::create( unsigned int vtxCount, unsigned int edgeCount )
101{
102 vtcs.reserve( vtxCount );
103 edges.reserve( edgeCount + 2 );
104 flow = 0;
105}
106
107template <class TWeight>
108int GCGraph<TWeight>::addVtx()
109{
110 Vtx v;
111 memset( &v, 0, sizeof(Vtx));
112 vtcs.push_back(v);
113 return (int)vtcs.size() - 1;
114}
115
116template <class TWeight>
117void GCGraph<TWeight>::addEdges( int i, int j, TWeight w, TWeight revw )
118{
119 CV_Assert( i>=0 && i<(int)vtcs.size() );
120 CV_Assert( j>=0 && j<(int)vtcs.size() );
121 CV_Assert( w>=0 && revw>=0 );
122 CV_Assert( i != j );
123
124 if( !edges.size() )
125 edges.resize( 2 );
126
127 Edge fromI, toI;
128 fromI.dst = j;
129 fromI.next = vtcs[i].first;
130 fromI.weight = w;
131 vtcs[i].first = (int)edges.size();
132 edges.push_back( fromI );
133
134 toI.dst = i;
135 toI.next = vtcs[j].first;
136 toI.weight = revw;
137 vtcs[j].first = (int)edges.size();
138 edges.push_back( toI );
139}
140
141template <class TWeight>
142void GCGraph<TWeight>::addTermWeights( int i, TWeight sourceW, TWeight sinkW )
143{
144 CV_Assert( i>=0 && i<(int)vtcs.size() );
145
146 TWeight dw = vtcs[i].weight;
147 if( dw > 0 )
148 sourceW += dw;
149 else
150 sinkW -= dw;
151 flow += (sourceW < sinkW) ? sourceW : sinkW;
152 vtcs[i].weight = sourceW - sinkW;
153}
154
155template <class TWeight>
156TWeight GCGraph<TWeight>::maxFlow()
157{
158 CV_Assert(!vtcs.empty());
159 CV_Assert(!edges.empty());
160 const int TERMINAL = -1, ORPHAN = -2;
161 Vtx stub, *nilNode = &stub, *first = nilNode, *last = nilNode;
162 int curr_ts = 0;
163 stub.next = nilNode;
164 Vtx *vtxPtr = &vtcs[0];
165 Edge *edgePtr = &edges[0];
166
167 std::vector<Vtx*> orphans;
168
169 // initialize the active queue and the graph vertices
170 for( int i = 0; i < (int)vtcs.size(); i++ )
171 {
172 Vtx* v = vtxPtr + i;
173 v->ts = 0;
174 if( v->weight != 0 )
175 {
176 last = last->next = v;
177 v->dist = 1;
178 v->parent = TERMINAL;
179 v->t = v->weight < 0;
180 }
181 else
182 v->parent = 0;
183 }
184 first = first->next;
185 last->next = nilNode;
186 nilNode->next = 0;
187
188 // run the search-path -> augment-graph -> restore-trees loop
189 for(;;)
190 {
191 Vtx* v, *u;
192 int e0 = -1, ei = 0, ej = 0;
193 TWeight minWeight, weight;
194 uchar vt;
195
196 // grow S & T search trees, find an edge connecting them
197 while( first != nilNode )
198 {
199 v = first;
200 if( v->parent )
201 {
202 vt = v->t;
203 for( ei = v->first; ei != 0; ei = edgePtr[ei].next )
204 {
205 if( edgePtr[ei^vt].weight == 0 )
206 continue;
207 u = vtxPtr+edgePtr[ei].dst;
208 if( !u->parent )
209 {
210 u->t = vt;
211 u->parent = ei ^ 1;
212 u->ts = v->ts;
213 u->dist = v->dist + 1;
214 if( !u->next )
215 {
216 u->next = nilNode;
217 last = last->next = u;
218 }
219 continue;
220 }
221
222 if( u->t != vt )
223 {
224 e0 = ei ^ vt;
225 break;
226 }
227
228 if( u->dist > v->dist+1 && u->ts <= v->ts )
229 {
230 // reassign the parent
231 u->parent = ei ^ 1;
232 u->ts = v->ts;
233 u->dist = v->dist + 1;
234 }
235 }
236 if( e0 > 0 )
237 break;
238 }
239 // exclude the vertex from the active list
240 first = first->next;
241 v->next = 0;
242 }
243
244 if( e0 <= 0 )
245 break;
246
247 // find the minimum edge weight along the path
248 minWeight = edgePtr[e0].weight;
249 CV_Assert( minWeight > 0 );
250 // k = 1: source tree, k = 0: destination tree
251 for( int k = 1; k >= 0; k-- )
252 {
253 for( v = vtxPtr+edgePtr[e0^k].dst;; v = vtxPtr+edgePtr[ei].dst )
254 {
255 if( (ei = v->parent) < 0 )
256 break;
257 weight = edgePtr[ei^k].weight;
258 minWeight = MIN(minWeight, weight);
259 CV_Assert( minWeight > 0 );
260 }
261 weight = fabs(v->weight);
262 minWeight = MIN(minWeight, weight);
263 CV_Assert( minWeight > 0 );
264 }
265
266 // modify weights of the edges along the path and collect orphans
267 edgePtr[e0].weight -= minWeight;
268 edgePtr[e0^1].weight += minWeight;
269 flow += minWeight;
270
271 // k = 1: source tree, k = 0: destination tree
272 for( int k = 1; k >= 0; k-- )
273 {
274 for( v = vtxPtr+edgePtr[e0^k].dst;; v = vtxPtr+edgePtr[ei].dst )
275 {
276 if( (ei = v->parent) < 0 )
277 break;
278 edgePtr[ei^(k^1)].weight += minWeight;
279 if( (edgePtr[ei^k].weight -= minWeight) == 0 )
280 {
281 orphans.push_back(v);
282 v->parent = ORPHAN;
283 }
284 }
285
286 v->weight = v->weight + minWeight*(1-k*2);
287 if( v->weight == 0 )
288 {
289 orphans.push_back(v);
290 v->parent = ORPHAN;
291 }
292 }
293
294 // restore the search trees by finding new parents for the orphans
295 curr_ts++;
296 while( !orphans.empty() )
297 {
298 Vtx* v2 = orphans.back();
299 orphans.pop_back();
300
301 int d, minDist = INT_MAX;
302 e0 = 0;
303 vt = v2->t;
304
305 for( ei = v2->first; ei != 0; ei = edgePtr[ei].next )
306 {
307 if( edgePtr[ei^(vt^1)].weight == 0 )
308 continue;
309 u = vtxPtr+edgePtr[ei].dst;
310 if( u->t != vt || u->parent == 0 )
311 continue;
312 // compute the distance to the tree root
313 for( d = 0;; )
314 {
315 if( u->ts == curr_ts )
316 {
317 d += u->dist;
318 break;
319 }
320 ej = u->parent;
321 d++;
322 if( ej < 0 )
323 {
324 if( ej == ORPHAN )
325 d = INT_MAX-1;
326 else
327 {
328 u->ts = curr_ts;
329 u->dist = 1;
330 }
331 break;
332 }
333 u = vtxPtr+edgePtr[ej].dst;
334 }
335
336 // update the distance
337 if( ++d < INT_MAX )
338 {
339 if( d < minDist )
340 {
341 minDist = d;
342 e0 = ei;
343 }
344 for( u = vtxPtr+edgePtr[ei].dst; u->ts != curr_ts; u = vtxPtr+edgePtr[u->parent].dst )
345 {
346 u->ts = curr_ts;
347 u->dist = --d;
348 }
349 }
350 }
351
352 if( (v2->parent = e0) > 0 )
353 {
354 v2->ts = curr_ts;
355 v2->dist = minDist;
356 continue;
357 }
358
359 /* no parent is found */
360 v2->ts = 0;
361 for( ei = v2->first; ei != 0; ei = edgePtr[ei].next )
362 {
363 u = vtxPtr+edgePtr[ei].dst;
364 ej = u->parent;
365 if( u->t != vt || !ej )
366 continue;
367 if( edgePtr[ei^(vt^1)].weight && !u->next )
368 {
369 u->next = nilNode;
370 last = last->next = u;
371 }
372 if( ej > 0 && vtxPtr+edgePtr[ej].dst == v2 )
373 {
374 orphans.push_back(u);
375 u->parent = ORPHAN;
376 }
377 }
378 }
379 }
380 return flow;
381}
382
383template <class TWeight>
384bool GCGraph<TWeight>::inSourceSegment( int i )
385{
386 CV_Assert( i>=0 && i<(int)vtcs.size() );
387 return vtcs[i].t == 0;
388}
389
390}} // namespace detail, cv
391
392
394
395#endif // OPENCV_IMGPROC_DETAIL_GCGRAPH_HPP
T back(T... args)
T empty(T... args)
T fabs(T... args)
CvArr * dst
Definition core_c.h:875
void * parent
Definition core_c.h:1913
const void * first
Definition core_c.h:1906
unsigned char uchar
Definition interface.h:51
#define MIN(a, b)
Definition cvdef.h:513
#define CV_Assert(expr)
Checks a condition at runtime and throws exception if it fails.
Definition base.hpp:342
CvArr * edges
Definition imgproc_c.h:860
CV_EXPORTS OutputArray int double double InputArray OutputArray int int bool double k
Definition imgproc.hpp:2133
InputArray int InputArray CV_IN_OUT Ptr< float > OutputArray flow
Definition imgproc.hpp:3388
OutputArray dst
Definition imgproc.hpp:3564
T memset(T... args)
"black box" representation of the file storage associated with a file on disk.
Definition calib3d.hpp:441
T next(T... args)
T pop_back(T... args)
T push_back(T... args)