hpc_maxtree.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_HPC_MAXTREE_HH
00029 # define OLENA_LRDE_UFMT_HPC_MAXTREE_HH
00030 
00031 # include <oln/level/fill.hh>
00032 # include <oln/lrde/ufmt/utils.hh>
00033 # include <oln/lrde/ufmt/ap_maxtree.hh>
00034 # include <oln/lrde/ufmt/attributes.hh>
00035 
00036 
00037 
00038 namespace oln
00039 {
00040 
00041   namespace lrde
00042   {
00043 
00044     namespace ufmt
00045     {
00046 
00047       // FIXME: doc.
00048 
00049       template <class I>
00050       struct hpc_maxtree : public ap_maxtree<I>
00051       {
00052         typedef ap_maxtree<I> super;
00053         using super::f;
00054         using super::nbh;
00055         using super::par;
00056         oln_lrde_ufmt_import_ap_maxtree_typedefs;
00057 
00058         // aux data
00059         std::vector<point> S;
00060         std::vector<size_t> H;
00061         std::vector<dpoint> dp_pre, dp_post;
00062         unsigned nb;
00063         unsigned nnodes;
00064         typename mute<I, unsigned>::ret label;
00065 
00066 
00067         // ctor
00068 
00069         hpc_maxtree(const abstract::image<I>& f,
00070                    const oln_neighborhood_type(I)& nbh)
00071           :
00072           super(f, nbh),
00073           label(f.size())
00074         {
00075         }
00076 
00077         template <class A> // void if no attributes
00078         void go()
00079         {
00080           init();
00081           compute_parent();  // 1st pass
00082           extract_maxtree<A>(); // 2nd pass
00083         }
00084 
00085         void init()
00086         {
00087           S = histogram_reverse_sort_p(f, H);
00088           nb = split<I>(nbh, dp_pre, dp_post);
00089           nnodes = 0;
00090         }
00091 
00092         void compute_parent()
00093         {
00094           int i = 0;
00095           for (int h = uint_nvalues(f) - 1; h >= 0; --h)
00096             {
00097               int i_first = i;
00098               int i_last  = i_first + H[h];
00099 
00100               // union-find
00101 
00102               for (i = i_first; i < i_last; ++i)
00103                 {
00104                   point p = S[i];
00105                   make_set(p);
00106                   // pre
00107                   for (unsigned j = 0; j < nb; ++j)
00108                     {
00109                       point n = p + dp_pre[j];
00110                       if (f.hold(n) and f[n] >= h)
00111                         do_union(n, p, h);
00112                     }
00113                   // post
00114                   for (unsigned j = 0; j < nb; ++j)
00115                     {
00116                       point n = p + dp_post[j];
00117                       if (f.hold(n) and f[n] > h)
00118                         do_union(n, p, h);
00119                     }
00120                 }
00121 
00122               // enhancing level compression:
00123               //   we compress within 'level h' but we can end up with:
00124               //   p' @ h+ --> p @ h --> lr @ h
00125               //   so we have p -> lr for all p at level h
00126               //   but p' --> p cannot be compressed by the code below
00127               for (int k = i_last - 1; k >= i_first; --k)
00128                 {
00129                   point p = S[k];
00130                   if (is_root(p))
00131                     ++nnodes;
00132                   else
00133                     par[p] = par[par[p]];
00134                 }
00135             } // end of "for all h"
00136         }
00137 
00138 
00139         template <class A> // A for attributes
00140         std::vector< node_<A> >
00141         extract_maxtree()
00142         {
00143           std::vector< node_<A> > node(nnodes);
00144 
00145           // bkd
00146           unsigned cur_l = nnodes - 1;
00147           for (int i = S.size() - 1; i != 0; --i)
00148             {
00149               point p = S[i];
00150 
00151               // nota: level compression is not completed here;
00152               // however, though it is useless to finalize it, the
00153               // code to perform completion is given but commented
00154               if (is_level_root(p))
00155                 {
00156                   /*
00157                   // completing level compression:
00158 
00159                   if (not is_level_root(par[p]))
00160                   {
00161                     // Cf. above comments; here we have
00162                     // p @ h+ --> par[p] @ h --> lr @ h
00163                     if (not is_root(p))
00164                       {
00165                         assert(f[p] > f[par[p]]);
00166                         assert(f[par[p]] == f[par[par[p]]]);
00167                         assert(is_level_root(par[par[p]]));
00168                       }
00169                     par[p] = par[par[p]];
00170                   }
00171                   // now the level compression is completed!
00172                   assert(is_level_root(par[p]));
00173                   */
00174 
00175                   // node initialization
00176                   label[p] = cur_l;
00177                   node[cur_l].par = label[par[p]];
00178                   --cur_l;
00179                 }
00180               else
00181                 // label propagation
00182                 label[p] = label[par[p]];
00183             }
00184           return node;
00185         }
00186 
00187 
00188         template <class A> // A for attributes
00189         void compute_attributes(std::vector< node_<A> >& node)
00190           // point-wise version
00191         {
00192           for (int i = S.size() - 1; i != 0; --i)
00193             {
00194               point p = S[i];
00195               if (is_level_root(p))
00196                 node[label[p]].init(f, p);
00197               else
00198                 node[label[p]].insert(f, p);
00199             }
00200           for (int l = 0; l < nnodes; ++l)
00201             if (node[l].par != l) // not root node
00202               node[node[l].par].embrace(node[l]);
00203         }
00204 
00205         void make_set(const point& x)
00206         {
00207           par[x] = x;
00208         }
00209 
00210         bool is_root(const point& x) const
00211         {
00212           return par[x] == x;
00213         }
00214 
00215         bool is_level_root(const point& x) const
00216         {
00217           return is_root(x) or f[par[x]] < f[x];
00218         }
00219 
00220         point find_level_root(const point& x)
00221         {
00222           if (is_level_root(x))
00223             return x;
00224           else
00225             return par[x] = find_level_root(par[x]);
00226         }
00227 
00228         point find_root(point x, value h)
00229         {
00230           while (not is_root(x))
00231             if (f[x] > h)
00232               x = par[x];
00233             else
00234               x = find_level_root(par[x]);
00235           return x;
00236         }
00237 
00238         void do_union(const point& n, const point& p, value h)
00239         {
00240           point r = find_root(n, h);
00241           if (r != p)
00242             par[r] = p;
00243         }
00244 
00245 
00246       }; // end of class hpc_maxtree
00247 
00248 
00249 
00250     } // end of namespace oln::lrde::ufmt
00251 
00252   } // end of namespace oln::lrde
00253 
00254 } // end of namespace oln
00255 
00256 
00257 #endif // ! OLENA_LRDE_UFMT_HPC_MAXTREE_HH

Generated on Tue Feb 20 20:19:52 2007 for Olena by  doxygen 1.5.1