https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add some experimental code about TUFA and regional minima.
* geraud/tufa_2008: New directory.
* geraud/tufa_2008/steps.0.cc: New.
* geraud/tufa_2008/compute_a.cc: New.
* geraud/tufa_2008/steps.1.cc: New.
* geraud/tufa_2008/steps.2.cc: New.
* geraud/tufa_2008/closing.cc: New.
* geraud/tufa_2008/steps.3.cc: New.
* geraud/tufa_2008/opening.cc: New.
* geraud/tufa_2008/experiment.cc: New.
* geraud/tufa_2008/steps.2b.cc: New.
* geraud/tufa_2008/filter.cc: New.
* geraud/tufa_2008/wst_f_equal_wst_a.cc: New.
* geraud/tufa_2008/closed_gradient.cc: New.
* geraud/tufa_2008/fz_count.cc: New.
* geraud/tufa_2008/regmin_count.cc: New.
closed_gradient.cc | 64 +++++++
closing.cc | 64 +++++++
compute_a.cc | 411 +++++++++++++++++++++++++++++++++++++++++++++++++++
experiment.cc | 138 +++++++++++++++++
filter.cc | 169 ++++++++++++++++++++
fz_count.cc | 159 +++++++++++++++++++
opening.cc | 63 +++++++
regmin_count.cc | 173 +++++++++++++++++++++
steps.0.cc | 170 +++++++++++++++++++++
steps.1.cc | 273 +++++++++++++++++++++++++++++++++
steps.2.cc | 184 ++++++++++++++++++++++
steps.2b.cc | 184 ++++++++++++++++++++++
steps.3.cc | 184 ++++++++++++++++++++++
wst_f_equal_wst_a.cc | 140 +++++++++++++++++
14 files changed, 2376 insertions(+)
Index: geraud/tufa_2008/steps.0.cc
--- geraud/tufa_2008/steps.0.cc (revision 0)
+++ geraud/tufa_2008/steps.0.cc (revision 0)
@@ -0,0 +1,170 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/steps.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/tree/data.hh>
+
+#include <mln/accu/count.hh>
+
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/morpho/closing_area.hh>
+#include <mln/level/fill.hh>
+
+
+namespace mln
+{
+
+ template <typename I>
+ void println_par(const I& par)
+ {
+ int nr = par.nrows(), nc = par.ncols();
+ for (int r = 0; r < nr; ++r)
+ {
+ for (int c = 0; c < nc; ++c)
+ if (par.at(r,c) == point2d(r,c))
+ std::cout << "( ) ";
+ else
+ std::cout << par.at(r,c) << ' ';
+ std::cout << std::endl;
+ }
+ }
+
+ template <typename P>
+ inline
+ mln_value(P) find_root__(P& par, const mln_value(P)& x)
+ {
+ if (par(x) == x)
+ return x;
+ else
+ return par(x) = find_root__(par, par(x));
+ }
+
+
+ template <typename I, typename A, typename N>
+ mln_concrete(I) filtering(const I& f, const A& a, const N& nbh,
mln_value(A) lambda)
+ {
+ typedef p_array<mln_psite(I)> S;
+ S s = level::sort_psites_increasing(a);
+
+ // s maps increasing attributes.
+
+ mln_concrete(I) out;
+ initialize(out, f);
+
+ mln_ch_value(I, mln_site(I)) par;
+ mln_ch_value(I, bool) deja_vu;
+ {
+ initialize(par, f);
+ mln_piter(A) p(par.domain());
+ for_all(p)
+ par(p) = p;
+ initialize(deja_vu, f);
+ level::fill(deja_vu, false);
+ }
+
+ // First pass.
+ {
+ mln_site(I) r;
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (a.domain().has(n) && deja_vu(n))
+ {
+ r = find_root__(par, n);
+ if (r != p)
+ if (f(r) == f(p) || a(r) < lambda)
+ par(r) = p; // Union.
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ // Second pass.
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ if (par(p) == p)
+ out(p) = f(p);
+ else
+ out(p) = out(par(p));
+ }
+ return out;
+ }
+
+
+} // mln
+
+
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ int_u8 n;
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, "../../../img/fly.pgm");
+ debug::println("f =", f);
+
+ debug::println("ref =", morpho::closing_area(f, c4(), 10));
+
+ typedef p_array<point2d> S;
+ S s = level::sort_psites_decreasing(f);
+
+ // Children go towards lower levels so leafs are regional minima.
+ // We get a min-tree so that we can perform morphological closings.
+
+ morpho::tree::data<I,S> t(f, s, c4());
+ accu::count< util::pix<I> > attr;
+
+ image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
+ I g = filtering(f, a, c4(), 10);
+ debug::println("g =", g);
+
+ {
+ S s = level::sort_psites_decreasing(g);
+ morpho::tree::data<I,S> t(g, s, c4());
+ image2d<unsigned> a_g = morpho::tree::compute_attribute_image(attr, t);
+ debug::println("a(f) =", a);
+ debug::println("a(g) =", a_g);
+ }
+
+}
Index: geraud/tufa_2008/compute_a.cc
--- geraud/tufa_2008/compute_a.cc (revision 0)
+++ geraud/tufa_2008/compute_a.cc (revision 0)
@@ -0,0 +1,411 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/compute_a.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/pw/all.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/level/fill.hh>
+#include <mln/level/paste.hh>
+#include <mln/level/compare.hh>
+
+#include <mln/morpho/tree/data.hh>
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/labeling/regional_minima.hh>
+
+#include <mln/accu/count.hh>
+
+
+
+namespace mln
+{
+
+ template <typename I>
+ void println_par(const I& par)
+ {
+ int nr = par.nrows(), nc = par.ncols();
+ for (int r = 0; r < nr; ++r)
+ {
+ for (int c = 0; c < nc; ++c)
+ if (par.at(r,c) == point2d(r,c))
+ std::cout << "( ) ";
+ else
+ std::cout << par.at(r,c) << ' ';
+ std::cout << std::endl;
+ }
+ }
+
+
+ template <typename P>
+ inline
+ mln_value(P) find_root__(P& par, const mln_value(P)& x)
+ {
+ if (par(x) == x)
+ return x;
+ else
+ return par(x) = find_root__(par, par(x));
+ }
+
+
+
+ //------------------------------- compute_a
+
+
+
+ template <typename I, typename N, typename A>
+ mln_ch_value(I, mln_result(A))
+ compute_a(const I& f, const N& nbh, A, unsigned& n_regmins)
+ {
+ typedef p_array<mln_psite(I)> S;
+ S s = level::sort_psites_increasing(f);
+ // s maps increasing attributes.
+
+ mln_ch_value(I, mln_site(I)) par;
+ mln_ch_value(I, mln_site(I)) zpar;
+ mln_ch_value(I, bool) deja_vu, flag;
+ mln_ch_value(I, A) attr;
+
+ n_regmins = f.domain().nsites();
+
+
+ // Initialization.
+ {
+ // parent
+ initialize(par, f);
+ initialize(zpar, f);
+
+ // deja_vu
+ initialize(deja_vu, f);
+ level::fill(deja_vu, false);
+
+ // flag
+ initialize(flag, f);
+ level::fill(flag, true);
+
+ // attr
+ initialize(attr, f);
+ }
+
+
+ // First Pass.
+ {
+ mln_site(I) r;
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ // Make-Set.
+ par(p) = p;
+ zpar(p) = p;
+ attr(p).take_as_init(p);
+
+ for_all(n)
+ if (f.domain().has(n) && deja_vu(n))
+ {
+ r = find_root__(zpar, n);
+ if (r != p)
+ {
+ // Fully compressed union.
+ zpar(r) = p;
+ attr(p).take(attr(r));
+
+ if (f(r) == f(p))
+ {
+ // Weak-Union; only for flat zones.
+ par(r) = p;
+
+ if (flag(p) == false && flag(r) == false)
+ {
+ // Two non-reg-min components merge (same flat
+ // zone) so we had an extra invalidation.
+ ++n_regmins;
+ }
+ flag(p) = flag(p) && flag(r);
+ --n_regmins; // So we get the number of flat zones
+ // minus the non-reg-min flat zones.
+ }
+ else
+ {
+ mln_invariant(f(r) < f(p));
+ if (flag(p) == true)
+ --n_regmins; // Invalidation.
+ flag(p) = false;
+ }
+ }
+ }
+ deja_vu(p) = true;
+ }
+ } // end of First Pass.
+
+
+ std::cout << "n reg min = " << n_regmins << std::endl;
+
+
+ {
+ unsigned n = 0;
+ mln_fwd_piter(S) p(s);
+ for_all(p)
+ if (par(p) == p && flag(p))
+ ++n;
+ mln_assertion(n == n_regmins);
+ }
+
+
+ // The attr image is not correct on flat zones since there is
+ // no back-propagation of the attribute value of the component
+ // root. For instance with f="v v v" we get attr="1 2 3"
+ // instead of "3 3 3". So a finalization is required.
+
+ mln_ch_value(I, mln_result(A)) a;
+ initialize(a, f);
+ level::paste(attr, a);
+
+ // Finalization.
+ {
+ mln_bkd_piter(S) p(s); // Reverse.
+
+ unsigned n_non_compressed_par = 0;
+ for_all(p)
+ {
+ a(p) = a(par(p));
+ if (par(par(p)) != par(p))
+ ++ n_non_compressed_par;
+ }
+ std::cout << "n_non_compressed_par = " <<
n_non_compressed_par << std::endl;
+ }
+
+ // TODO: compress at least the reg minima!
+
+
+ {
+ image2d<unsigned> regmin;
+ initialize(regmin, f);
+ {
+ unsigned i_regmin = 0;
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ {
+ if (par(p) == p)
+ {
+ if (flag(p))
+ regmin(p) = ++i_regmin;
+ else
+ regmin(p) = 0;
+ }
+ else
+ regmin(p) = regmin(par(p));
+ }
+ }
+
+ debug::println("f", f);
+
+ debug::println("flag", flag);
+ // We can see that some point are at true for components that
+ // are not reg min; flag is a candidate to be compressed...
+
+ debug::println("regmin", regmin);
+
+
+
+ // TODO:
+
+ // On veut tester ici dans quel ordre on voit les
+ // reg min lorsque a croit. Pour tous les points d'un reg min,
+ // est-ce que le root est vu en premier ?
+
+
+
+ image2d<bool> seen;
+ initialize(seen, f);
+ level::fill(seen, false);
+
+ s = level::sort_psites_increasing(a);
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ {
+ if (regmin(p) == 0)
+ continue;
+ // p is in a regional minimum.
+ if (par(p) != p) // A non-root point.
+ {
+ mln_assertion(regmin(par(p)) != 0); // Root in a regional minimum.
+ mln_assertion(regmin(par(p)) == regmin(p)); // and the same as p.
+ mln_assertion(seen(par(p)));
+ }
+ seen(p) = true;
+ }
+ debug::println(seen);
+
+// if (flag(p))
+// std::cout << a(p) << ' ' << p << ' '
<< (par(p) == p) << std::endl;
+
+ }
+
+ return a;
+ }
+
+
+
+ //------------------------------- filtering
+
+
+
+// template <typename I, typename A, typename N>
+// mln_concrete(I) filtering(const I& f, const A& a, const N& nbh,
+// unsigned n_regmins, unsigned n_wanted)
+// {
+// typedef p_array<mln_psite(I)> S;
+// S s = level::sort_psites_increasing(a);
+
+// // s maps increasing attributes.
+
+// mln_concrete(I) out;
+// initialize(out, f);
+
+// mln_ch_value(I, mln_site(I)) par;
+// mln_ch_value(I, bool) deja_vu, flag;
+
+// // Initialization.
+// {
+// initialize(par, f);
+// mln_piter(A) p(par.domain());
+// for_all(p)
+// par(p) = p;
+// initialize(deja_vu, f);
+// level::fill(deja_vu, false);
+
+// // flag
+// initialize(flag, f);
+// level::fill(flag, true);
+// }
+
+
+// int counter = 0;
+// // We are trying to count the number of merges of regional minima...
+
+
+// // First Pass.
+// {
+// mln_site(I) r;
+// mln_fwd_piter(S) p(s);
+// mln_niter(N) n(nbh, p);
+// for_all(p)
+// {
+// for_all(n)
+// if (a.domain().has(n) && deja_vu(n))
+// {
+// r = find_root__(par, n);
+// if (r != p)
+// if (a(r) == a(p))
+// {
+// par(r) = p; // Union.
+// if (flag(r) == true && flag(p) == true)
+// --counter;
+// flag(p) = flag(p) && flag(r);
+// }
+// else // a(r) != a(p)
+// {
+// if (flag(r) == true && flag(p) == true)
+// ++counter;
+// mln_invariant(a(p) > a(r));
+// flag(p) = false;
+// }
+// }
+// deja_vu(p) = true;
+// }
+// std::cout << counter << std::endl;
+// }
+
+// // // Second Pass.
+// // {
+// // mln_bkd_piter(S) p(s);
+// // for_all(p)
+// // if (par(p) == p)
+// // out(p) = f(p);
+// // else
+// // out(p) = out(par(p));
+// // }
+
+// return out;
+// }
+
+
+
+
+} // mln
+
+
+
+
+int main(int, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, argv[1]);
+ // debug::println(f);
+
+ accu::count<point2d> area;
+ unsigned n_regmins;
+ image2d<unsigned> a = compute_a(f, c4(), area, n_regmins);
+ // debug::println(a);
+
+// {
+// // Test of 'n_regmins'.
+// unsigned ref;
+// labeling::regional_minima(f, c4(), ref);
+// mln_assertion(n_regmins == ref);
+// }
+
+// {
+// // Test of 'a'.
+// typedef p_array<point2d> S;
+// S s = level::sort_psites_decreasing(f);
+// morpho::tree::data<I,S> t(f, s, c4());
+// accu::count< util::pix<I> > area;
+// image2d<unsigned> ref = morpho::tree::compute_attribute_image(area, t);
+// mln_assertion(a == ref);
+// }
+
+
+
+
+
+// unsigned n_wanted = 10;
+// I g = filtering(f, a, c4(), n_regmins, n_wanted);
+
+}
Index: geraud/tufa_2008/steps.1.cc
--- geraud/tufa_2008/steps.1.cc (revision 0)
+++ geraud/tufa_2008/steps.1.cc (revision 0)
@@ -0,0 +1,273 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/steps.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/tree/data.hh>
+
+#include <mln/accu/count.hh>
+#include <mln/util/set.hh>
+
+#include <mln/labeling/regional_minima.hh>
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/morpho/closing_area.hh>
+#include <mln/level/fill.hh>
+
+
+namespace mln
+{
+
+ template <typename I>
+ void println_par(const I& par)
+ {
+ int nr = par.nrows(), nc = par.ncols();
+ for (int r = 0; r < nr; ++r)
+ {
+ for (int c = 0; c < nc; ++c)
+ if (par.at(r,c) == point2d(r,c))
+ std::cout << "( ) ";
+ else
+ std::cout << par.at(r,c) << ' ';
+ std::cout << std::endl;
+ }
+ }
+
+ template <typename P>
+ inline
+ mln_value(P) find_root__(P& par, const mln_value(P)& x)
+ {
+ if (par(x) == x)
+ return x;
+ else
+ return par(x) = find_root__(par, par(x));
+ }
+
+
+ template <typename I, typename A, typename N>
+ void run_run(const I& f, const A& a, const N& nbh)
+ {
+ typedef p_array<mln_psite(I)> S;
+ S s = level::sort_psites_increasing(a);
+ // s maps increasing attributes.
+
+ mln_ch_value(I, mln_site(I)) par;
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, util::set<unsigned>) labels;
+ unsigned nbassins, current_n;
+
+
+ // Initialization.
+ {
+ mln_piter(A) p(f.domain());
+
+ // parent
+ initialize(par, f);
+ for_all(p)
+ par(p) = p;
+
+ // deja_vu
+ initialize(deja_vu, f);
+ level::fill(deja_vu, false);
+
+ // labels
+ mln_ch_value(I, unsigned) regmin = labeling::regional_minima(a, nbh,
+ nbassins);
+ debug::println(regmin);
+ initialize(labels, f);
+ for_all(p)
+ if (regmin(p) != 0) // p in a reg min of the attribute image
+ labels(p).insert(regmin(p));
+ }
+
+ current_n = nbassins;
+
+ // First pass.
+ {
+ mln_site(I) r;
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (a.domain().has(n) && deja_vu(n))
+ {
+ r = find_root__(par, n);
+ if (r != p)
+ {
+ par(r) = p; // Union.
+
+ // logging the different cases
+ if (labels(p).is_empty() && labels(r).is_empty())
+ {
+ std::cout << "x";
+
+ // It can happen with:
+ // M M m
+ // (m a min, M a flat zone)
+ // During the pass:
+ // M M {m}
+ // then the 1st point is processed
+ // {} M {m}
+ // and when processing the 2nd point
+ // r={} p={} {m}
+ // the (left) neighbor of p has an empty set such as p.
+
+// // Extra log.
+// std::cout << std::endl
+// << "p = " << p << " "
+// << "r = " << r << std::endl;
+// debug::println(labels);
+ }
+ else
+ if (labels(p).is_empty() || labels(r).is_empty())
+ {
+ std::cout << (labels(p).is_empty() ? 'p' : 'r');
+ }
+ else
+ if (labels(p) == labels(r))
+ {
+ std::cout << "=";
+// // Extra log.
+// std::cout << std::endl
+// << "p = " << p << " "
+// << "r = " << r << std::endl;
+// debug::println(labels);
+ }
+ else
+ std::cout << ".";
+ // end of log
+
+ // The invariants below are erroneous.
+// mln_invariant(! (labels(p).is_empty() && labels(r).is_empty()));
+// mln_invariant(labels(p) != labels(r));
+
+ // Either:
+ // one of the two label sets is empty (and the other is not)
+ // or:
+ // both label sets are not empty then they differ.
+
+ // More restrictively:
+// mln_invariant(! labels(r).is_empty());
+
+ if (labels(p).is_empty())
+ {
+ labels(p).insert(labels(r));
+ }
+ else
+ {
+
+// std::cout << std::endl
+// << "at " << p << std::endl
+// << "before:" << std::endl;
+// debug::println(labels);
+
+ unsigned
+ np = labels(p).nelements(),
+ nr = labels(r).nelements();
+ labels(p).insert(labels(r));
+ unsigned
+ n = labels(p).nelements(),
+ dnp = n - np,
+ dnr = n - nr,
+ delta_n = std::min(dnp, dnr);
+
+ // The invariant below is erroneous.
+// mln_invariant(delta_n != 0);
+
+
+// std::cout << "delta = " << delta_n << std::endl
+// << "after: " << std::endl;
+// debug::println(labels);
+
+
+ // We can have the three cases below:
+ if (dnr > dnp)
+ std::cout << '>';
+ else
+ if (dnr < dnp)
+ std::cout << '<';
+ else
+ std::cout << '~';
+ std::cout << '(' << delta_n << ')';
+ }
+ }
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ std::cout << std::endl;
+// debug::println(labels);
+ }
+
+
+} // mln
+
+
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ int_u8 n;
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, "../../../img/tiny.pgm");
+// debug::println("f =", f);
+
+ typedef p_array<point2d> S;
+ S s = level::sort_psites_decreasing(f);
+
+ // Children go towards lower levels so leafs are regional minima.
+ // We get a min-tree so that we can perform morphological closings.
+
+ morpho::tree::data<I,S> t(f, s, c4());
+ accu::count< util::pix<I> > attr;
+
+ image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
+ run_run(f, a, c4());
+
+// {
+// S s = level::sort_psites_decreasing(g);
+// morpho::tree::data<I,S> t(g, s, c4());
+// image2d<unsigned> a_g = morpho::tree::compute_attribute_image(attr, t);
+// debug::println("a(f) =", a);
+// debug::println("a(g) =", a_g);
+// }
+
+}
Index: geraud/tufa_2008/steps.2.cc
--- geraud/tufa_2008/steps.2.cc (revision 0)
+++ geraud/tufa_2008/steps.2.cc (revision 0)
@@ -0,0 +1,184 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/steps.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/tree/data.hh>
+
+#include <mln/accu/count.hh>
+#include <mln/util/set.hh>
+
+#include <mln/labeling/regional_minima.hh>
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/morpho/closing_area.hh>
+#include <mln/level/fill.hh>
+
+
+namespace mln
+{
+
+ template <typename I>
+ void println_par(const I& par)
+ {
+ int nr = par.nrows(), nc = par.ncols();
+ for (int r = 0; r < nr; ++r)
+ {
+ for (int c = 0; c < nc; ++c)
+ if (par.at(r,c) == point2d(r,c))
+ std::cout << "( ) ";
+ else
+ std::cout << par.at(r,c) << ' ';
+ std::cout << std::endl;
+ }
+ }
+
+ template <typename P>
+ inline
+ mln_value(P) find_root__(P& par, const mln_value(P)& x)
+ {
+ if (par(x) == x)
+ return x;
+ else
+ return par(x) = find_root__(par, par(x));
+ }
+
+
+ template <typename I, typename A, typename N>
+ void run_run(const I& f, const A& a, const N& nbh)
+ {
+ typedef p_array<mln_psite(I)> S;
+ S s = level::sort_psites_increasing(a);
+ // s maps increasing attributes.
+
+ mln_ch_value(I, mln_site(I)) par;
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, util::set<unsigned>) labels;
+ unsigned nbassins, current_n;
+
+
+ // Initialization.
+ {
+ mln_piter(A) p(f.domain());
+
+ // parent
+ initialize(par, f);
+ for_all(p)
+ par(p) = p;
+
+ // deja_vu
+ initialize(deja_vu, f);
+ level::fill(deja_vu, false);
+
+ // labels
+ mln_ch_value(I, unsigned) regmin = labeling::regional_minima(a, nbh,
+ nbassins);
+ initialize(labels, f);
+ for_all(p)
+ if (regmin(p) != 0) // p in a reg min of the attribute image
+ labels(p).insert(regmin(p));
+ }
+
+ current_n = nbassins;
+
+ // First pass.
+ {
+ mln_site(I) r;
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (a.domain().has(n) && deja_vu(n))
+ {
+ r = find_root__(par, n);
+ if (r != p)
+ {
+ par(r) = p; // Union.
+
+ if (labels(r).is_empty())
+ // No-op.
+ ;
+ else
+ if (labels(p).is_empty())
+ labels(p) = labels(r);
+ else
+ if (labels(p) == labels(r))
+ // No-op.
+ ;
+ else
+ {
+ labels(p).insert(labels(r));
+ --current_n;
+ }
+ }
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ std::cout << std::endl;
+ std::cout << "end = " << current_n << std::endl;
+ }
+
+
+} // mln
+
+
+
+
+int main(int, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ int_u8 n;
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, argv[1]);
+
+ typedef p_array<point2d> S;
+ S s = level::sort_psites_decreasing(f);
+
+ // Children go towards lower levels so leafs are regional minima.
+ // We get a min-tree so that we can perform morphological closings.
+
+ morpho::tree::data<I,S> t(f, s, c4());
+ accu::count< util::pix<I> > attr;
+
+ image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
+ run_run(f, a, c4());
+
+}
Index: geraud/tufa_2008/closing.cc
--- geraud/tufa_2008/closing.cc (revision 0)
+++ geraud/tufa_2008/closing.cc (revision 0)
@@ -0,0 +1,64 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/closing.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/morpho/elementary/gradient.hh>
+#include <mln/morpho/closing_volume.hh>
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm
lambda output.pgm" << std::endl;
+ std::abort();
+}
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc != 4)
+ usage(argv);
+
+ image2d<int_u8> f;
+ io::pgm::load(f, argv[1]);
+ unsigned lambda = std::atoi(argv[2]);
+ io::pgm::save(morpho::closing_volume(f,
+ c4(),
+ lambda),
+ argv[3]);
+}
Index: geraud/tufa_2008/steps.3.cc
--- geraud/tufa_2008/steps.3.cc (revision 0)
+++ geraud/tufa_2008/steps.3.cc (revision 0)
@@ -0,0 +1,184 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/steps.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/tree/data.hh>
+
+#include <mln/accu/count.hh>
+#include <mln/util/set.hh>
+
+#include <mln/labeling/regional_minima.hh>
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/morpho/closing_area.hh>
+#include <mln/level/fill.hh>
+
+
+namespace mln
+{
+
+ template <typename I>
+ void println_par(const I& par)
+ {
+ int nr = par.nrows(), nc = par.ncols();
+ for (int r = 0; r < nr; ++r)
+ {
+ for (int c = 0; c < nc; ++c)
+ if (par.at(r,c) == point2d(r,c))
+ std::cout << "( ) ";
+ else
+ std::cout << par.at(r,c) << ' ';
+ std::cout << std::endl;
+ }
+ }
+
+ template <typename P>
+ inline
+ mln_value(P) find_root__(P& par, const mln_value(P)& x)
+ {
+ if (par(x) == x)
+ return x;
+ else
+ return par(x) = find_root__(par, par(x));
+ }
+
+
+ template <typename I, typename A, typename N>
+ void run_run(const I& f, const A& a, const N& nbh)
+ {
+ typedef p_array<mln_psite(I)> S;
+ S s = level::sort_psites_increasing(a);
+ // s maps increasing attributes.
+
+ mln_ch_value(I, mln_site(I)) par;
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, util::set<unsigned>) labels;
+ unsigned nbassins, current_n;
+
+
+ // Initialization.
+ {
+ mln_piter(A) p(f.domain());
+
+ // parent
+ initialize(par, f);
+ for_all(p)
+ par(p) = p;
+
+ // deja_vu
+ initialize(deja_vu, f);
+ level::fill(deja_vu, false);
+
+ // labels
+ mln_ch_value(I, unsigned) regmin = labeling::regional_minima(a, nbh,
+ nbassins);
+ initialize(labels, f);
+ for_all(p)
+ if (regmin(p) != 0) // p in a reg min of the attribute image
+ labels(p).insert(regmin(p));
+ }
+
+ current_n = nbassins;
+
+ // First pass.
+ {
+ mln_site(I) r;
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (a.domain().has(n) && deja_vu(n))
+ {
+ r = find_root__(par, n);
+ if (r != p)
+ {
+ par(r) = p; // Union.
+
+ if (labels(r).is_empty())
+ // No-op.
+ ;
+ else
+ if (labels(p).is_empty())
+ labels(p) = labels(r);
+ else
+ if (labels(p) == labels(r))
+ // No-op.
+ ;
+ else
+ {
+ labels(p).insert(labels(r));
+ --current_n;
+ }
+ }
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ std::cout << std::endl;
+ std::cout << "end = " << current_n << std::endl;
+ }
+
+
+} // mln
+
+
+
+
+int main(int, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ int_u8 n;
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, argv[1]);
+
+ typedef p_array<point2d> S;
+ S s = level::sort_psites_decreasing(f);
+
+ // Children go towards lower levels so leafs are regional minima.
+ // We get a min-tree so that we can perform morphological closings.
+
+ morpho::tree::data<I,S> t(f, s, c4());
+ accu::count< util::pix<I> > attr;
+
+ image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
+ run_run(f, a, c4());
+
+}
Index: geraud/tufa_2008/opening.cc
--- geraud/tufa_2008/opening.cc (revision 0)
+++ geraud/tufa_2008/opening.cc (revision 0)
@@ -0,0 +1,63 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/opening.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/morpho/opening_volume.hh>
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm
lambda output.pgm" << std::endl;
+ std::abort();
+}
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc != 4)
+ usage(argv);
+
+ image2d<int_u8> f, g;
+ io::pgm::load(f, argv[1]);
+ unsigned lambda = std::atoi(argv[2]);
+ initialize(g, f);
+ morpho::opening_volume(f, c4(), lambda, g);
+ io::pgm::save(g,
+ argv[3]);
+}
Index: geraud/tufa_2008/experiment.cc
--- geraud/tufa_2008/experiment.cc (revision 0)
+++ geraud/tufa_2008/experiment.cc (revision 0)
@@ -0,0 +1,138 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/experiment.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/literal/black.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/tree/data.hh>
+
+#include <mln/accu/volume.hh>
+#include <mln/win/disk2d.hh>
+
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/morpho/meyer_wst.hh>
+#include <mln/morpho/opening.hh>
+#include <mln/morpho/closing_area.hh>
+
+#include <mln/level/fill.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/stretch.hh>
+
+
+
+namespace mln
+{
+
+ struct colorize : Function_v2v< colorize >
+ {
+ typedef value::rgb8 result;
+ colorize(unsigned max)
+ : lut(max + 1)
+ {
+ lut[0] = literal::black;
+ for (unsigned i = 1; i <= max; ++i)
+ lut[i] = result(100 + std::rand() % 150,
+ 100 + std::rand() % 150,
+ 100 + std::rand() % 150);
+ }
+ result operator()(unsigned i) const
+ {
+ return lut[i];
+ }
+ std::vector<result> lut;
+ };
+
+} // mln
+
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm"
<< std::endl;
+ std::abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc != 2)
+ usage(argv);
+
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, argv[1]);
+
+ typedef p_array<point2d> S;
+ S s = level::sort_psites_decreasing(f);
+
+ // Children go towards lower levels so leafs are regional minima.
+ // We get a min-tree so that we can perform morphological closings.
+
+ morpho::tree::data<I,S> t(f, s, c4());
+ accu::volume<I> attr;
+
+ image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
+ io::pgm::save(level::stretch(int_u8(), a),
+ "a.pgm");
+
+ unsigned n;
+ image2d<unsigned> wst_a = morpho::meyer_wst(a, c4(), n);
+ io::ppm::save(level::transform(wst_a, colorize(n)),
+ "wst_a.ppm");
+ std::cout << "n(a) = " << n << std::endl;
+
+ // FIXME: ça n'a pas de sens de faire ce qui est dessous... :-(
+
+
+ image2d<unsigned> aa = morpho::closing_area(a, c4(), 100);
+ io::pgm::save(level::stretch(int_u8(), aa),
+ "aa.pgm");
+
+ image2d<unsigned> wst_aa = morpho::meyer_wst(aa, c4(), n);
+ io::ppm::save(level::transform(wst_aa, colorize(n)),
+ "wst_aa.ppm");
+ std::cout << "n(aa) = " << n << std::endl;
+}
Index: geraud/tufa_2008/steps.2b.cc
--- geraud/tufa_2008/steps.2b.cc (revision 0)
+++ geraud/tufa_2008/steps.2b.cc (revision 0)
@@ -0,0 +1,184 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/steps.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/tree/data.hh>
+
+#include <mln/accu/count.hh>
+#include <set>
+
+#include <mln/labeling/regional_minima.hh>
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/morpho/closing_area.hh>
+#include <mln/level/fill.hh>
+
+
+namespace mln
+{
+
+ template <typename I>
+ void println_par(const I& par)
+ {
+ int nr = par.nrows(), nc = par.ncols();
+ for (int r = 0; r < nr; ++r)
+ {
+ for (int c = 0; c < nc; ++c)
+ if (par.at(r,c) == point2d(r,c))
+ std::cout << "( ) ";
+ else
+ std::cout << par.at(r,c) << ' ';
+ std::cout << std::endl;
+ }
+ }
+
+ template <typename P>
+ inline
+ mln_value(P) find_root__(P& par, const mln_value(P)& x)
+ {
+ if (par(x) == x)
+ return x;
+ else
+ return par(x) = find_root__(par, par(x));
+ }
+
+
+ template <typename I, typename A, typename N>
+ void run_run(const I& f, const A& a, const N& nbh)
+ {
+ typedef p_array<mln_psite(I)> S;
+ S s = level::sort_psites_increasing(a);
+ // s maps increasing attributes.
+
+ mln_ch_value(I, mln_site(I)) par;
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, std::set<unsigned>) labels;
+ unsigned nbassins, current_n;
+
+
+ // Initialization.
+ {
+ mln_piter(A) p(f.domain());
+
+ // parent
+ initialize(par, f);
+ for_all(p)
+ par(p) = p;
+
+ // deja_vu
+ initialize(deja_vu, f);
+ level::fill(deja_vu, false);
+
+ // labels
+ mln_ch_value(I, unsigned) regmin = labeling::regional_minima(a, nbh,
+ nbassins);
+ initialize(labels, f);
+ for_all(p)
+ if (regmin(p) != 0) // p in a reg min of the attribute image
+ labels(p).insert(regmin(p));
+ }
+
+ current_n = nbassins;
+
+ // First pass.
+ {
+ mln_site(I) r;
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (a.domain().has(n) && deja_vu(n))
+ {
+ r = find_root__(par, n);
+ if (r != p)
+ {
+ par(r) = p; // Union.
+
+ if (labels(r).empty())
+ // No-op.
+ ;
+ else
+ if (labels(p).empty())
+ labels(p) = labels(r);
+ else
+ if (labels(p) == labels(r))
+ // No-op.
+ ;
+ else
+ {
+ labels(p).insert(labels(r).begin(), labels(r).end());
+ --current_n;
+ }
+ }
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ std::cout << std::endl;
+ std::cout << "end = " << current_n << std::endl;
+ }
+
+
+} // mln
+
+
+
+
+int main(int, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ int_u8 n;
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, argv[1]);
+
+ typedef p_array<point2d> S;
+ S s = level::sort_psites_decreasing(f);
+
+ // Children go towards lower levels so leafs are regional minima.
+ // We get a min-tree so that we can perform morphological closings.
+
+ morpho::tree::data<I,S> t(f, s, c4());
+ accu::count< util::pix<I> > attr;
+
+ image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
+ run_run(f, a, c4());
+
+}
Index: geraud/tufa_2008/filter.cc
--- geraud/tufa_2008/filter.cc (revision 0)
+++ geraud/tufa_2008/filter.cc (revision 0)
@@ -0,0 +1,169 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/filter.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/literal/black.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/level/fill.hh>
+
+#include <mln/morpho/tree/data.hh>
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/morpho/closing_volume.hh>
+
+
+
+namespace mln
+{
+
+ template <typename P>
+ inline
+ mln_value(P) find_root__(P& par, const mln_value(P)& x)
+ {
+ if (par(x) == x)
+ return x;
+ else
+ return par(x) = find_root__(par, par(x));
+ }
+
+
+ template <typename I, typename A, typename N>
+ mln_concrete(I) filtering(const I& f, const A& a, const N& nbh,
mln_value(A) lambda)
+ {
+ typedef p_array<mln_psite(I)> S;
+ S s = level::sort_psites_increasing(a);
+
+ // s maps increasing attributes.
+
+ mln_concrete(I) out;
+ initialize(out, f);
+
+ mln_ch_value(I, mln_site(I)) par;
+ mln_ch_value(I, bool) deja_vu;
+ {
+ initialize(par, f);
+ mln_piter(A) p(par.domain());
+ for_all(p)
+ par(p) = p;
+ initialize(deja_vu, f);
+ level::fill(deja_vu, false);
+ }
+
+ // First pass.
+ {
+ mln_site(I) r;
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (a.domain().has(n) && deja_vu(n))
+ {
+ r = find_root__(par, n);
+ if (r != p)
+ if (f(r) == f(p) || a(r) < lambda)
+ par(r) = p; // Union.
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ // Second pass.
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ if (par(p) == p)
+ out(p) = f(p);
+ else
+ out(p) = out(par(p));
+ }
+ return out;
+ }
+
+
+} // mln
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm
lambda output.pgm" << std::endl;
+ std::abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc != 4)
+ usage(argv);
+
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, argv[1]);
+
+ unsigned lambda = std::atoi(argv[2]);
+
+ typedef p_array<point2d> S;
+ S s = level::sort_psites_decreasing(f);
+
+ // Children go towards lower levels so leafs are regional minima.
+ // We get a min-tree so that we can perform morphological closings.
+
+ morpho::tree::data<I,S> t(f, s, c4());
+ accu::volume<I> attr;
+
+ image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
+
+ I g = filtering(f, a, c4(), lambda);
+
+ {
+ I ref = morpho::closing_volume(f, c4(), lambda);
+ if (g != ref)
+ {
+ io::pgm::save(ref, "ref.pgm");
+ std::cerr << "oops!" << std::endl;
+ }
+ }
+
+ io::pgm::save(g, argv[3]);
+}
Index: geraud/tufa_2008/wst_f_equal_wst_a.cc
--- geraud/tufa_2008/wst_f_equal_wst_a.cc (revision 0)
+++ geraud/tufa_2008/wst_f_equal_wst_a.cc (revision 0)
@@ -0,0 +1,140 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/steps.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/pw/all.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/io/pbm/save.hh>
+#include <mln/literal/black.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/level/transform.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/tree/data.hh>
+
+#include <mln/accu/volume.hh>
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/labeling/regional_minima.hh>
+
+#include <mln/core/var.hh>
+
+
+namespace mln
+{
+
+ struct colorize : Function_v2v< colorize >
+ {
+ typedef value::rgb8 result;
+ colorize(unsigned max)
+ : lut(max + 1)
+ {
+ lut[0] = literal::black;
+ for (unsigned i = 1; i <= max; ++i)
+ lut[i] = result(100 + std::rand() % 150,
+ 100 + std::rand() % 150,
+ 100 + std::rand() % 150);
+ }
+ result operator()(unsigned i) const
+ {
+ return lut[i];
+ }
+ std::vector<result> lut;
+ };
+
+} // mln
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm"
<< std::endl;
+ std::abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc != 2)
+ usage(argv);
+
+ unsigned nref, n;
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, argv[1]);
+
+ labeling::regional_minima(f, c4(), nref);
+ std::cout << nref << std::endl;
+
+
+ image2d<unsigned> wst_f = morpho::meyer_wst(f, c4(), n);
+ mln_assertion(n == nref);
+
+ io::ppm::save(level::transform(wst_f, colorize(n)),
+ "wst_f.ppm");
+ mln_VAR(WST_f, (pw::value(wst_f) == pw::cst(0u)) | f.domain());
+ io::pbm::save(WST_f, "wst_f.pbm");
+
+
+ typedef p_array<point2d> S;
+ S s = level::sort_psites_decreasing(f);
+
+ // Children go towards lower levels so leafs are regional minima.
+ // We get a min-tree so that we can perform morphological closings.
+
+ morpho::tree::data<I,S> t(f, s, c4());
+ accu::volume<I> vol;
+ image2d<unsigned> a = morpho::tree::compute_attribute_image(vol, t);
+
+ labeling::regional_minima(a, c4(), n);
+ mln_assertion(n == nref);
+
+
+ image2d<unsigned> wst_a = morpho::meyer_wst(a, c4(), n);
+ mln_assertion(n == nref);
+
+ io::ppm::save(level::transform(wst_a, colorize(n)),
+ "wst_a.ppm");
+ mln_VAR(WST_a, (pw::value(wst_a) == pw::cst(0u)) | f.domain());
+ io::pbm::save(WST_a, "wst_a.pbm");
+
+
+ io::pbm::save((pw::value(WST_a) != pw::value(WST_f)) | f.domain(),
+ "diff.pbm");
+}
Index: geraud/tufa_2008/closed_gradient.cc
--- geraud/tufa_2008/closed_gradient.cc (revision 0)
+++ geraud/tufa_2008/closed_gradient.cc (revision 0)
@@ -0,0 +1,64 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/closed_gradient.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/morpho/elementary/gradient.hh>
+#include <mln/morpho/closing_volume.hh>
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm
lambda output.pgm" << std::endl;
+ std::abort();
+}
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc != 4)
+ usage(argv);
+
+ image2d<int_u8> f;
+ io::pgm::load(f, argv[1]);
+ unsigned lambda = std::atoi(argv[2]);
+ io::pgm::save(morpho::closing_volume(morpho::elementary::gradient(f, c4()),
+ c4(),
+ lambda),
+ argv[3]);
+}
Index: geraud/tufa_2008/fz_count.cc
--- geraud/tufa_2008/fz_count.cc (revision 0)
+++ geraud/tufa_2008/fz_count.cc (revision 0)
@@ -0,0 +1,159 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/fz_count.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/labeling/regional_minima.hh>
+#include <mln/labeling/flat_zones.hh>
+#include <mln/level/fill.hh>
+
+
+namespace mln
+{
+
+ template <typename I>
+ void println_par(const I& par)
+ {
+ int nr = par.nrows(), nc = par.ncols();
+ for (int r = 0; r < nr; ++r)
+ {
+ for (int c = 0; c < nc; ++c)
+ if (par.at(r,c) == point2d(r,c))
+ std::cout << "( ) ";
+ else
+ std::cout << par.at(r,c) << ' ';
+ std::cout << std::endl;
+ }
+ }
+
+ template <typename P>
+ inline
+ mln_value(P) find_root__(P& par, const mln_value(P)& x)
+ {
+ if (par(x) == x)
+ return x;
+ else
+ return par(x) = find_root__(par, par(x));
+ }
+
+
+ template <typename I, typename N>
+ unsigned fz_count(const I& f, const N& nbh)
+ {
+ typedef p_array<mln_psite(I)> S;
+ S s = level::sort_psites_increasing(f);
+ // s maps increasing attributes.
+
+ mln_ch_value(I, mln_site(I)) par;
+ mln_ch_value(I, bool) deja_vu;
+
+ unsigned counter = f.domain().nsites();
+
+ // Initialization.
+ {
+ mln_piter(I) p(f.domain());
+
+ // parent
+ initialize(par, f);
+ for_all(p)
+ par(p) = p;
+
+ // deja_vu
+ initialize(deja_vu, f);
+ level::fill(deja_vu, false);
+ }
+
+ // First pass.
+ {
+ mln_site(I) r;
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (f.domain().has(n) && deja_vu(n))
+ {
+ r = find_root__(par, n);
+ if (r != p) // not already merged
+ {
+ if (f(r) == f(p))
+ {
+
+ // Moving the line below out of this test
+ // (either before the test or after the block)
+ // makes the algorithm fail.
+ // The erroneous result is less than the ref
+ // result => we want this current block too many
+ // times. Since we merge (thru "par(r) = p")
+ // whatever "f(r) == f(p)" is true or not, we
+ // have more often "f(r) == f(p)" than expected.
+ par(r) = p;
+
+ --counter;
+ }
+ }
+ }
+
+ deja_vu(p) = true;
+ }
+ }
+
+ return counter;
+ }
+
+
+} // mln
+
+
+
+
+int main(int, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, argv[1]);
+
+ unsigned ref, n = fz_count(f, c4());
+ labeling::flat_zones(f, c4(), ref);
+
+ if (n == ref)
+ std::cout << "success: n flat zones = " << n <<
std::endl;
+ else
+ std::cout << "FAILURE: found = " << n << " v. ref =
" << ref << std::endl;
+}
Index: geraud/tufa_2008/regmin_count.cc
--- geraud/tufa_2008/regmin_count.cc (revision 0)
+++ geraud/tufa_2008/regmin_count.cc (revision 0)
@@ -0,0 +1,173 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file sandbox/geraud/tufa/regmin_count.cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/labeling/regional_minima.hh>
+#include <mln/labeling/flat_zones.hh>
+#include <mln/level/fill.hh>
+
+
+namespace mln
+{
+
+ template <typename I>
+ void println_par(const I& par)
+ {
+ int nr = par.nrows(), nc = par.ncols();
+ for (int r = 0; r < nr; ++r)
+ {
+ for (int c = 0; c < nc; ++c)
+ if (par.at(r,c) == point2d(r,c))
+ std::cout << "( ) ";
+ else
+ std::cout << par.at(r,c) << ' ';
+ std::cout << std::endl;
+ }
+ }
+
+ template <typename P>
+ inline
+ mln_value(P) find_root__(P& par, const mln_value(P)& x)
+ {
+ if (par(x) == x)
+ return x;
+ else
+ return par(x) = find_root__(par, par(x));
+ }
+
+
+ template <typename I, typename N>
+ unsigned regmin_count(const I& f, const N& nbh)
+ {
+ typedef p_array<mln_psite(I)> S;
+ S s = level::sort_psites_increasing(f);
+ // s maps increasing attributes.
+
+ mln_ch_value(I, mln_site(I)) par;
+ mln_ch_value(I, bool) deja_vu, flag;
+
+ unsigned counter = f.domain().nsites();
+
+
+ // Initialization.
+ {
+ mln_piter(I) p(f.domain());
+
+ // parent
+ initialize(par, f);
+ for_all(p)
+ par(p) = p;
+
+ // flag
+ initialize(flag, f);
+ level::fill(flag, true);
+
+ // deja_vu
+ initialize(deja_vu, f);
+ level::fill(deja_vu, false);
+ }
+
+ // First pass.
+ {
+ mln_site(I) r;
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ unsigned loc = 0;
+ for_all(n)
+ if (f.domain().has(n) && deja_vu(n))
+ {
+ r = find_root__(par, n);
+ if (r != p)
+ {
+ if (f(r) == f(p))
+ {
+ par(r) = p; // Union.
+ if (flag(p) == false && flag(r) == false)
+ {
+ // Two non-reg-min components merge (same flat
+ // zone) so we had an extra invalidation.
+ ++counter;
+ }
+ flag(p) = flag(p) && flag(r);
+ --counter; // So we get the number of flat zones
+ // minus the non-reg-min flat zones.
+ }
+ else
+ {
+ mln_invariant(f(r) < f(p));
+ if (flag(p) == true)
+ {
+ ++loc;
+ --counter; // Invalidation.
+ }
+ flag(p) = false;
+ }
+ }
+ }
+ mln_invariant(loc == 0 || loc == 1);
+ deja_vu(p) = true;
+ }
+ }
+
+ return counter;
+ }
+
+
+} // mln
+
+
+
+
+int main(int, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ typedef image2d<int_u8> I;
+ I f;
+ io::pgm::load(f, argv[1]);
+
+ unsigned ref, n = regmin_count(f, c4());
+ labeling::regional_minima(f, c4(), ref);
+
+ if (n == ref)
+ std::cout << "success: n regional minima = " << n <<
std::endl;
+ else
+ std::cout << "FAILURE: found = " << n << " v. ref =
" << ref << std::endl;
+}