generic_simplified_salembier.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 #ifndef OLENA_LRDE_UFMT_GENERIC_SIMPLIFIED_SALEMBIER_HH
00029 # define OLENA_LRDE_UFMT_GENERIC_SIMPLIFIED_SALEMBIER_HH
00030 
00031 
00032 # include <climits> // For INT_MAX.
00033 # include <cfloat>  // For FLT_MAX.
00034 # include <queue>
00035 # include <set>
00036 # include <map>
00037 
00038 # include <algorithm>
00039 # include <iterator>
00040 
00041 # include <oln/level/fill.hh>
00042 # include <oln/lrde/ufmt/utils.hh>
00043 
00044 
00045 
00046 namespace oln
00047 {
00048 
00049   namespace lrde
00050   {
00051 
00052     namespace ufmt
00053     {
00054 
00055       /*-------------.
00056       | point_less.  |
00057       `-------------*/
00058 
00059       template <typename I, typename P>
00060       struct point_less
00061       {
00062         // To be specialized.
00063       };
00064 
00065       template <typename I>
00066       struct point_less<I, oln::point2d>
00067       {
00068         point_less (const abstract::image<I>& f) :
00069           f_(f.exact())
00070         {
00071         }
00072 
00073         bool
00074         operator() (const oln::point2d& p, const oln::point2d& q)
00075         {
00076           // Ensure the equivalence of the ``strict'' weak ordering
00077           // (http://www.sgi.com/tech/stl/StrictWeakOrdering.html) is
00078           // preserved when P and Q are the same point.
00079           if (p == q)
00080             return false;
00081 
00082           // Compare the values.
00083           // FIXME: Use a more robust comparison function (for floats)?
00084           float val_diff = f_[p] - f_[q];
00085           if (val_diff < 0.f)
00086             return true;
00087           else if (val_diff > 0.f)
00088             return false;
00089           else
00090             {
00091               // Then compare the row numbers.
00092               int row_diff = p.row() - q.row();
00093               if (row_diff < 0)
00094                 return true;
00095               else if (row_diff > 0)
00096                 return false;
00097               else
00098                 {
00099                   // Finally, compare the row numbers.
00100                   int col_diff = p.col() - q.col();
00101                   if (col_diff < 0)
00102                     return true;
00103                   else
00104                     return false;
00105                 }
00106             }
00107         }
00108 
00109         const I& f_;
00110       };
00111 
00112 
00113       /*----------------.
00114       | point_greater.  |
00115       `----------------*/
00116 
00117       template <typename I, typename P>
00118       struct point_greater
00119       {
00120         // To be specialized.
00121       };
00122 
00123       template <typename I>
00124       struct point_greater<I, oln::point2d>
00125       {
00126         point_greater (const abstract::image<I>& f) :
00127           f_(f.exact())
00128         {
00129         }
00130 
00131         bool
00132         operator() (const oln::point2d& p, const oln::point2d& q)
00133         {
00134           // Ensure the equivalence of the ``strict'' weak ordering
00135           // (http://www.sgi.com/tech/stl/StrictWeakOrdering.html) is
00136           // preserved when P and Q are the same point.
00137           if (p == q)
00138             return false;
00139 
00140           // Compare the values.
00141           // FIXME: Use a more robust comparison function (for floats)?
00142           float val_diff = f_[p] - f_[q];
00143           if (val_diff > 0.f)
00144             return true;
00145           else if (val_diff < 0.f)
00146             return false;
00147           else
00148             {
00149               // Then compare the row numbers.
00150               int row_diff = p.row() - q.row();
00151               if (row_diff > 0)
00152                 return true;
00153               else if (row_diff < 0)
00154                 return false;
00155               else
00156                 {
00157                   // Finally, compare the row numbers.
00158                   int col_diff = p.col() - q.col();
00159                   if (col_diff > 0)
00160                     return true;
00161                   else
00162                     return false;
00163                 }
00164             }
00165         }
00166 
00167         const I& f_;
00168       };
00169 
00170 
00171       /* A simplified version of Salembier et al. algorithm.
00172 
00173          pset : a set of point, ordered by increasing pix values,
00174          then increasing rows, then increasing cols.
00175 
00176          points : the set of all the point, ordered by *decreasing* pix
00177          values, then increasing rows, then increasing cols.
00178          (a vector might be a good idea ?)
00179 
00180          node_at_levels : a set of points or a bit-array of points.
00181 
00182            
00183 
00184            flood (h)  // h is a point here, not a level!
00185   
00186              // FIXME: Use a fuzzy (tolerant) version of find?
00187              i = pset.find(q)
00188              while (i != pset.end())
00189                p <- *i                   // (Or : p <- pset.lower_bound(h) ?)
00190                STATUS(p) <- true
00191                for every neighbor q of p
00192                  if STATUS(q) == false
00193                    pset.insert(q)
00194                    STATUS(q) <- true
00195                    node-at-level.insert(q)
00196                    if (ORI(q) > ORI(p))
00197                      m = q
00198                      repeat
00199                        m <- flood(m)
00200                      until ORI(m) <= ORI(h)
00201                // FIXME: Use a fuzzy (tolerant) version of find?
00202                i = pset.find(q)
00203   
00204              // find first level lower than h beeing part of node_at_level.
00205              // m = sites.upper_bound(h)      // Recall that sites are sorted
00206                                               // in *descending* order.
00207              while (m != sites.end() and      // Was: « m >= 0 ».
00208                     node_at_level.find(*m) == node_at_level.end())
00209                ++m;                           // Was: « m = h - 1 ».
00210              if m != sites.end()
00211                father of C(h) <- C(*m)
00212              else
00213                C(h) has no father       // C(*h) is root node.
00214              node-at-level.erase(h)
00215              return m
00216       */
00217 
00218       template <class I>
00219       struct generic_simplified_salembier
00220       {
00221         typedef oln_point_type(I) point;
00222         typedef oln_value_type(I) value;
00223         typedef oln_neighborhood_type(I) Nbh;
00224         typedef oln_iter_type(Nbh) niter;
00225 
00226         const I& f;
00227         const Nbh& nbh;
00228 
00229         // FIXME: In an index-based version, STATUS could be a bit
00230         // vector (of the STL)
00231         typename mute<I, bool>::ret status;
00232 
00233         // FIXME: Rename this attribute.
00234         // node_at_level.
00235         typedef std::set< point, point_less<I, point> > node_at_level_t;
00236         node_at_level_t node_at_level;
00237 
00238         // pset.
00239         typedef std::set< point, point_less<I, point> > pset_t;
00240         typedef typename pset_t::const_iterator pset_iterator;
00241         // Set of points to be processed (replaces the hqueue data structure).
00242         pset_t pset;
00243         point p_min;
00244 
00245         // All sites, sorted by increasing levels (then by row/col).
00246         typedef std::set< point, point_greater<I, point> > sites_t;
00247         typedef typename sites_t::const_iterator site_iterator;
00248         // Set of all values present in the input image, sorting in
00249         // descending order.
00250         sites_t sites;
00251 
00252         std::map<point, point, point_less<I, point> > father;
00253 
00254 # ifdef OLN_DEBUG
00255         unsigned npoints;
00256 # endif // OLN_DEBUG
00257 
00258         generic_simplified_salembier(const abstract::image<I>& f,
00259                           const oln_neighborhood_type(I)& nbh) :
00260           f(f.exact()),
00261           nbh(nbh),
00262           status(f.size()),
00263           node_at_level(point_less<I, point>(f.exact())),
00264           pset(point_less<I, point>(f.exact())),
00265           sites(point_greater<I, point>(f.exact())),
00266           father(point_less<I, point>(f.exact()))
00267 # ifdef OLN_DEBUG
00268           , npoints(f.npoints())
00269 # endif // OLN_DEBUG
00270         {
00271         }
00272 
00273 
00274         void go()
00275         {
00276           init();
00277 //        // -- DEBUG ---------------------------------------------------
00278 //        std::cerr << "p_min = " << p_min << std::endl;
00279 //        std::cerr << "f[p_min] = " << f[p_min] << std::endl;
00280 //        // --------------------------------------------------- DEBUG --
00281           flood(p_min);
00282         }
00283 
00284 
00285         void init()
00286         {
00287           level::fill(status, false);
00288 
00289           oln_iter_type(I) p(f);
00290           p = mlc::begin;
00291           p_min = p;
00292           value h_min = f[p];
00293           for_all(p)
00294             {
00295               // Init sites.
00296               sites.insert(p);
00297               // Find the global minimum.
00298               if (f[p] < h_min)
00299                 {
00300                   h_min = f[p];
00301                   p_min = p;
00302                 }
00303             }
00304 //        // -- DEBUG ---------------------------------------------------
00305 //        std::cerr << "p_min = " << p_min << std::endl;
00306 //        std::cerr << "h_min = " << h_min << std::endl;
00307 //        // --------------------------------------------------- DEBUG --
00308           pset.insert(p_min);
00309 //        // -- DEBUG ---------------------------------------------------
00310 //        std::cerr << "p_min = " << p_min << std::endl;
00311 //        std::cerr << "h_min = " << h_min << std::endl;
00312 //        // --------------------------------------------------- DEBUG --
00313         }
00314 
00315 # ifdef OLN_DEBUG
00316         void update_status (std::ostream& ostr)
00317         {
00318           static unsigned nupdates = 0;
00319           static const unsigned step = 1;
00320           static unsigned next_step = step;
00321           ++nupdates;
00322           unsigned percent = nupdates * 100 / npoints;
00323           if (percent >= next_step)
00324             {
00325               // Print.
00326               std::cerr << percent << "% points processed" << std::endl;
00327               // Increase the next step.
00328               while (percent >= next_step)
00329                 next_step += step;
00330             }
00331         }
00332 # endif // OLN_DEBUG
00333 
00334 
00335         // H is a point here, not a level!
00336         // FIXME: Change the name of this argument, as it's confusing.
00337         site_iterator flood(const point& h)
00338         {
00339 //        // -- DEBUG ---------------------------------------------------
00340 //        std::cerr << "pset = ";
00341 //        for (typename pset_t::const_iterator j = pset.begin();
00342 //             j != pset.end(); ++j)
00343 //          std::cerr << *j << " ";
00344 //        std::cerr << std::endl;
00345 //        // --------------------------------------------------- DEBUG --
00346 
00347 //        // -- DEBUG ---------------------------------------------------
00348 //        std::cerr << "h = " << h << std::endl;
00349 //        // --------------------------------------------------- DEBUG --
00350 
00351           site_iterator m;
00352 
00353           pset_iterator i;
00354           i = pset.find(h);
00355           while (i != pset.end())
00356             {
00357 //            // -- DEBUG -----------------------------------------------
00358 //            std::cerr << "  pset = ";
00359 //            for (typename pset_t::const_iterator j = pset.begin();
00360 //                 j != pset.end(); ++j)
00361 //              std::cerr << *j << " ";
00362 //            std::cerr << std::endl;
00363 //            // ----------------------------------------------- DEBUG --
00364 
00365               point p = *i;
00366 //            // -- DEBUG -----------------------------------------------
00367 //            std::cerr << "  p = " << p << std::endl;
00368 //            // ----------------------------------------------- DEBUG --
00369               pset.erase(i);
00370 
00371               status[p] = true;
00372 #ifdef OLN_DEBUG
00373               update_status(std::cerr);
00374 #endif // OLN_DEBUG
00375 
00376 //            // -- DEBUG -----------------------------------------------
00377 //            std::cerr << "  status = " << std::endl;
00378 //            print_image(status, std::cerr);
00379 //            // ----------------------------------------------- DEBUG --
00380 
00381               oln_neighb_type(Nbh) q(nbh, p);
00382               for_all(q)
00383                 {
00384 //                // -- DEBUG -------------------------------------------
00385 //                std::cerr << "    q = " << q << std::endl;
00386 //                // ------------------------------------------- DEBUG --
00387 
00388                   if (f.hold(q))
00389                     {
00390                       if (status[q] == false)
00391                         {
00392                           pset.insert(q);
00393 //                        // -- DEBUG -----------------------------------
00394 //                        std::cerr << "    pset = ";
00395 //                        for (typename pset_t::const_iterator j =
00396 //                               pset.begin(); j != pset.end(); ++j)
00397 //                          std::cerr << *j << " ";
00398 //                        std::cerr << std::endl;
00399 //                        // ----------------------------------- DEBUG --
00400                           status[q] = true;
00401                           node_at_level.insert(q); // err. 1
00402                           if (f[q] > f[p])
00403                             {
00404                               m = sites.find(q);
00405                               if (m == sites.end())
00406                                 abort();
00407                               while (m != sites.end() and
00408                                      f[*m] > f[h]) // err. 2
00409                                 m = flood(*m);
00410                             }
00411                         }
00412                     }
00413                 }
00414               i = pset.find(h);
00415             }
00416 
00417           m = sites.upper_bound(h);
00418           if (m != sites.end())
00419             ++m;                                // Was: « m = h - 1 ».
00420           while (m != sites.end() and           // Was: « m >= 0 ».
00421                  node_at_level.find(*m) == node_at_level.end())
00422             ++m;                                // Was: « m = h - 1 ».
00423           if (m != sites.end())                 // Was: « m >= 0 ».
00424             {
00425 //            // -- DEBUG -----------------------------------------------
00426 //            std::cerr << "father[" << h << "] = " << (*m) << std::endl;
00427 //            // ----------------------------------------------- DEBUG --
00428               father[h] = *m;
00429             }
00430           else
00431             {
00432 //            // -- DEBUG -----------------------------------------------
00433               std::cerr << "father[" << h << "] is root" << std::endl;
00434 //            // ----------------------------------------------- DEBUG --
00435               father[h] = h;
00436             }
00437           node_at_level.erase(h);
00438           return m;
00439         }
00440 
00441 
00442         unsigned n_level_roots() const
00443         {
00444           return father.size();
00445         }
00446 
00447         template <typename T>
00448         void
00449         print_image (const image2d<T>& ima, std::ostream& o)
00450         {
00451           for (coord row = 0; row < ima.nrows(); ++row)
00452             {
00453               for (coord col = 0; col < ima.ncols(); ++col)
00454                 o << ima(row, col) << " ";
00455               o << std::endl;
00456             }
00457         }
00458 
00459 
00460       }; // end of struct generic_simplified_salembier
00461 
00462 
00463     } // end of namespace oln::lrde::ufmt
00464 
00465   } // end of namespace oln::lrde
00466 
00467 } // end of namespace oln
00468 
00469 
00470 #endif // ! OLENA_LRDE_UFMT_GENERIC_SIMPLIFIED_SALEMBIER_HH

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