fiorio-1.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_1_HH
00041 # define OLENA_LRDE_UFMT_FIORIO_1_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         }
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           // Special treatment of the first line (no merge).
00142           build_tree_of_line(0);
00143           for (coord i = 1; i < ima_.nrows(); ++i)
00144             {
00145               build_tree_of_line(i);
00146               // Merge the tree of the current line with the rest of the image.
00147               merge_line(i);
00148             }
00149         }
00150 
00151         void build_tree_of_line(coord row)
00152         {
00153           // Start at the second pixel (the first pixel has no left
00154           // neighbor.
00155           for (coord j = 1; j < ima_.ncols(); ++j)
00156             {
00157               point left = find_level_root(point(row, j - 1));
00158               point this_one = point(row, j);
00159               merge(left, this_one);
00160             }
00161         }
00162 
00163         void merge_line(coord row)
00164         {
00165           precondition(row > 0);
00166 
00167           // Special treatment of the pixel on the first column.
00168           {
00169             point p     (row,     0);
00170             point upper (row - 1, 0);
00171             // Merge with upper pixel.
00172             merge(p, upper);
00173           }
00174           for (coord col = 1; col < ima_.ncols(); ++col)
00175             {
00176               point p     (row,     col    );
00177               point upper (row - 1, col    );
00178 
00179               // Note: merging with the left pixel is useless.
00180 
00181               // Merge with upper pixel.
00182               merge(p, upper);
00183             }
00184         }
00185 
00186         // FIXME: Turn this recursive method into a loop!
00187         // FIXME: Get rid of the swap, using an introductory method.
00189         void merge(const point& p, const point& q)
00190         {
00191           point r = find_level_root(p);
00192           point s = find_level_root(q);
00193 
00194           // Stop the recursion when R and S are equal.
00195           if (r == s)
00196             return;
00197 
00198           // Update the number of level roots.
00199           if (ima_[r] == ima_[s])
00200             --n_level_roots_cpt_;
00201 
00202           // The rest of the routine assumes that R has a value
00203           // greater or equal to S; swap them if needed.
00204           if (ima_[r] < ima_[s])
00205             std::swap(r, s);
00206 
00207           point t = parent_[r];
00208 
00209           // Join R and S only if S is higher than the parent of R.
00210           if (r == t or ima_[s] > ima_[t])
00211             parent_[r] = s;
00212           // FIXME: Study whether the order (S, T) is important.  That
00213           // might be the case when S and T have the same value.
00214           merge(t, s);
00215         }
00216 
00218         bool is_top(const point& p) const
00219         {
00220           return parent_[p] == p;
00221         }
00222 
00223         bool is_level_root(const point& p) const
00224         {
00225           return
00226             is_top(p) ||
00227             (ima_[parent_[p]] != ima_[p]);
00228         }
00229 
00234         point find_level_root(const point& p)
00235         {
00236           // Path compression.
00237           if (not is_top(p))
00238             parent_[p] = find_level_root(parent_[p]);
00239           // Is P a level root at the end the routine?
00240           if (is_level_root(p))
00241             return p;
00242           else
00243             return parent_[p];
00244         }
00245 
00246       protected:
00248         I ima_;
00250         parent_type parent_;
00251         // Counter of level roots (method 1).
00252         unsigned n_level_roots_cpt_;
00253 
00254       };
00255 
00256     } // end of namespace oln::lrde::ufmt
00257 
00258   } // end of namespace oln::lrde
00259 
00260 } // end of namespace oln
00261 
00262 #endif // ! OLENA_LRDE_UFMT_FIORIO_1_HH

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