hdc_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_HDC_MAXTREE_HH
00029 # define OLENA_LRDE_UFMT_HDC_MAXTREE_HH
00030 
00031 # include <oln/level/fill.hh>
00032 # include <oln/lrde/ufmt/utils.hh>
00033 # include <oln/lrde/ufmt/ad_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 
00048       // FIXME: make it more generic! and move it...
00049 
00050       template <class T>
00051       std::vector<int> to_index(const image2d<T>& input,
00052                                 const std::vector<dpoint2d>& dp_)
00053       {
00054         std::vector<int> dp(dp_.size());
00055         for (unsigned i = 0; i < dp_.size(); ++i)
00056           dp[i] = dp_[i].row() * (input.ncols() + 2 * input.border()) + dp_[i].col();
00057         return dp;
00058       }
00059 
00060 
00061 
00062 
00063       // FIXME: doc.
00064 
00065       template <class I>
00066       struct hdc_maxtree : public ad_maxtree<I>
00067       {
00068         typedef ad_maxtree<I> super;
00069         using super::f;
00070         using super::dpar;
00071         oln_lrde_ufmt_import_ad_maxtree_typedefs;
00072 
00073         const oln_neighborhood_type(I)& nbh;
00074 
00075         // aux data
00076         std::vector<int> S;
00077         std::vector<size_t> H;
00078         std::vector<oln_dpoint_type(I)> dp_pre_, dp_post_; // temp
00079         std::vector<int> dp_pre, dp_post;
00080         unsigned nb;
00081         unsigned nnodes;
00082 
00083 
00084         // ctor
00085 
00086         hdc_maxtree(const abstract::image<I>& f,
00087                    const oln_neighborhood_type(I)& nbh)
00088           :
00089           super(f),
00090           nbh(nbh)
00091         {
00092         }
00093 
00094         template <class A> // void if no attributes
00095         void go()
00096         {
00097           init();
00098           compute_parent();  // 1st pass
00099           extract_maxtree<A>(); // 2nd pass
00100         }
00101 
00102         void init()
00103         {
00104           S = histogram_reverse_sort_i(f.real(), H);
00105           nb = split<I>(nbh, dp_pre_, dp_post_);
00106           dp_pre  = to_index(f.real(), dp_pre_);
00107           dp_post = to_index(f.real(), dp_post_);
00108           nnodes = 0;
00109           dpar.memset_0();
00110         }
00111 
00112         void compute_parent()
00113         {
00114           int ip = 0;
00115           for (int h = uint_nvalues(f.real()) - 1; h >= 0; --h)
00116             {
00117               int ip_first = ip;
00118               int ip_last = ip + H[h];
00119 
00120               // union-find
00121 
00122               for (ip = ip_first; ip < ip_last; ++ip)
00123                 {
00124                   point p = S[ip];
00125                   // pre
00126                   for (unsigned i = 0; i < nb; ++i)
00127                     {
00128                       point n = p + dp_pre[i];
00129                       if (f[n] >= h)
00130                         do_union(n, p, h);
00131                     }
00132                   // post
00133                   for (unsigned i = 0; i < nb; ++i)
00134                     {
00135                       point n = p + dp_post[i];
00136                       if (f[n] > h)
00137                         do_union(n, p, h);
00138                     }
00139                 }
00140 
00141               // finalizing level compression
00142 
00143               for (int i = ip_last - 1; i >= ip_first; --i)
00144                 {
00145                   point p = S[i];
00146                   if (is_root(p))
00147                     ++nnodes;
00148                   else
00149                     dpar[p] += dpar[p + dpar[p]];
00150                 }
00151               
00152             } // end of "for all h"
00153         }
00154 
00155 
00156         template <class A> // A for attributes
00157         std::vector< node_<A> >
00158         extract_maxtree()
00159         {
00160           std::vector< node_<A> > node(nnodes);
00161           dpar_t& label = dpar;
00162 
00163           // bkd
00164           unsigned cur_l = nnodes - 1;
00165           for (int i = S.size() - 1; i != 0; --i)
00166             {
00167               point p = S[i];
00168               assert(is_level_root(p + dpar[p])); // level compression is total
00169               if (is_level_root(p))
00170                 {
00171                   // node initialization
00172                   point par_p = p + dpar[p]; // this value is saved
00173                   label[p] = cur_l; // because dpar[p] is modified here
00174                   node[cur_l].par = label[par_p]; // so this line is ok
00175                   if (is_root(p))
00176                     assert(node[cur_l].par == cur_l);
00177                   --cur_l;
00178                 }
00179               else
00180                 // label propagation
00181                 label[p] = label[p + dpar[p]];
00182             }
00183           return node;
00184         }
00185 
00186 
00187         template <class A> // A for attributes
00188         void compute_attributes(std::vector< node_<A> >& node)
00189           // point-wise version
00190         {
00191           dpar_t& label = dpar;
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 
00206         point find_root(point x, value h)
00207         {
00208           while (not is_root(x))
00209             if (f[x] > h)
00210               x += dpar[x];
00211             else
00212               x = find_level_root(x + dpar[x]);
00213           return x;
00214         }
00215 
00216         void do_union(const point& n, const point& p, value h)
00217         {
00218           point r = find_root(n, h);
00219           if (r != p)
00220             dpar[r] = p - r;
00221         }
00222 
00223 
00224       }; // end of class hdc_maxtree
00225 
00226 
00227 
00228     } // end of namespace oln::lrde::ufmt
00229 
00230   } // end of namespace oln::lrde
00231 
00232 } // end of namespace oln
00233 
00234 
00235 #endif // ! OLENA_LRDE_UFMT_HDC_MAXTREE_HH

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