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
00028 #ifndef OLENA_MORPHO_FAST_MORPHO_HXX
00029 # define OLENA_MORPHO_FAST_MORPHO_HXX
00030
00031
00032
00033
00034
00035
00036
00037 # include <mlc/is_a.hh>
00038 # include <oln/utils/histogram.hh>
00039
00040 namespace oln {
00041 namespace morpho {
00042
00045 namespace internal {
00046
00056 template<class E1, class E2, class E3>
00057 void
00058 find_struct_elts(const abstract::struct_elt<E1>& se,
00059 E2 se_add[mlc::exact<E1>::ret::dim],
00060 E3 se_rem[mlc::exact<E1>::ret::dim])
00061 {
00062 mlc_is_a(E2, abstract::struct_elt)::ensure();
00063 mlc_is_a(E3, abstract::struct_elt)::ensure();
00064 const unsigned dim = E1::dim;
00065
00066
00067 oln_dpoint_type(E1) back[dim];
00068 for (unsigned n = 0; n < dim; ++n)
00069 back[n].nth(n) = -1;
00070
00071 oln_iter_type(E1) dp(se);
00072 oln_iter_type(E1) dp_prime(se);
00073
00074 for_all(dp)
00075 {
00076 bool add[dim];
00077
00078 bool rem[dim];
00079 for (unsigned n = 0; n < dim; ++n)
00080 add[n] = rem[n] = true;
00081
00082 for_all(dp_prime)
00083 for (unsigned n = 0; n < dim; ++n)
00084 {
00085 if (dp_prime.cur() + back[n] == dp)
00086
00087 add[n] = false;
00088
00089 if (dp.cur() + back[n] == dp_prime)
00090
00091 rem[n] = false;
00092 }
00093
00094 for (unsigned n = 0; n < dim; ++n)
00095 {
00096 if (add[n])
00097 {
00098 se_add[n].add(dp);
00099 }
00100 if (rem[n])
00101 {
00102 se_rem[n].add(dp.cur() + back[n]);
00103 }
00104 }
00105 }
00106
00107 for (unsigned n = 0; n < dim; ++n)
00108 postcondition(se_add[n].card() == se_rem[n].card());
00109 }
00110
00117 template<class I, class E1, class E2, class H>
00118
00119 void
00120 hist_update(utils::abstract::histogram<H>& hist,
00121 const abstract::non_vectorial_image<I>& input,
00122 const oln_point_type(I)& p,
00123 const abstract::struct_elt<E1>& se_rem,
00124 const abstract::struct_elt<E2>& se_add)
00125 {
00126 {
00127 oln_iter_type(E1) dp(se_rem);
00128 for_all(dp)
00129 --hist[input[p + dp]];
00130 }
00131 {
00132 oln_iter_type(E2) dp(se_add);
00133 for_all(dp)
00134 ++hist[input[p + dp]];
00135 }
00136 }
00137
00138
00153 template<unsigned NP1,
00154 unsigned Dim,
00155 typename I,
00156 typename S,
00157 typename H,
00158 typename B,
00159 typename P,
00160 typename O>
00161 struct fast_morpho_inner {
00162
00166 static void
00167 doit(I& input, S& size, H& hist,
00168 B* se_add, B* se_rem, B* se_add_back, B* se_rem_back,
00169 P& p, O& output, const unsigned* dims)
00170 {
00171 const unsigned N = *dims;
00172
00173 fast_morpho_inner<NP1 + 1, Dim,
00174 I, S, H, B, P, O>::doit(input, size, hist,
00175 se_add, se_rem,
00176 se_add_back, se_rem_back, p,
00177 output, dims + 1);
00178 if (p.nth(N) == 0) {
00179 for(++p.nth(N); p.nth(N) < size.nth(N); ++p.nth(N)) {
00180 hist_update(hist, input, p, se_rem[N], se_add[N]);
00181 output[p] = hist.res();
00182 fast_morpho_inner<NP1 + 1, Dim,
00183 I, S, H, B, P, O>::doit(input, size, hist,
00184 se_add, se_rem,
00185 se_add_back,
00186 se_rem_back,
00187 p, output, dims + 1);
00188 }
00189 --p.nth(N);
00190 } else {
00191 for(--p.nth(N); p.nth(N) >= 0; --p.nth(N)) {
00192 hist_update(hist, input, p, se_rem_back[N], se_add_back[N]);
00193 output[p] = hist.res();
00194 fast_morpho_inner<NP1 + 1, Dim,
00195 I, S, H, B, P, O>::doit(input, size, hist,
00196 se_add, se_rem,
00197 se_add_back,
00198 se_rem_back,
00199 p, output, dims + 1);
00200 }
00201 ++p.nth(N);
00202 }
00203 return;
00204 }
00205 };
00206
00207 template<unsigned Dim,
00208 typename I,
00209 typename S,
00210 typename H,
00211 typename B,
00212 typename P,
00213 typename O>
00214 struct fast_morpho_inner<Dim, Dim, I, S, H, B, P, O> {
00215 static void
00216 doit(I& input, S& size, H& hist,
00217 B* se_add, B* se_rem, B* se_add_back, B* se_rem_back,
00218 P& p, O& output, const unsigned* dims)
00219 {
00220 const unsigned N = *dims;
00221
00222 if (p.nth(N) == 0) {
00223
00224
00225 oln_iter_type(B) dpr(se_rem[N]);
00226 oln_iter_type(B) dpa(se_add[N]);
00227 for(++p.nth(N);
00228 p.nth(N) < size.nth(N);
00229 ++p.nth(N)) {
00230 for_all(dpr)
00231 --hist[input[p + dpr]];
00232 for_all(dpa)
00233 ++hist[input[p + dpa]];
00234 output[p] = hist.res();
00235 }
00236 --p.nth(N);
00237 } else {
00238
00239
00240 oln_iter_type(B) dpr(se_rem_back[N]);
00241 oln_iter_type(B) dpa(se_add_back[N]);
00242 for(--p.nth(N);
00243 p.nth(N) >= 0;
00244 --p.nth(N)) {
00245 for_all(dpr)
00246 --hist[input[p + dpr]];
00247 for_all(dpa)
00248 ++hist[input[p + dpa]];
00249 output[p] = hist.res();
00250 }
00251 ++p.nth(N);
00252 }
00253 return;
00254 }
00255 };
00256 }
00257
00261 template<class E>
00262 struct sort_dimensions
00263 {
00267 sort_dimensions(abstract::struct_elt<E> se[mlc::exact<E>::ret::dim])
00268 : se_(se) {}
00269
00275 bool operator()(unsigned a, unsigned b)
00276 {
00277 return se_[a].card() > se_[b].card();
00278 }
00279
00280 protected:
00281 abstract::struct_elt<E>* se_;
00282 };
00283
00314 template<class I, class E, class H>
00315 oln_concrete_type(I)
00316 fast_morpho(const abstract::non_vectorial_image<I>& input,
00317 const abstract::struct_elt<E>& se)
00318 {
00319 enum { dim = E::dim };
00320
00321
00322 oln_concrete_type(I) output(input.size());
00323 input.border_adapt_copy(se.delta());
00324
00325
00326 E se_add[dim];
00327 E se_rem[dim];
00328 internal::find_struct_elts(se, se_add, se_rem);
00329
00330
00331 E se_add_back[dim];
00332 E se_rem_back[dim];
00333 for (unsigned n = 0; n < dim; ++n)
00334 for (unsigned i = 0; i < se_add[n].card(); ++i)
00335 {
00336 oln_dpoint_type(I) dp = se_add[n].dp(i);
00337 dp.nth(n) += 1;
00338 se_rem_back[n].add(dp);
00339
00340 dp = se_rem[n].dp(i);
00341 dp.nth(n) += 1;
00342 se_add_back[n].add(dp);
00343 }
00344
00345
00346 unsigned dims[dim];
00347 for (unsigned n = 0; n < dim; ++n)
00348 dims[n] = n;
00349 sort_dimensions<E> s(se_add);
00350 std::sort(dims, dims + dim, s);
00351
00352 const typename I::size_type size = input.size();
00353
00354
00355 H hist;
00356 oln_point_type(I) p;
00357
00358
00359 typename E::iter_type dp(se);
00360 for_all(dp)
00361 ++hist[input[p + dp]];
00362
00363
00364
00365
00366 output[p] = hist.res();
00367
00368 internal::fast_morpho_inner<1, E::dim, const I,
00369 const typename I::size_type, H,
00370 const E,oln_point_type(I),oln_concrete_type(I)>::doit(input.exact(), size, hist,
00371 se_add, se_rem,
00372 se_add_back, se_rem_back,
00373 p, output, dims);
00374 return output;
00375 }
00376
00377 }
00378 }
00379
00380 #endif // OLENA_MORPHO_FAST_MORPHO_HXX