00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 #ifndef MLN_MORPHO_SKELETON_CONSTRAINED_HH
00028 # define MLN_MORPHO_SKELETON_CONSTRAINED_HH
00029 
00036 
00037 # include <mln/core/concept/image.hh>
00038 # include <mln/core/concept/neighborhood.hh>
00039 # include <mln/core/site_set/p_queue_fast.hh>
00040 # include <mln/core/site_set/p_priority.hh>
00041 # include <mln/extension/adjust_duplicate.hh>
00042 # include <mln/extension/adjust_fill.hh>
00043 # include <mln/data/fill.hh>
00044 
00045 # include <mln/util/timer.hh>
00046 
00047 namespace mln
00048 {
00049 
00050   namespace morpho
00051   {
00052 
00053     template <typename I,
00054               typename N, typename F,
00055               typename K, typename R>
00056     mln_ch_value(I, bool)
00057     skeleton_constrained(const Image<I>& input,
00058                          const Neighborhood<N>& nbh, const F& is_simple,
00059                          const Image<K>& constraint, const Image<R>& priority);
00060 
00061 
00062 
00063 # ifndef MLN_INCLUDE_ONLY
00064 
00065 
00066     namespace impl
00067     {
00068 
00069       namespace generic
00070       {
00071 
00072         template <typename I,
00073                   typename N, typename F,
00074                   typename K, typename R>
00075         inline
00076         mln_ch_value(I, bool)
00077           skeleton_constrained(const Image<I>& input_,
00078                                const Neighborhood<N>& nbh_, const F& is_simple,
00079                                const Image<K>& constraint_, const Image<R>& priority_)
00080         {
00081           trace::entering("morpho::skeleton_constrained");
00082 
00083           const I& input      = exact(input_);
00084           const N& nbh        = exact(nbh_);
00085           const K& constraint = exact(constraint_);
00086           const R& priority   = exact(priority_);
00087 
00088           mln_precondition(input.is_valid());
00089           mln_precondition(nbh.is_valid());
00090           mln_precondition(constraint.is_valid());
00091           mln_precondition(priority.is_valid());
00092 
00093           typedef mln_value(I) V;
00094           mlc_is(V, bool)::check();
00095 
00096           extension::adjust_duplicate(input, nbh);
00097           extension::adjust_duplicate(constraint, nbh);
00098           extension::adjust_duplicate(priority, nbh);
00099 
00100           
00101 
00102           typedef mln_psite(I) P;
00103           typedef p_queue_fast<P> Q;
00104           p_priority<mln_value(R), Q> q;
00105 
00106           mln_concrete(I) output;
00107 
00108           
00109           {
00110             output = duplicate(input);
00111             extension::adjust_duplicate(output, nbh);
00112 
00113             mln_piter(I) p(input.domain());
00114             for_all(p)
00115               if (input(p) == false &&
00116                   is_simple.check(input, p)) 
00117                                       
00118               {
00119                 q.push(priority(p), p);
00120               }
00121           }
00122 
00123           
00124           {
00125             P p;
00126 
00127             mln_niter(N) n(nbh, p);
00128             while (! q.is_empty())
00129             {
00130               p = q.pop_front();
00131               for_all(n)
00132                 if (output.has(n) &&
00133                     output(n) == true &&
00134                     constraint(n) == false &&
00135                     is_simple.check(output, n)) 
00136                 {
00137                   output(n) = false; 
00138                   q.push(priority(n), n);
00139                 }
00140             }
00141           }
00142 
00143           trace::exiting("morpho::skeleton_constrained");
00144           return output;
00145         }
00146 
00147       } 
00148 
00149 
00150         template <typename I,
00151                   typename N, typename F,
00152                   typename K, typename R>
00153         inline
00154         mln_ch_value(I, bool)
00155         skeleton_constrained_fast(const Image<I>& input_,
00156                                   const Neighborhood<N>& nbh_,
00157                                   const F& is_simple,
00158                                   const Image<K>& constraint_,
00159                                   const Image<R>& priority_)
00160         {
00161           trace::entering("morpho::skeleton_constrained_fast");
00162 
00163           const I& input      = exact(input_);
00164           const N& nbh        = exact(nbh_);
00165           const K& constraint = exact(constraint_);
00166           const R& priority   = exact(priority_);
00167 
00168           mln_precondition(input.is_valid());
00169           mln_precondition(nbh.is_valid());
00170           mln_precondition(constraint.is_valid());
00171           mln_precondition(priority.is_valid());
00172 
00173           typedef mln_value(I) V;
00174           mlc_is(V, bool)::check();
00175 
00176           
00177           
00178           
00179           
00180           
00181           extension::adjust_fill(input, nbh, false);
00182           extension::adjust_fill(constraint, nbh, false);
00183 
00184           
00185 
00186           typedef p_queue_fast<unsigned> Q;
00187           p_priority<mln_value(R), Q> q;
00188 
00189           mln_concrete(I) output;
00190 
00191           
00192           {
00193             output = duplicate(input);
00194             extension::adjust_fill(output, nbh, false);
00195 
00196             mln_pixter(const I) p_in(input);
00197             for_all(p_in)
00198               if (p_in.val() == false &&
00199                   is_simple.check__(input, p_in)) 
00200                                                   
00201               {
00202                 q.push(priority.element(p_in.offset()), p_in);
00203               }
00204           }
00205 
00206           
00207           {
00208             util::array<int> dp = offsets_wrt(input, nbh.foreground());
00209             const unsigned n_nbhs = dp.nelements();
00210             while (! q.is_empty())
00211             {
00212               unsigned p = q.pop_front();
00213 
00214               for (unsigned i = 0; i < n_nbhs; ++i)
00215               {
00216                 unsigned n = p + dp[i];
00217 
00218                 if (output.element(n) == true &&
00219                     constraint.element(n) == false &&
00220                     is_simple.check__(output, n)) 
00221                 {
00222                   output.element(n) = false; 
00223                   q.push(priority.element(n), n);
00224                 }
00225               }
00226             }
00227           }
00228 
00229           trace::exiting("morpho::skeleton_constrained_fast");
00230           return output;
00231         }
00232 
00233 
00234     } 
00235 
00236 
00237     namespace internal
00238     {
00239 
00240       template <typename I,
00241                 typename N, typename F,
00242                 typename K, typename R>
00243       inline
00244       mln_ch_value(I, bool)
00245       skeleton_constrained_dispatch(
00246         mln::trait::image::value_access::any,
00247         mln::trait::image::value_storage::any,
00248         const Image<I>& input,
00249         const Neighborhood<N>& nbh,
00250         const F& is_simple,
00251         const Image<K>& constraint,
00252         const Image<R>& priority)
00253       {
00254         return impl::generic::skeleton_constrained(input, nbh,
00255                                                    is_simple,
00256                                                    constraint,
00257                                                    priority);
00258       }
00259 
00260       template <typename I,
00261                 typename N, typename F,
00262                 typename K, typename R>
00263       inline
00264       mln_ch_value(I, bool)
00265       skeleton_constrained_dispatch(
00266         mln::trait::image::value_access::direct,
00267         mln::trait::image::value_storage::one_block,
00268         const Image<I>& input,
00269         const Neighborhood<N>& nbh,
00270         const F& is_simple,
00271         const Image<K>& constraint,
00272         const Image<R>& priority)
00273       {
00274         return impl::skeleton_constrained_fast(input, nbh,
00275                                                is_simple,
00276                                                constraint,
00277                                                priority);
00278       }
00279 
00280 
00281     } 
00282 
00283 
00284     template <typename I,
00285               typename N, typename F,
00286               typename K, typename R>
00287     inline
00288     mln_ch_value(I, bool)
00289     skeleton_constrained(const Image<I>& input,
00290                          const Neighborhood<N>& nbh, const F& is_simple,
00291                          const Image<K>& constraint, const Image<R>& priority)
00292     {
00293       trace::entering("morpho::skeleton_constrained");
00294 
00295       mln_ch_value(I, bool)
00296         output = internal::skeleton_constrained_dispatch(
00297           mln_trait_image_value_access(I)(),
00298           mln_trait_image_value_storage(I)(),
00299           input, nbh, is_simple, constraint, priority);
00300 
00301       trace::exiting("morpho::skeleton_constrained");
00302       return output;
00303     }
00304 
00305 # endif // ! MLN_INCLUDE_ONLY
00306 
00307   } 
00308 
00309 } 
00310 
00311 
00312 #endif // ! MLN_MORPHO_SKELETON_CONSTRAINED_HH