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 #ifndef MLN_MORPHO_ELEMENTARY_GRADIENT_HH
00027 # define MLN_MORPHO_ELEMENTARY_GRADIENT_HH
00028 
00032 
00033 # include <mln/morpho/includes.hh>
00034 # include <mln/accu/stat/min_max.hh>
00035 
00036 
00037 namespace mln
00038 {
00039 
00040   namespace morpho
00041   {
00042 
00043     namespace elementary
00044     {
00045 
00046 
00047       template <typename I, typename N>
00048       mln_concrete(I)
00049       gradient(const Image<I>& input, const Neighborhood<N>& nbh);
00050 
00051 
00052 # ifndef MLN_INCLUDE_ONLY
00053 
00054       namespace internal
00055       {
00056 
00057         template <typename I, typename N>
00058         void
00059         gradient_tests(const Image<I>& input, const Neighborhood<N>& nbh)
00060         {
00061           mln_precondition(exact(input).is_valid());
00062           mln_precondition(exact(nbh).is_valid());
00063           (void) input;
00064           (void) nbh;
00065         }
00066 
00067       } 
00068 
00069 
00070       namespace impl
00071       {
00072 
00073         template <typename I, typename N>
00074         mln_concrete(I)
00075         gradient_on_function(const Image<I>& input_, const Neighborhood<N>& nbh_)
00076         {
00077           trace::entering("morpho::elementary::impl::gradient_on_function");
00078 
00079           const I& input = exact(input_);
00080           const N& nbh   = exact(nbh_);
00081           internal::gradient_tests(input, nbh);
00082 
00083           accu::stat::min_max<mln_value(I)> a;
00084 
00085           extension::adjust_duplicate(input, nbh);
00086 
00087           mln_concrete(I) output;
00088           initialize(output, input);
00089 
00090           mln_piter(I) p(input.domain());
00091           mln_niter(N) n(nbh, p);
00092           for_all(p)
00093             {
00094               a.take_as_init(input(p));
00095               for_all(n) if (input.has(n))
00096                 a.take(input(n));
00097               output(p) = a.second() - a.first();
00098             }
00099 
00100           trace::exiting("morpho::elementary::impl::gradient_on_function");
00101           return output;
00102         }
00103 
00104         template <typename I, typename N>
00105         mln_concrete(I)
00106         gradient_on_set(const Image<I>& input_, const Neighborhood<N>& nbh_)
00107         {
00108           trace::entering("morpho::elementary::impl::gradient_on_set");
00109 
00110           const I& input = exact(input_);
00111           const N& nbh   = exact(nbh_);
00112           internal::gradient_tests(input, nbh);
00113 
00114           extension::adjust_duplicate(input, nbh);
00115 
00116           mln_concrete(I) output;
00117           initialize(output, input);
00118           data::fill(output, false);
00119 
00120           mln_piter(I) p(input.domain());
00121           mln_niter(N) n(nbh, p);
00122           for_all(p)
00123             if (input(p) == true)
00124               {
00125                 for_all(n) if (input.has(n))
00126                   if (input(n) == false)
00127                     {
00128                       output(p) = true;
00129                       break;
00130                     }
00131               }
00132             else 
00133               {
00134                 for_all(n) if (input.has(n))
00135                   if (input(n) == true)
00136                     {
00137                       output(p) = true;
00138                       break;
00139                     }
00140               }
00141 
00142           trace::exiting("morpho::elementary::impl::gradient_on_set");
00143           return output;
00144         }
00145 
00146 
00147         template <typename I, typename N>
00148         mln_concrete(I)
00149         gradient_on_function_fastest(const Image<I>& input_, const Neighborhood<N>& nbh_)
00150         {
00151           trace::entering("morpho::elementary::impl::gradient_on_function_fastest");
00152 
00153           const I& input = exact(input_);
00154           const N& nbh   = exact(nbh_);
00155           internal::gradient_tests(input, nbh);
00156 
00157           accu::stat::min_max<mln_value(I)> a;
00158           extension::adjust_duplicate(input, nbh);
00159 
00160           typedef mln_concrete(I) O;
00161           O output;
00162           initialize(output, input);
00163 
00164           mln_pixter(const I) p_in(input);
00165           mln_pixter(O) p_out(output);
00166           mln_nixter(const I, N) n(p_in, nbh);
00167           for_all_2(p_in, p_out)
00168             {
00169               a.take_as_init(p_in.val());
00170               for_all(n)
00171                 a.take(n.val());
00172               p_out.val() = a.second() - a.first();
00173             }
00174 
00175           trace::exiting("morpho::elementary::impl::gradient_on_function_fastest");
00176           return output;
00177         }
00178 
00179       } 
00180 
00181 
00182       namespace internal
00183       {
00184 
00185         
00186 
00187         template <typename I, typename N>
00188         mln_concrete(I)
00189         gradient_dispatch(trait::image::kind::any,
00190                           trait::image::speed::any,
00191                           const Image<I>& input, const Neighborhood<N>& nbh)
00192         {
00193           return impl::gradient_on_function(input, nbh);
00194         }
00195 
00196         template <typename I, typename N>
00197         mln_concrete(I)
00198         gradient_dispatch(trait::image::kind::any,
00199                           trait::image::speed::fastest,
00200                           const Image<I>& input, const Neighborhood<N>& nbh)
00201         {
00202           return impl::gradient_on_function_fastest(input, nbh);
00203         }
00204 
00205         template <typename I, typename N>
00206         mln_concrete(I)
00207         gradient_dispatch(trait::image::kind::logic,
00208                           trait::image::speed::any,
00209                           const Image<I>& input, const Neighborhood<N>& nbh)
00210         {
00211           return impl::gradient_on_set(input, nbh);
00212         }
00213 
00214         
00215         
00216         template <typename I, typename N>
00217         mln_concrete(I)
00218         gradient_dispatch(trait::image::kind::logic,
00219                           trait::image::speed::fastest,
00220                           const Image<I>& input, const Neighborhood<N>& nbh)
00221         {
00222           return impl::gradient_on_set(input, nbh);
00223         }
00224 
00225         template <typename I, typename N>
00226         mln_concrete(I)
00227         gradient_dispatch(const Image<I>& input, const Neighborhood<N>& nbh)
00228         {
00229           return gradient_dispatch(mln_trait_image_kind(I)(),
00230                                    mln_trait_image_speed(I)(),
00231                                    input, nbh);
00232         }
00233 
00234       } 
00235 
00236 
00237       
00238 
00239       template <typename I, typename N>
00240       mln_concrete(I)
00241         gradient(const Image<I>& input, const Neighborhood<N>& nbh)
00242       {
00243         trace::entering("morpho::elementary::gradient");
00244 
00245         internal::gradient_tests(input, nbh);
00246         mln_concrete(I) output = internal::gradient_dispatch(input, nbh);
00247         
00248         trace::exiting("morpho::elementary::gradient");
00249         return output;
00250       }
00251 
00252 # endif // ! MLN_INCLUDE_ONLY
00253 
00254     } 
00255 
00256   } 
00257 
00258 } 
00259 
00260 
00261 #endif // ! MLN_MORPHO_ELEMENTARY_GRADIENT_HH