fiorio-3.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, 51 Franklin Street, Fifth Floor,
00016 // Boston, 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 
00041 #ifndef OLENA_LRDE_UFMT_FIORIO_3_HH
00042 # define OLENA_LRDE_UFMT_FIORIO_3_HH
00043 
00044 # include <algorithm>
00045 
00046 # include <oln/core/image2d.hh>
00047 # include <oln/level/fill.hh>
00048 
00049 namespace oln
00050 {
00051   namespace lrde
00052   {
00053     namespace ufmt
00054     {
00055 
00056       // FIXME: Not generic (works only on 2-D images).
00057       template <typename I>
00058       class fiorio
00059       {
00060         typedef oln_point_type(I) point;
00061         typedef oln_value_type(I) value;
00062         typedef oln_iter_type(I) piter;
00063         typedef typename mute<I, point>::ret parent_type;
00064 
00065       public:
00066         fiorio(const abstract::image<I>& ima) :
00067           ima_(ima.exact().clone()), parent_(ima.size()),
00068           n_level_roots_cpt_(ima.npoints())
00069         {
00070           // Init the image of parents.
00071           piter p (parent_);
00072           for_all (p)
00073             parent_[p] = p;
00074         }
00075 
00077         void go()
00078         {
00079           scan_line();
00080         }
00081 
00082 
00085       public:
00086         const I& ima() const
00087         {
00088           return ima_;
00089         }
00090 
00091         const parent_type& parent() const
00092         {
00093           return parent_;
00094         }
00096 
00097 
00102         unsigned n_level_roots1() const
00103         {
00104           return n_level_roots_cpt_;
00105         }
00106 
00109         unsigned n_level_roots2() const
00110         {
00111           unsigned n_level_roots = 0;
00112           oln_iter_type(parent_type) p(parent_);
00113           for_all (p)
00114             if (is_level_root(p))
00115               ++n_level_roots;
00116           return n_level_roots;
00117         }
00118 
00120         typedef typename mute<parent_type, bool>::ret level_roots_image_type;
00121 
00125         level_roots_image_type level_roots() const
00126         {
00127           // Image of level roots.
00128           level_roots_image_type level_roots (ima_.size());
00129           oln_iter_type(parent_type) p(ima_);
00130           for_all (p)
00131             level_roots[p] = is_level_root(p);
00132           return level_roots;
00133         }
00135 
00136 
00137       protected:
00138         // FIXME: Improve to handle other neighborhoods than 4-c.
00139         void scan_line()
00140         {
00141           // Build the max-tree of each line separately.
00142           for (coord i = 0; i < ima_.nrows(); ++i)
00143             build_tree_of_line(i);
00144           // Then merge all max-trees, line per line.
00145           for (coord j = 0; j < ima_.ncols(); ++j)
00146             for (coord i = 0; i < ima_.nrows() - 1; ++i)
00147               merge(point(i, j), point(i + 1, j));
00148         }
00149 
00150         void build_tree_of_line(coord row)
00151         {
00152           // Start at the second pixel (the first pixel has no left
00153           // neighbor.
00154           for (coord j = 1; j < ima_.ncols(); ++j)
00155             {
00156               point left = find_level_root(point(row, j - 1));
00157               point this_one = point(row, j);
00158               insert(this_one, left);
00159             }
00160         }
00161 
00163         void insert(const point& p, const point& n)
00164         {
00165           point r = find_ancestor(n, ima_[p]);
00166           if (ima_[r] <= ima_[p])
00167             {
00168               parent_[p] = r;
00169               if (ima_[r] == ima_[p])
00170                 // Update the number of level roots.
00171                 --n_level_roots_cpt_;
00172             }
00173           else
00174             {
00175               if (not is_top(r))
00176                 parent_[p] = parent_[r];
00177               parent_[r] = p;
00178             }
00179         }
00180 
00183         void merge(const point& p, const point& q)
00184         {
00185           // The \a merge_ routine assumes that P has a value greater
00186           // or equal to Q; swap them if needed.
00187           if (ima_[p] >= ima_[q])
00188             merge_(p, q);
00189           else
00190             merge_(q, p);
00191         }
00192 
00193         // FIXME: Turn this recursive method into a loop!
00194         void merge_(const point& p, const point& q)
00195         {
00196           precondition (p != q);
00197           precondition (ima_[p] >= ima_[q]);
00198 
00199           point r = find_ancestor(p, ima_[q]);
00200           point s = find_level_root(q);
00201 
00202           // Stop the recursion when R and S are equal (i.e., they are
00203           // already merged).
00204           if (r == s)
00205             return;
00206 
00207           point t = parent_[s];
00208 
00209           if (ima_[s] == ima_[r])
00210             {
00211               parent_[s] = r;
00212               // Update the number of level roots.
00213               --n_level_roots_cpt_;
00214             }
00215           else
00216             {
00217               if (not is_top(r))
00218                 parent_[s] = parent_[r];
00219               parent_[r] = s;
00220             }
00221           merge_(r, t);
00222         }
00223 
00225         bool is_top(const point& p) const
00226         {
00227           return parent_[p] == p;
00228         }
00229 
00230         point find_top(point p) const
00231         {
00232           while (not is_top(p))
00233             p = parent_[p];
00234           return p;
00235         }
00236 
00237         bool is_level_root(const point& p) const
00238         {
00239           return
00240             is_top(p) ||
00241             (ima_[parent_[p]] != ima_[p]);
00242         }
00243 
00246         point find_level_root(const point& p)
00247         {
00248           // Is P a level root at the end the routine?
00249           if (is_level_root(p))
00250             return p;
00251           else
00252             // Path compression.
00253             return parent_[p] = find_level_root(parent_[p]);
00254         }
00255 
00258         point find_ancestor(point p, const value& level)
00259         {
00260           while (not is_top(p) and ima_[parent_[p]] >= level)
00261             p = find_level_root(parent_[p]);
00262           return p;
00263         }
00264 
00265       protected:
00267         I ima_;
00269         parent_type parent_;
00270         // Counter of level roots (method 1).
00271         unsigned n_level_roots_cpt_;
00272 
00273       };
00274 
00275     } // end of namespace oln::lrde::ufmt
00276 
00277   } // end of namespace oln::lrde
00278 
00279 } // end of namespace oln
00280 
00281 #endif // ! OLENA_LRDE_UFMT_FIORIO_3_HH

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