fiorio-2.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 
00040 #ifndef OLENA_LRDE_UFMT_FIORIO_2_HH
00041 # define OLENA_LRDE_UFMT_FIORIO_2_HH
00042 
00043 # include <algorithm>
00044 
00045 # include <oln/core/image2d.hh>
00046 # include <oln/level/fill.hh>
00047 
00048 namespace oln
00049 {
00050   namespace lrde
00051   {
00052     namespace ufmt
00053     {
00054 
00055       // FIXME: Not generic (works only on 2-D images).
00056       template <typename I>
00057       class fiorio
00058       {
00059         typedef oln_point_type(I) point;
00060         typedef oln_value_type(I) value;
00061         typedef oln_iter_type(I) piter;
00062         typedef typename mute<I, point>::ret parent_type;
00063 
00064       public:
00065         fiorio(const abstract::image<I>& ima) :
00066           ima_(ima.exact().clone()), parent_(ima.size())
00067           , n_level_roots_cpt_(ima.npoints())
00068         {
00069           // Init the image of parents.
00070           piter p (parent_);
00071           for_all (p)
00072             parent_[p] = p;
00073         }
00074 
00076         void go()
00077         {
00078           scan_line();
00079         }
00080 
00081 
00084       public:
00085         const I& ima() const
00086         {
00087           return ima_;
00088         }
00089 
00090         const parent_type& parent() const
00091         {
00092           return parent_;
00093         }
00095 
00096 
00101         unsigned n_level_roots1() const
00102         {
00103           return n_level_roots_cpt_;
00104         }
00105 
00108         unsigned n_level_roots2() const
00109         {
00110           unsigned n_level_roots = 0;
00111           oln_iter_type(parent_type) p(parent_);
00112           for_all (p)
00113             if (is_level_root(p))
00114               ++n_level_roots;
00115           return n_level_roots;
00116         }
00117 
00119         typedef typename mute<parent_type, bool>::ret level_roots_image_type;
00120 
00124         level_roots_image_type level_roots() const
00125         {
00126           // Image of level roots.
00127           level_roots_image_type level_roots (ima_.size());
00128           oln_iter_type(parent_type) p(ima_);
00129           for_all (p)
00130             level_roots[p] = is_level_root(p);
00131           return level_roots;
00132         }
00134 
00135 
00136       protected:
00137         // FIXME: Improve to handle other neighborhoods than 4-c.
00138         void scan_line()
00139         {
00140           // Special treatment of the first line (no merge).
00141           build_tree_of_line(0);
00142           for (coord i = 1; i < ima_.nrows(); ++i)
00143             {
00144               build_tree_of_line(i);
00145               // Merge the tree of the current line with the rest of the image.
00146               merge_line(i);
00147             }
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 
00162         void merge_line(coord row)
00163         {
00164           precondition(row > 0);
00165 
00166           for (coord col = 0; col < ima_.ncols(); ++col)
00167             {
00168               point p     (row,     col    );
00169               point upper (row - 1, col    );
00170 
00171               // Note: merging with the left pixel is useless.
00172 
00173               // Merge with upper pixel.
00174               merge(p, upper);
00175             }
00176         }
00177 
00179         void insert(const point& p, const point& n)
00180         {
00181           point r = find_ancestor(n, ima_[p]);
00182           if (ima_[r] <= ima_[p])
00183             {
00184               parent_[p] = r;
00185               if (ima_[r] == ima_[p])
00186                 // Update the number of level roots.
00187                 --n_level_roots_cpt_;
00188             }
00189           else
00190             {
00191               if (not is_top(r))
00192                 parent_[p] = parent_[r];
00193               parent_[r] = p;
00194             }
00195         }
00196 
00199         void merge(const point& p, const point& q)
00200         {
00201           // The \a merge_ routine assumes that P has a value greater
00202           // or equal to Q; swap them if needed.
00203           if (ima_[p] >= ima_[q])
00204             merge_(p, q);
00205           else
00206             merge_(q, p);
00207         }
00208 
00209         // FIXME: Turn this recursive method into a loop!
00210         void merge_(const point& p, const point& q)
00211         {
00212           precondition (p != q);
00213           precondition (ima_[p] >= ima_[q]);
00214 
00215           point r = find_ancestor(p, ima_[q]);
00216           point s = find_level_root(q);
00217 
00218           // Stop the recursion when R and S are equal (i.e., they are
00219           // already merged).
00220           if (r == s)
00221             return;
00222 
00223           point t = parent_[s];
00224 
00225           if (ima_[s] == ima_[r])
00226             {
00227               parent_[s] = r;
00228               // Update the number of level roots.
00229               --n_level_roots_cpt_;
00230             }
00231           else
00232             {
00233               if (not is_top(r))
00234                 parent_[s] = parent_[r];
00235               parent_[r] = s;
00236             }
00237           merge_(r, t);
00238         }
00239 
00240 // FIXME: ``New'' Version (iterative, instead of recursive).  To be tested.
00241 #if 0
00242         void merge_(point p, point q)
00243         {
00244           precondition (p != q);
00245           precondition (ima_[p] >= ima_[q]);
00246 
00247           point r = find_ancestor(p, ima_[q]);
00248           point s = find_level_root(q);
00249 
00250           // Stop the recursion when R and S are equal (i.e., they are
00251           // already merged).
00252           while (r != s)
00253             {
00254               invariant (p != q);
00255               invariant (ima_[p] >= ima_[q]);
00256 
00257               point t = parent_[s];
00258               if (ima_[s] == ima_[r])
00259                 {
00260                   parent_[s] = r;
00261                   // Update the number of level roots.
00262                   --n_level_roots_cpt_;
00263                 }
00264               else
00265                 {
00266                   if (not is_top(r))
00267                     parent_[s] = parent_[r];
00268                   parent_[r] = s;
00269                 }
00270               p = r;
00271               q = t;
00272               r = find_ancestor(p, ima_[q]);
00273               s = find_level_root(q);
00274             }
00275         }
00276 #endif
00277 
00279         bool is_top(const point& p) const
00280         {
00281           return parent_[p] == p;
00282         }
00283 
00284         bool is_level_root(const point& p) const
00285         {
00286           return
00287             is_top(p) ||
00288             (ima_[parent_[p]] != ima_[p]);
00289         }
00290 
00293         point find_level_root(const point& p)
00294         {
00295           // Is P a level root at the end the routine?
00296           if (is_level_root(p))
00297             return p;
00298           else
00299             // Path compression.
00300             return parent_[p] = find_level_root(parent_[p]);
00301         }
00302 
00305         point find_ancestor(point p, const value& level)
00306         {
00307           while (not is_top(p) and ima_[parent_[p]] >= level)
00308             p = find_level_root(parent_[p]);
00309           return p;
00310         }
00311 
00312       protected:
00314         I ima_;
00316         parent_type parent_;
00317         // Counter of level roots (method 1).
00318         unsigned n_level_roots_cpt_;
00319 
00320       };
00321 
00322     } // end of namespace oln::lrde::ufmt
00323 
00324   } // end of namespace oln::lrde
00325 
00326 } // end of namespace oln
00327 
00328 #endif // ! OLENA_LRDE_UFMT_FIORIO_2_HH

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