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