• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

breadth_first_thinning.hh

00001 // Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
00002 //
00003 // This file is part of Olena.
00004 //
00005 // Olena is free software: you can redistribute it and/or modify it under
00006 // the terms of the GNU General Public License as published by the Free
00007 // Software Foundation, version 2 of the License.
00008 //
00009 // Olena is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // As a special exception, you may use this file as part of a free
00018 // software project without restriction.  Specifically, if other files
00019 // instantiate templates or use macros or inline functions from this
00020 // file, or you compile this file and link it with other files to produce
00021 // an executable, this file does not by itself cause the resulting
00022 // executable to be covered by the GNU General Public License.  This
00023 // exception does not however invalidate any other reasons why the
00024 // executable file might be covered by the GNU General Public License.
00025 
00026 #ifndef MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH
00027 # define MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH
00028 
00032 
00033 # include <algorithm>
00034 
00035 # include <mln/core/routine/duplicate.hh>
00036 
00037 # include <mln/core/concept/image.hh>
00038 # include <mln/core/concept/neighborhood.hh>
00039 
00040 # include <mln/core/site_set/p_set.hh>
00041 
00042 # include <mln/fun/p2b/tautology.hh>
00043 
00044 namespace mln
00045 {
00046 
00047   namespace topo
00048   {
00049 
00050     namespace skeleton
00051     {
00052 
00067       template <typename I, typename N, typename F, typename G, typename H>
00068       mln_concrete(I)
00069       breadth_first_thinning(const Image<I>& input,
00070                              const Neighborhood<N>& nbh,
00071                              Function_v2b<F>& is_simple,
00072                              G detach,
00073                              const Function_v2b<H>& constraint =
00074                                fun::p2b::tautology());
00075 
00076 
00077 # ifndef MLN_INCLUDE_ONLY
00078 
00079       template <typename I, typename N, typename F, typename G, typename H>
00080       inline
00081       mln_concrete(I)
00082       breadth_first_thinning(const Image<I>& input_,
00083                              const Neighborhood<N>& nbh_,
00084                              Function_v2b<F>& is_simple_,
00085                              G detach,
00086                              const Function_v2b<H>& constraint_)
00087       {
00088         const I& input = exact(input_);
00089         const N& nbh = exact(nbh_);
00090         F& is_simple = exact(is_simple_);
00091         const H& constraint = exact(constraint_);
00092 
00093         I output = duplicate(input);
00094         // Attach the work image to IS_SIMPLE.
00095         is_simple.set_image(output);
00096 
00097         typedef mln_psite(I) psite;
00098         typedef p_set<psite> set_t;
00099         set_t set;
00100         // Populate SET with candidate simple points.
00101         mln_piter(I) p_(output.domain());
00102         for_all(p_)
00103         {
00104           /* CONSTRAINTS and IS_SIMPLE are site-to-boolean (p2b)
00105              predicate functors; passing an iterator as argument might
00106              not be possible (C++ cannot resolve template routines if
00107              an implicit conversion of the argument is needed).  Help
00108              the compiler and pass an actual, explicit psite.  */
00109           psite p = p_;
00110           if (output(p) && constraint(p) && is_simple(p))
00111             set.insert(p);
00112         }
00113 
00114         while (!set.is_empty())
00115           {
00116             set_t next_set;
00117 
00118             /* FIXME: Using the following code does not work (it does
00119                compiles, but does not behave like the code using a
00120                hand-made loop).  There must be a bug somewhere in
00121                p_set or p_indexed_psite. */
00122 # if 0
00123             mln_piter(set_t) ps(set);
00124             for_all(ps);
00125             {
00126               // Same remark as above.
00127               psite p = p_;
00128 # endif
00129             for (unsigned i = 0; i < set.nsites(); ++i)
00130               {
00131                 psite p = set[i];
00132 
00133                 /* FIXME: We compute the cell and attachment of P twice:
00134                    during the call to is_simple() and within detach().
00135                    How could we reuse this elegantly, without breaking
00136                    the genericity of the skeleton algorithm?  */
00137                 if (constraint(p) && is_simple(p))
00138                   {
00139                     detach(p, output);
00140                     mln_niter(N) n(nbh, p);
00141                     for_all(n)
00142                       if (output.domain().has(n)
00143                           && output(n) && constraint(p) && is_simple(n))
00144                         next_set.insert(n);
00145                   }
00146               }
00147             set.clear();
00148             std::swap(set, next_set);
00149           }
00150         return output;
00151       }
00152 
00153 # endif // MLN_INCLUDE_ONLY
00154 
00155     } // end of namespace mln::topo::skeleton
00156 
00157   } // end of namespace mln::topo
00158 
00159 } // end of namespace mln
00160 
00161 #endif // ! MLN_TOPO_SKELETON_BREADTH_FIRST_THINNING_HH

Generated on Tue Oct 4 2011 15:23:28 for Milena (Olena) by  doxygen 1.7.1