basic_najman.hh

00001 // Copyright (C) 2006  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016 // Boston, MA 02110-1301, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef OLENA_LRDE_UFMT_BASIC_NAJMAN_HH
00029 # define OLENA_LRDE_UFMT_BASIC_NAJMAN_HH
00030 
00031 # include <list>
00032 
00033 # include <oln/level/fill.hh>
00034 # include <oln/lrde/ufmt/utils.hh>
00035 # include <oln/lrde/ufmt/ap_maxtree.hh>
00036 
00037 
00038 namespace oln
00039 {
00040 
00041   namespace lrde
00042   {
00043 
00044     namespace ufmt
00045     {
00046 
00047       template <class I>
00048       struct basic_najman : public ap_maxtree<I>
00049       {
00050         typedef ap_maxtree<I> super;
00051         using super::f;
00052         using super::nbh;
00053         using super::par;
00054         oln_lrde_ufmt_import_ap_maxtree_typedefs;
00055 
00056         struct node {
00057           int level;
00058           int area;
00059           int highest;
00060           std::list<point> children;
00061 
00062           void addChildren(const node& n)
00063           {
00064             typename std::list<point>::const_iterator it;
00065             for (it = n.children.begin();
00066                  it != n.children.end();
00067                  ++it)
00068               children.push_back((*it));
00069           }
00070           void addChild(const point n)
00071           {
00072             children.push_back(n);
00073           }
00074         };
00075 
00076         image2d<point> Par_tree;
00077         // Par_node is handled by par (from ap_maxtree)
00078         image2d<int> Rnk_tree;
00079         image2d<int> Rnk_node;
00080         image2d<point> lowestNode;
00081         image2d<node> nodes;
00082         image2d<bool> isproc;
00083         point Root;
00084         std::vector<point> S;
00085         // std::map<point,point> M; // to keep the root of any point.
00086 
00087         
00088         basic_najman(const abstract::image<I>& f,
00089                      const oln_neighborhood_type(I)& nbh)
00090           : ap_maxtree<I>(f, nbh),
00091           Par_tree(f.size()),
00092           Rnk_tree(f.size()),
00093           Rnk_node(f.size()),
00094           lowestNode(f.size()),
00095           nodes(f.size()),
00096           isproc(f.size())
00097         {
00098         }
00099 
00100         void MakeSet_tree(point x)
00101         {
00102           Par_tree[x] = x;
00103           Rnk_tree[x] = 0;
00104         }
00105 
00106         void MakeSet_node(point x)
00107         {
00108           par[x] = x; // was Par_node[x] = x;
00109           Rnk_node[x] = 0;
00110         }
00111 
00112         point Find_tree(point x)
00113         {
00114           if (Par_tree[x] != x)
00115             Par_tree[x] = Find_tree(Par_tree[x]);
00116           return Par_tree[x];
00117         }
00118 
00119         point Find_node(point x)
00120         {
00121           return find_level_root(x);
00122         }
00123 
00124         void go()
00125         {
00126           init();
00127           BuildComponentTree();
00128         }
00129 
00130         void init()
00131         {
00132           S = histogram_reverse_sort_p(f);
00133           level::fill(isproc, false);
00134           for (int ip = 0; ip < int(S.size()); ++ip)
00135             {
00136               point p = S[ip];
00137               MakeSet_node(p);
00138               MakeSet_tree(p);
00139 //            if (lowestNode.hold(p))
00140               lowestNode[p] = p;
00141 //            if (nodes.hold(p))
00142               nodes[p] = MakeNode(f[p]);
00143             }
00144         }
00145 
00146         void BuildComponentTree()
00147         {
00148           for (int ip = 0; ip < int(S.size()); ++ip)
00149             {
00150               point p = S[ip];
00151               isproc[p] = true;
00152               
00153               point curTree = Find_tree(p);
00154               point curNode = Find_node(lowestNode[curTree]);
00155 
00156               oln_neighb_type(Nbh) q(nbh, p);
00157               for_all(q)
00158                 if (f.hold(q) and isproc[q] and f[q] >= f[p]) // f[q] >= f[p] parce qu'on prend l'ordre de l'histogramme
00159                   {
00160                     point adjTree = Find_tree(q);
00161                     point adjNode = Find_node(lowestNode[adjTree]);
00162                     if (curNode != adjNode)
00163                       {
00164                         if (nodes[curNode].level == nodes[adjNode].level)
00165                           curNode = MergeNode(adjNode, curNode);
00166                         else
00167                           {
00168                             // we have nodes[curNode].level < nodes[adjNode].level
00169                             nodes[curNode].addChild(adjNode);
00170                             //apparemment NON :Par_node[adjNode] = curNode; // car adjNode devient fils de curNode
00171                             nodes[curNode].area += nodes[adjNode].area;
00172                             nodes[curNode].highest += nodes[adjNode].highest;
00173                           }
00174                       }
00175                     curTree = Link_tree(adjTree, curTree);
00176                     lowestNode[curTree] = curNode;
00177                   }
00178             }
00179           Root = lowestNode[Find_tree(Find_node(point(0, 0)))];
00180           // Pour garder une map de correspondance point <-> local_root
00181 //            for (int ip = 0; ip < int(S.size()); ++ip)
00182 //              {
00183 //                point p = S[ip];
00184 //             M(p) = Find_node(p);
00185 //           }
00186         }
00187 
00188         point MergeNode(point& node1, point& node2)
00189         {
00190           point tmpNode = Link_node(node1, node2);
00191           point tmpNode2;
00192           if (tmpNode == node2)
00193             {
00194               nodes[node2].addChildren(nodes[node1]);
00195               tmpNode2 = node1;
00196             }
00197           else
00198             {
00199               nodes[node1].addChildren(nodes[node2]);
00200               tmpNode2 = node2;
00201             }
00202           nodes[tmpNode].area += nodes[tmpNode2].area;
00203           nodes[tmpNode].highest += nodes[tmpNode2].highest;
00204           return tmpNode;
00205         }
00206 
00207         point Link_tree(point x, point y)
00208         {
00209           if (Rnk_tree[x] > Rnk_tree[y])
00210             swap(x, y);
00211           else
00212             if (Rnk_tree[x] == Rnk_tree[y])
00213               Rnk_tree[y] += 1;
00214           Par_tree[x] = y;
00215           return y;
00216         }
00217         
00218         point Link_node(point x, point y)
00219         {
00220           if (Rnk_node[x] > Rnk_node[y])
00221             swap(x, y);
00222           else
00223             if (Rnk_node[x] == Rnk_node[y])
00224               Rnk_node[y] += 1;
00225           par[x] = y; // was Par_node[x] = y;
00226           return y;
00227         }
00228         
00229         node MakeNode(int level)
00230         {
00231           node n;
00232           n.level = level;
00233           n.area = 1;
00234           n.highest = level;
00235           return n;
00236         }
00237 
00238 //      void image_output(image2d<point>& img)
00239 //      {
00240 //        for(int i = 0; i < img.nrows(); ++i)
00241 //          {
00242 //            for(int j = 0; j < img.ncols(); ++j)
00243 //              {
00244 //                int l = (img[point(i, j)]).row() * img.ncols() + (img[point(i, j)]).col();
00245 //                std::cout << " " << l << " ";
00246 //              }
00247 //            std::cout << std::endl;
00248 //          }
00249 //      }
00250 
00251 
00252 
00253 //      void print_tree(point p)
00254 //      {
00255 //        node& n = nodes[p];
00256 //        std::cout << "point " << p << "=" << (p.row() * lowestNode.ncols() + p.col()) << " : ";
00257 
00258 //        typename std::list<point>::const_iterator it;
00259 //        for (it = n.children.begin();
00260 //             it != n.children.end();
00261 //             ++it)
00262 //          {
00263 //            point q = *it;
00264 //            std::cout << q << "=" << (q.row() * lowestNode.ncols() + q.col()) << " ";
00265 //          }
00266 //        std::cout << std::endl;
00267 
00268 //        for (it = n.children.begin();
00269 //             it != n.children.end();
00270 //             ++it)
00271 //          print_tree(*it);
00272 //      }
00273 
00274       }; // end of struct basic_najman
00275       
00276     } // end of namespace oln::lrde::ufmt
00277 
00278   } // end of namespace oln::lrde
00279 
00280 } // end of namespace oln
00281 
00282 
00283 #endif // ! OLENA_LRDE_UFMT_BASIC_NAJMAN_HH

Generated on Tue Feb 20 20:18:29 2007 for Olena by  doxygen 1.5.1