00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef MLN_MORPHO_WATERSHED_TOPOLOGICAL_HH
00029 # define MLN_MORPHO_WATERSHED_TOPOLOGICAL_HH
00030
00040
00041 # include <vector>
00042 # include <map>
00043 # include <queue>
00044
00045 # include <mln/core/site_set/p_set.hh>
00046 # include <mln/core/site_set/p_priority.hh>
00047 # include <mln/core/site_set/p_queue_fast.hh>
00048
00049 # include <mln/util/ord.hh>
00050
00051 # include <mln/data/sort_psites.hh>
00052 # include <mln/data/fill.hh>
00053
00054
00055
00056
00057 namespace mln
00058 {
00059
00060 namespace morpho
00061 {
00062
00063 namespace watershed
00064 {
00065
00066 template <class I>
00067 mln_site(I) min (const Image<I> &ima_, p_set<mln_site(I)>& components)
00068 {
00069 const I& ima = exact(ima_);
00070
00071 if (components.nsites() == 0)
00072 return mln_site(I)(-1, -1);
00073
00074 typename p_set<mln_site(I)>::fwd_piter it(components);
00075 mln_site(I) min = components[0];
00076
00077 for_all(it)
00078 if (ima(it) < ima(min))
00079 min = it;
00080
00081 return min;
00082 }
00083
00084 template <class I>
00085 mln_site(I) max (p_set<mln_site(I)>& components)
00086 {
00087 if (components.nsites() == 0)
00088 return mln_site(I)(-1, -1);
00089
00090 typename p_set<mln_site(I)>::fwd_piter it(components);
00091 mln_site(I) max = components[0];
00092
00093 for_all(it)
00094 if (ima(it) > ima(max))
00095 max = it;
00096
00097 return max;
00098 }
00099
00100
00101
00102 template <class I, class N>
00103 struct topo_wst
00104 {
00105
00106
00107 typedef mln_site(I) site;
00108 typedef I image_t;
00109 typedef N neighborhood_t;
00110
00111
00112
00113 private:
00114 struct node {
00115 mln_value(I) level;
00116 int area;
00117 int highest;
00118 typedef mln_site(I) site;
00119
00120
00121 std::vector<site> children;
00122
00123 void addChildren(const node& n)
00124 {
00125
00126
00127
00128
00129
00130 for (unsigned i=0; i < n.children.size(); ++i)
00131 children.push_back(n.children[i]);
00132 }
00133
00134 void addChild(const site p)
00135 {
00136
00137 children.push_back(p);
00138 }
00139 };
00140
00141 public:
00142
00143 mln_ch_value(I, site) Par_node;
00144 mln_ch_value(I, site) Par_tree;
00145
00146 mln_ch_value(I, int) Rnk_tree;
00147 mln_ch_value(I, int) Rnk_node;
00148 mln_ch_value(I, site) subtreeRoot;
00149 mln_ch_value(I, node) nodes;
00150 site Root;
00151
00152 private:
00153
00154 void MakeSet_tree(site x);
00155 void MakeSet_node(site x);
00156 site Find_tree(site x);
00157 site Find_node(site x);
00158 void BuildComponentTree();
00159 site MergeNode(site& node1, site& node2);
00160 site Link_tree(site x, site y);
00161 site Link_node(site x, site y);
00162 node MakeNode(int level);
00163
00164 private:
00165 mln_ch_value(I, bool) isproc;
00166
00167
00168 public:
00169 topo_wst(const Image<I>& i,
00170 const Neighborhood<N>& n);
00171
00172 public:
00173 const I &ima;
00174 const N &nbh;
00175
00176 public:
00177 void go();
00178
00179 private:
00180 site min (p_set<site>& components);
00181 site max (p_set<site>& components);
00182 bool highest_fork (p_set<site>& components);
00183 bool highest_fork (p_set<site>& components, site &r);
00184
00185
00186
00187 public:
00188 site lca (site a, site b);
00189
00190 private:
00191 int *euler;
00192 int *depth;
00193 int ctree_size;
00194 std::map<site, int, mln::util::ord<site> > pos;
00195 site *repr;
00196
00197 int *minim;
00198 int **Minim;
00199
00200 void compute_ctree_size (site p);
00201 void build_euler_tour_rec(site p, int &position, int d);
00202 void build_euler_tour();
00203 void build_minim ();
00204 void removeOneSonNodes(site *p, mln_ch_value(I, site) &newPar_node);
00205 void compressTree();
00206 };
00207
00209 template <class T>
00210 typename T::image_t
00211 topological(T &tree);
00212
00213
00214
00215 # ifndef MLN_INCLUDE_ONLY
00216
00217
00218 template <class I, class N>
00219 topo_wst<I, N>::topo_wst(const Image<I>& i,
00220 const Neighborhood<N>& n)
00221 : ima(exact(i)), nbh(exact(n))
00222 {
00223 initialize(Par_node, i);
00224 initialize(Par_tree, i);
00225 initialize(Rnk_tree, i);
00226 initialize(Rnk_node, i);
00227 initialize(subtreeRoot, i);
00228 initialize(nodes, i);
00229 initialize(isproc, i);
00230 }
00231
00232 template <class I, class N>
00233 void topo_wst<I, N>::MakeSet_tree(site x)
00234 {
00235 Par_tree(x) = x;
00236 Rnk_tree(x) = 0;
00237 }
00238
00239 template <class I, class N>
00240 void topo_wst<I, N>::MakeSet_node(site x)
00241 {
00242 Par_node(x) = x;
00243 Rnk_node(x) = 0;
00244 }
00245
00246 template <class I, class N>
00247 typename topo_wst<I, N>::site topo_wst<I, N>::Find_tree(site x)
00248 {
00249 if (Par_tree(x) != x)
00250 Par_tree(x) = Find_tree(Par_tree(x));
00251 return Par_tree(x);
00252 }
00253
00254 template <class I, class N>
00255 typename topo_wst<I, N>::site topo_wst<I, N>::Find_node(site x)
00256 {
00257 if (Par_node(x) != x)
00258 Par_node(x) = Find_node(Par_node(x));
00259 return Par_node(x);
00260 }
00261
00262 template <class I, class N>
00263 void topo_wst<I, N>::go()
00264 {
00265 BuildComponentTree();
00266 compressTree();
00267
00268 build_euler_tour();
00269 build_minim();
00270 }
00271
00272 template <class I, class N>
00273 void topo_wst<I, N>::BuildComponentTree()
00274 {
00275
00276
00277
00278 p_array<mln_site(I)> S;
00279 S = data::sort_psites_increasing(ima);
00280
00281
00282 data::fill(isproc, false);
00283 for (int ip = 0; ip < int(S.nsites()); ++ip)
00284 {
00285 site p = S[ip];
00286 MakeSet_node(p);
00287 MakeSet_tree(p);
00288
00289 subtreeRoot(p) = p;
00290
00291 nodes(p) = MakeNode(ima(p));
00292 }
00293
00294
00295
00296 typename p_array<mln_site(I)>::fwd_piter ip(S);
00297 for_all(ip)
00298 {
00299 site p = ip.to_site();
00300
00301 site curCanonicalElt = Find_tree(p);
00302 site curNode = Find_node(subtreeRoot(curCanonicalElt));
00303
00304
00305 mln_niter(N) q(nbh, ip);
00306 for_all(q)
00307 if (ima.has(q) and isproc(q) and ima(q) <= ima(p))
00308 {
00309 site adjCanonicalElt = Find_tree(q);
00310 site adjNode = Find_node(subtreeRoot(adjCanonicalElt));
00311 if (curNode != adjNode)
00312 {
00313 if (nodes(curNode).level == nodes(adjNode).level)
00314 curNode = MergeNode(adjNode, curNode);
00315 else
00316 {
00317 nodes(curNode).addChild(adjNode);
00318 nodes(curNode).area += nodes(adjNode).area;
00319 nodes(curNode).highest += nodes(adjNode).highest;
00320 }
00321 }
00322
00323 curCanonicalElt = Link_tree(adjCanonicalElt, curCanonicalElt);
00324 subtreeRoot(curCanonicalElt) = curNode;
00325 }
00326 isproc(p) = true;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 mln_piter(I) r(Par_node.domain());
00336 for_all(r)
00337 Par_node(r) = Find_node(r);
00338
00339
00340
00341 mln_fwd_piter(I) rp(Par_node.domain());;
00342 rp.start();
00343
00344 Root = subtreeRoot(Find_tree(Find_node(rp)));
00345 }
00346
00347
00348 template <class I, class N>
00349 typename topo_wst<I, N>::site topo_wst<I, N>::MergeNode(site& node1,
00350 site& node2)
00351 {
00352 site tmpNode = Link_node(node1, node2);
00353 site tmpNode2;
00354 if (tmpNode == node2)
00355 {
00356 nodes(node2).addChildren(nodes(node1));
00357 tmpNode2 = node1;
00358 }
00359 else
00360 {
00361 nodes(node1).addChildren(nodes(node2));
00362 tmpNode2 = node2;
00363 }
00364 nodes(tmpNode).area += nodes(tmpNode2).area;
00365 nodes(tmpNode).highest += nodes(tmpNode2).highest;
00366 return tmpNode;
00367 }
00368
00369 template <class I, class N>
00370 typename topo_wst<I, N>::site topo_wst<I, N>::Link_tree(site x, site y)
00371 {
00372 if (Rnk_tree(x) > Rnk_tree(y))
00373 std::swap(x, y);
00374 else
00375 if (Rnk_tree(x) == Rnk_tree(y))
00376 Rnk_tree(y) += 1;
00377 Par_tree(x) = y;
00378 return y;
00379 }
00380
00381 template <class I, class N>
00382 typename topo_wst<I, N>::site topo_wst<I, N>::Link_node(site x, site y)
00383 {
00384 if (Rnk_node(x) > Rnk_node(y))
00385 std::swap(x, y);
00386 else
00387 if (Rnk_node(x) == Rnk_node(y))
00388 Rnk_node(y) += 1;
00389 Par_node(x) = y;
00390 return y;
00391 }
00392
00393 template <class I, class N>
00394 typename topo_wst<I, N>::node topo_wst<I, N>::MakeNode(int level)
00395 {
00396 node n;
00397 n.level = level;
00398 n.area = 1;
00399 n.highest = level;
00400 return n;
00401 }
00402
00403
00404 template <class I, class N>
00405 bool topo_wst<I, N>::highest_fork (p_set<site>& components, site &r)
00406 {
00407 if (components.nsites() == 0)
00408 {
00409 std::cerr << "highest fork : empty set" << std::endl;
00410 return false;
00411 }
00412
00413 site
00414 m = min(components),
00415 hfork = m;
00416
00417 typename p_set<site>::fwd_piter it(components);
00418 for_all(it)
00419 {
00420
00421 if (it.to_site() == m)
00422 continue;
00423
00424 site c = lca(hfork, it.to_site());
00425 if (c != it.to_site())
00426 hfork = c;
00427 }
00428
00429 if (nodes(m).level == nodes(hfork).level)
00430 return false;
00431
00432 r = hfork;
00433 return true;
00434 }
00435
00436 template <class I, class N>
00437 bool topo_wst<I, N>::highest_fork (p_set<site>& components) {
00438 site i;
00439 return highest_fork(components, i);
00440 }
00441
00442 template <class I, class N>
00443 void topo_wst<I, N>::compute_ctree_size (site p)
00444 {
00445 ctree_size += 1;
00446 node& n = nodes(p);
00447
00448
00449
00450
00451
00452 for (unsigned i=0; i < n.children.size(); ++i)
00453 compute_ctree_size(n.children[i]);
00454 }
00455
00456
00457 template <class I, class N>
00458 void topo_wst<I, N>::build_euler_tour_rec(site p, int &position, int d)
00459 {
00460 if (pos.find(p) == pos.end())
00461 pos[p] = position;
00462
00463 repr[position] = p;
00464 depth[position] = d;
00465 euler[position] = pos[p];
00466 ++position;
00467 node& n = nodes(p);
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 for (unsigned i=0; i < n.children.size(); ++i)
00480 {
00481 build_euler_tour_rec(n.children[i], position, d+1);
00482 depth[position] = d;
00483 euler[position] = pos[p];
00484 repr[position] = p;
00485 ++position;
00486 }
00487 }
00488
00489
00490 template <class I, class N>
00491 void topo_wst<I, N>::build_euler_tour ()
00492 {
00493 ctree_size = 0;
00494 compute_ctree_size(Root);
00495
00496 int size = 2 * ctree_size - 1;
00497
00498
00499 euler = new int[size];
00500 depth = new int[size];
00501 repr = new site[size];
00502
00503 int position = 0;
00504 build_euler_tour_rec(Root, position, 0);
00505 }
00506
00507
00508 template <class I, class N>
00509 void topo_wst<I, N>::build_minim ()
00510 {
00511
00512 int size = 2 * ctree_size - 1;
00513 int logn = (int)(ceil(log((double)(size))/log(2.0)));
00514
00515 minim = new int [logn * size];
00516 Minim = new int* [logn];
00517
00518 Minim[0] = minim;
00519
00520
00521 for (int i = 0; i < size - 1; ++i)
00522 if (depth[euler[i]] < depth[euler[i+1]]) {
00523 Minim[0][i] = i;
00524 } else {
00525 Minim[0][i] = i+1;
00526 }
00527
00528
00529
00530 int k;
00531 for (int j = 1; j < logn; j++) {
00532 k = 1 << (j - 1);
00533 Minim[j] = &minim[j * size];
00534 for (int i = 0; i < size; i++) {
00535 if ((i + (k << 1)) >= size) {
00536
00537 }
00538 else {
00539 if (depth[euler[Minim[j - 1][i]]]
00540 <= depth[euler[Minim[j - 1][i + k]]])
00541 Minim[j][i] = Minim[j - 1][i];
00542 else
00543 Minim[j][i] = Minim[j - 1][i + k];
00544 }
00545 }
00546 }
00547
00548 }
00549
00550
00551 template <class I, class N>
00552 typename topo_wst<I, N>::site topo_wst<I, N>::lca (site a, site b)
00553 {
00554 int
00555 m = pos[a],
00556 n = pos[b],
00557 k;
00558
00559 if (m == n)
00560 return repr[m];
00561
00562 if (m > n)
00563 {
00564 k = n;
00565 n = m;
00566 m = k;
00567 }
00568
00569 k = (int)(log((double)(n - m))/log(2.));
00570
00571 if (depth[euler[Minim[k][m]]] < depth[euler[Minim[k][n - (1 << k)]]]) {
00572 return repr[euler[Minim[k][m]]];
00573 } else {
00574 return repr[euler[Minim[k][n - (1 << k)]]];
00575 }
00576 }
00577
00578
00579 template <class I, class N>
00580 void topo_wst<I, N>::removeOneSonNodes(site *p,
00581 mln_ch_value(I, site) &newPar_node)
00582 {
00583 node &n = nodes(*p);
00584
00585 if (n.children.size() == 1)
00586 {
00587 n.area = -1;
00588 newPar_node(*p) = n.children[0];
00589 *p = n.children[0];
00590 removeOneSonNodes(p, newPar_node);
00591 }
00592 else
00593 {
00594 for (unsigned i = 0; i < n.children.size(); ++i)
00595 removeOneSonNodes(&(n.children[i]), newPar_node);
00596 }
00597 }
00598
00599
00600 template <class I, class N>
00601 void topo_wst<I, N>::compressTree()
00602 {
00603 mln_ch_value(I, site) newPar_node;
00604 initialize(newPar_node, Par_node);
00605
00606
00607 removeOneSonNodes(&Root, newPar_node);
00608
00609
00610 mln_piter(I) p(Par_node.domain());
00611 for_all(p)
00612 while (nodes(Par_node(p)).area == -1)
00613 Par_node(p) = newPar_node(Par_node(p));
00614 }
00615
00616 template <class T>
00617 bool w_constructible(T &tree, typename T::site p, typename T::site &r)
00618 {
00619
00620 typedef typename T::image_t I;
00621 typedef typename T::neighborhood_t N;
00622
00623 const I &ima = exact(tree.ima);
00624 const N &nbh = exact(tree.nbh);
00625
00626
00627 mln_niter(N) q(nbh, p);
00628 p_set<mln_site(I)> v;
00629
00630 for_all(q)
00631
00632
00633 if (ima.domain().has(q) && ima(q) < ima(p))
00634 v.insert(tree.Par_node(q));
00635
00636 if (v.nsites() == 0)
00637 return false;
00638
00639 if (v.nsites() == 1)
00640 {
00641 r = v[0];
00642 return true;
00643 }
00644
00645 mln_site(I) c = min(ima, v);
00646 mln_site(I) cmin = c;
00647
00648 typename p_set<mln_site(I)>::fwd_piter it(v);
00649 for_all(it)
00650 {
00651
00652 if (it.to_site() == cmin)
00653 continue;
00654
00655 mln_site(I) c1 = tree.lca(c, it);
00656
00657 if (c1 != it)
00658 c = c1;
00659 }
00660
00661 if (tree.nodes(c).level >= ima(p))
00662 return false;
00663
00664 r = c;
00665 return true;
00666 }
00667
00668 template <class T>
00669 bool w_constructible(T &tree, typename T::site p) {
00670 typename T::site r;
00671 return w_constructible(tree, p, r);
00672 }
00673
00674
00675
00676 template <class T>
00677 typename T::image_t topological(T &tree)
00678 {
00679
00680 typedef typename T::image_t I;
00681 typedef typename T::neighborhood_t N;
00682
00683 I ima = exact(tree.ima);
00684 const N &nbh = exact(tree.nbh);
00685
00686
00687 mln_ch_value(I, bool) cmax;
00688 initialize(cmax, ima);
00689
00690
00691 mln_ch_value(I, bool) enqueued;
00692 initialize(enqueued, ima);
00693
00694 p_priority< mln_value(I), p_queue_fast<mln_site(I)> > l;
00695
00696 std::queue<mln_site(I)> m;
00697 mln_value(I) min = mln_min(mln_value(I));
00698
00699 std::cout << "Init" << std::endl;
00700
00701
00702 data::fill(cmax, false);
00703 data::fill(enqueued, false);
00704
00705 mln_piter(I) it(tree.Par_node.domain());
00706 for_all(it)
00707
00708 if (tree.nodes(tree.Par_node(it)).children.size() == 0)
00709 {
00710 cmax(it) = true;
00711 m.push(it);
00712 }
00713
00714 while (!m.empty())
00715 {
00716
00717 mln_niter(N) q(nbh, m.front());
00718
00719
00720 for_all(q)
00721 if (cmax.domain().has(q) && !cmax(q) && !enqueued(q))
00722 {
00723 enqueued(q) = true;
00724 l.push(mln_max(mln_value(I)) - ima(q), q);
00725 }
00726 m.pop();
00727 }
00728
00729
00730 std::cout << "end" << std::endl;
00731
00732
00733 while (!l.is_empty())
00734 {
00735 mln_site(I) x = l.front();
00736 l.pop();
00737 enqueued(x) = false;
00738
00739 mln_site(I) c;
00740 bool is_w = w_constructible(tree, x, c);
00741
00742 if (is_w)
00743 {
00744 ima(x) = tree.nodes(c).level;
00745 tree.Par_node(x) = c;
00746
00747
00748 if (tree.nodes(c).children.size() == 0)
00749 cmax(x) = true;
00750 else
00751
00752 if (tree.nodes(c).children.size() == 1)
00753 std::cerr << "ERREUR COMPOSANTE BRANCHE "
00754 << tree.nodes(c).children.size() << std::endl;
00755
00756
00757
00758 mln_niter(N) q(nbh, x);
00759
00760
00761 for_all(q)
00762 if (ima.domain().has(q) && !cmax(q) && !enqueued(q))
00763 {
00764 enqueued(q) = true;
00765 l.push(mln_max(mln_value(I)) - ima(q), q);
00766
00767
00768
00769
00770 }
00771 }
00772 }
00773
00774 for_all(it)
00775 ima(it) = tree.nodes(tree.Par_node(it)).level;
00776
00777 return ima;
00778 }
00779
00780 # endif // MLN_INCLUDE_ONLY
00781
00782
00783 }
00784
00785 }
00786
00787 }
00788
00789 #endif // ! MLN_MORPHO_WATERSHED_TOPOLOGICAL_HH