gcgraph.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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. #ifndef OPENCV_IMGPROC_DETAIL_GCGRAPH_HPP
  42. #define OPENCV_IMGPROC_DETAIL_GCGRAPH_HPP
  43. //! @cond IGNORED
  44. namespace cv { namespace detail {
  45. template <class TWeight> class GCGraph
  46. {
  47. public:
  48. GCGraph();
  49. GCGraph( unsigned int vtxCount, unsigned int edgeCount );
  50. ~GCGraph();
  51. void create( unsigned int vtxCount, unsigned int edgeCount );
  52. int addVtx();
  53. void addEdges( int i, int j, TWeight w, TWeight revw );
  54. void addTermWeights( int i, TWeight sourceW, TWeight sinkW );
  55. TWeight maxFlow();
  56. bool inSourceSegment( int i );
  57. private:
  58. class Vtx
  59. {
  60. public:
  61. Vtx *next; // initialized and used in maxFlow() only
  62. int parent;
  63. int first;
  64. int ts;
  65. int dist;
  66. TWeight weight;
  67. uchar t;
  68. };
  69. class Edge
  70. {
  71. public:
  72. int dst;
  73. int next;
  74. TWeight weight;
  75. };
  76. std::vector<Vtx> vtcs;
  77. std::vector<Edge> edges;
  78. TWeight flow;
  79. };
  80. template <class TWeight>
  81. GCGraph<TWeight>::GCGraph()
  82. {
  83. flow = 0;
  84. }
  85. template <class TWeight>
  86. GCGraph<TWeight>::GCGraph( unsigned int vtxCount, unsigned int edgeCount )
  87. {
  88. create( vtxCount, edgeCount );
  89. }
  90. template <class TWeight>
  91. GCGraph<TWeight>::~GCGraph()
  92. {
  93. }
  94. template <class TWeight>
  95. void GCGraph<TWeight>::create( unsigned int vtxCount, unsigned int edgeCount )
  96. {
  97. vtcs.reserve( vtxCount );
  98. edges.reserve( edgeCount + 2 );
  99. flow = 0;
  100. }
  101. template <class TWeight>
  102. int GCGraph<TWeight>::addVtx()
  103. {
  104. Vtx v;
  105. memset( &v, 0, sizeof(Vtx));
  106. vtcs.push_back(v);
  107. return (int)vtcs.size() - 1;
  108. }
  109. template <class TWeight>
  110. void GCGraph<TWeight>::addEdges( int i, int j, TWeight w, TWeight revw )
  111. {
  112. CV_Assert( i>=0 && i<(int)vtcs.size() );
  113. CV_Assert( j>=0 && j<(int)vtcs.size() );
  114. CV_Assert( w>=0 && revw>=0 );
  115. CV_Assert( i != j );
  116. if( !edges.size() )
  117. edges.resize( 2 );
  118. Edge fromI, toI;
  119. fromI.dst = j;
  120. fromI.next = vtcs[i].first;
  121. fromI.weight = w;
  122. vtcs[i].first = (int)edges.size();
  123. edges.push_back( fromI );
  124. toI.dst = i;
  125. toI.next = vtcs[j].first;
  126. toI.weight = revw;
  127. vtcs[j].first = (int)edges.size();
  128. edges.push_back( toI );
  129. }
  130. template <class TWeight>
  131. void GCGraph<TWeight>::addTermWeights( int i, TWeight sourceW, TWeight sinkW )
  132. {
  133. CV_Assert( i>=0 && i<(int)vtcs.size() );
  134. TWeight dw = vtcs[i].weight;
  135. if( dw > 0 )
  136. sourceW += dw;
  137. else
  138. sinkW -= dw;
  139. flow += (sourceW < sinkW) ? sourceW : sinkW;
  140. vtcs[i].weight = sourceW - sinkW;
  141. }
  142. template <class TWeight>
  143. TWeight GCGraph<TWeight>::maxFlow()
  144. {
  145. CV_Assert(!vtcs.empty());
  146. CV_Assert(!edges.empty());
  147. const int TERMINAL = -1, ORPHAN = -2;
  148. Vtx stub, *nilNode = &stub, *first = nilNode, *last = nilNode;
  149. int curr_ts = 0;
  150. stub.next = nilNode;
  151. Vtx *vtxPtr = &vtcs[0];
  152. Edge *edgePtr = &edges[0];
  153. std::vector<Vtx*> orphans;
  154. // initialize the active queue and the graph vertices
  155. for( int i = 0; i < (int)vtcs.size(); i++ )
  156. {
  157. Vtx* v = vtxPtr + i;
  158. v->ts = 0;
  159. if( v->weight != 0 )
  160. {
  161. last = last->next = v;
  162. v->dist = 1;
  163. v->parent = TERMINAL;
  164. v->t = v->weight < 0;
  165. }
  166. else
  167. v->parent = 0;
  168. }
  169. first = first->next;
  170. last->next = nilNode;
  171. nilNode->next = 0;
  172. // run the search-path -> augment-graph -> restore-trees loop
  173. for(;;)
  174. {
  175. Vtx* v, *u;
  176. int e0 = -1, ei = 0, ej = 0;
  177. TWeight minWeight, weight;
  178. uchar vt;
  179. // grow S & T search trees, find an edge connecting them
  180. while( first != nilNode )
  181. {
  182. v = first;
  183. if( v->parent )
  184. {
  185. vt = v->t;
  186. for( ei = v->first; ei != 0; ei = edgePtr[ei].next )
  187. {
  188. if( edgePtr[ei^vt].weight == 0 )
  189. continue;
  190. u = vtxPtr+edgePtr[ei].dst;
  191. if( !u->parent )
  192. {
  193. u->t = vt;
  194. u->parent = ei ^ 1;
  195. u->ts = v->ts;
  196. u->dist = v->dist + 1;
  197. if( !u->next )
  198. {
  199. u->next = nilNode;
  200. last = last->next = u;
  201. }
  202. continue;
  203. }
  204. if( u->t != vt )
  205. {
  206. e0 = ei ^ vt;
  207. break;
  208. }
  209. if( u->dist > v->dist+1 && u->ts <= v->ts )
  210. {
  211. // reassign the parent
  212. u->parent = ei ^ 1;
  213. u->ts = v->ts;
  214. u->dist = v->dist + 1;
  215. }
  216. }
  217. if( e0 > 0 )
  218. break;
  219. }
  220. // exclude the vertex from the active list
  221. first = first->next;
  222. v->next = 0;
  223. }
  224. if( e0 <= 0 )
  225. break;
  226. // find the minimum edge weight along the path
  227. minWeight = edgePtr[e0].weight;
  228. CV_Assert( minWeight > 0 );
  229. // k = 1: source tree, k = 0: destination tree
  230. for( int k = 1; k >= 0; k-- )
  231. {
  232. for( v = vtxPtr+edgePtr[e0^k].dst;; v = vtxPtr+edgePtr[ei].dst )
  233. {
  234. if( (ei = v->parent) < 0 )
  235. break;
  236. weight = edgePtr[ei^k].weight;
  237. minWeight = MIN(minWeight, weight);
  238. CV_Assert( minWeight > 0 );
  239. }
  240. weight = fabs(v->weight);
  241. minWeight = MIN(minWeight, weight);
  242. CV_Assert( minWeight > 0 );
  243. }
  244. // modify weights of the edges along the path and collect orphans
  245. edgePtr[e0].weight -= minWeight;
  246. edgePtr[e0^1].weight += minWeight;
  247. flow += minWeight;
  248. // k = 1: source tree, k = 0: destination tree
  249. for( int k = 1; k >= 0; k-- )
  250. {
  251. for( v = vtxPtr+edgePtr[e0^k].dst;; v = vtxPtr+edgePtr[ei].dst )
  252. {
  253. if( (ei = v->parent) < 0 )
  254. break;
  255. edgePtr[ei^(k^1)].weight += minWeight;
  256. if( (edgePtr[ei^k].weight -= minWeight) == 0 )
  257. {
  258. orphans.push_back(v);
  259. v->parent = ORPHAN;
  260. }
  261. }
  262. v->weight = v->weight + minWeight*(1-k*2);
  263. if( v->weight == 0 )
  264. {
  265. orphans.push_back(v);
  266. v->parent = ORPHAN;
  267. }
  268. }
  269. // restore the search trees by finding new parents for the orphans
  270. curr_ts++;
  271. while( !orphans.empty() )
  272. {
  273. Vtx* v2 = orphans.back();
  274. orphans.pop_back();
  275. int d, minDist = INT_MAX;
  276. e0 = 0;
  277. vt = v2->t;
  278. for( ei = v2->first; ei != 0; ei = edgePtr[ei].next )
  279. {
  280. if( edgePtr[ei^(vt^1)].weight == 0 )
  281. continue;
  282. u = vtxPtr+edgePtr[ei].dst;
  283. if( u->t != vt || u->parent == 0 )
  284. continue;
  285. // compute the distance to the tree root
  286. for( d = 0;; )
  287. {
  288. if( u->ts == curr_ts )
  289. {
  290. d += u->dist;
  291. break;
  292. }
  293. ej = u->parent;
  294. d++;
  295. if( ej < 0 )
  296. {
  297. if( ej == ORPHAN )
  298. d = INT_MAX-1;
  299. else
  300. {
  301. u->ts = curr_ts;
  302. u->dist = 1;
  303. }
  304. break;
  305. }
  306. u = vtxPtr+edgePtr[ej].dst;
  307. }
  308. // update the distance
  309. if( ++d < INT_MAX )
  310. {
  311. if( d < minDist )
  312. {
  313. minDist = d;
  314. e0 = ei;
  315. }
  316. for( u = vtxPtr+edgePtr[ei].dst; u->ts != curr_ts; u = vtxPtr+edgePtr[u->parent].dst )
  317. {
  318. u->ts = curr_ts;
  319. u->dist = --d;
  320. }
  321. }
  322. }
  323. if( (v2->parent = e0) > 0 )
  324. {
  325. v2->ts = curr_ts;
  326. v2->dist = minDist;
  327. continue;
  328. }
  329. /* no parent is found */
  330. v2->ts = 0;
  331. for( ei = v2->first; ei != 0; ei = edgePtr[ei].next )
  332. {
  333. u = vtxPtr+edgePtr[ei].dst;
  334. ej = u->parent;
  335. if( u->t != vt || !ej )
  336. continue;
  337. if( edgePtr[ei^(vt^1)].weight && !u->next )
  338. {
  339. u->next = nilNode;
  340. last = last->next = u;
  341. }
  342. if( ej > 0 && vtxPtr+edgePtr[ej].dst == v2 )
  343. {
  344. orphans.push_back(u);
  345. u->parent = ORPHAN;
  346. }
  347. }
  348. }
  349. }
  350. return flow;
  351. }
  352. template <class TWeight>
  353. bool GCGraph<TWeight>::inSourceSegment( int i )
  354. {
  355. CV_Assert( i>=0 && i<(int)vtcs.size() );
  356. return vtcs[i].t == 0;
  357. }
  358. }} // namespace detail, cv
  359. //! @endcond
  360. #endif // OPENCV_IMGPROC_DETAIL_GCGRAPH_HPP