https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Augment Laurent's ISMM code.
* laurent/playing_with_attributes.cc: Augment.
* laurent/ismm2009.cc: Memorize as...
* laurent/ismm2009.v2.cc: ...this new file.
* laurent/ismm2009.cc: Augment.
ismm2009.cc | 67 ++++++++-----
ismm2009.v2.cc | 67 ++++++++-----
playing_with_attributes.cc | 224 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 299 insertions(+), 59 deletions(-)
Index: laurent/ismm2009.cc
--- laurent/ismm2009.cc (revision 3172)
+++ laurent/ismm2009.cc (working copy)
@@ -1,10 +1,13 @@
#include "ismm2009.hh"
#include <mln/value/int_u8.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
#include <mln/value/label_8.hh>
#include <mln/value/label_16.hh>
-#include <mln/io/pgm/load.hh>
#include <mln/util/ord_pair.hh>
#include <mln/debug/println.hh>
#include <mln/core/routine/duplicate.hh>
@@ -18,14 +21,9 @@
/*
-
TO-DO list:
- -----------
-
- - having a heap for every lr (support merge)
- handling adjacency on the fly (instead of having an image)
-
*/
@@ -266,7 +264,7 @@
typename N_e2e,
typename L >
mln_ch_value(G, L)
- f_to_wst_unique_g(F& f, // On pixels.
+ compute_wst_g_from_f(F& f, // On pixels.
G& g, // On edges.
const N_e2p& e2p,
const N_e2e& e2e,
@@ -277,7 +275,7 @@
e2p.win()),
g);
- // FIXME: Here, we want a unique value per edge!
+# ifdef MAKE_UNIQUE
if (echo)
debug::println("g (before):", g);
@@ -311,6 +309,9 @@
}
}
+# endif // MAKE_UNIQUE
+
+
mln_VAR( wst_g,
morpho::meyer_wst(g, e2e, n_basins) );
@@ -333,8 +334,9 @@
void usage(char* argv[])
{
- std::cerr << "usage: " << argv[0] << " input.pgm"
<< std::endl;
- std::cerr << "Laurent ISMM 2009 scheme." << std::endl;
+ std::cerr << "usage: " << argv[0] << " input.pgm echo
output.pgm" << std::endl;
+ std::cerr << "Laurent ISMM 2009 scheme with saliency map as output."
<< std::endl;
+ std::cerr << " echo = 0 or 1." << std::endl;
abort();
}
@@ -347,14 +349,20 @@
using value::int_u8;
using value::label_16;
- bool echo = true;
-
- if (argc != 2)
+ if (argc != 4)
usage(argv);
image2d<int_u8> raw_f;
io::pgm::load(raw_f, argv[1]);
+ bool echo;
+ {
+ int echo_ = std::atoi(argv[2]);
+ if (echo_ != 0 && echo_ != 1)
+ usage(argv);
+ echo = bool(echo_);
+ }
+
typedef image2d<int_u8> Complex;
typedef mln_pset_(Complex) full_D;
@@ -372,15 +380,9 @@
L n_basins;
- mln_VAR( wst_g,
- f_to_wst_g(f, g, e2p(), e2e(), n_basins) );
-
- /*
- UNIQUE:
mln_VAR( wst_g,
- f_to_wst_unique_g(f, g, e2p(), e2e(), n_basins, echo) );
- */
+ compute_wst_g_from_f(f, g, e2p(), e2e(), n_basins, echo) );
if (echo)
@@ -501,11 +503,12 @@
std::vector<pair_t> v = sort_attributes(a, n_basins); // Sort regions.
+ // Optional code (for testing purpose): change attributes
+ // so that they are all different.
- // Maybe activate to test purpose:
- /*
+# ifdef MAKE_UNIQUE
make_unique_attribute(a, v, n_basins, echo);
- */
+# endif
// Display attributes.
@@ -796,13 +799,13 @@
// +---------------------------------------------------------------+
- {
-
// Dealing with the watershed line.
mln_VAR(aa_line, aa | is_line);
{
+
+ {
// First, processing the 1D-faces (edges) of the watershed line.
std::vector< std::vector<E> > lca;
@@ -886,16 +889,26 @@
}
if (echo)
- debug::println("aa | basins", aa_basins);
+ debug::println("aa | basins:", aa_basins);
}
-
if (echo)
debug::println("aa:", aa);
+
+ // Output is salency map.
+ {
+
+ image2d<int_u8> output(f_.domain());
+ data::fill(output, 0);
+ data::paste(aa_line, output);
+ io::pgm::save(output, argv[3]);
+ }
+
+
} // end of main
Index: laurent/playing_with_attributes.cc
--- laurent/playing_with_attributes.cc (revision 3172)
+++ laurent/playing_with_attributes.cc (working copy)
@@ -13,6 +13,10 @@
#include <mln/morpho/tree/compute_attribute_image.hh>
#include <mln/labeling/regional_minima.hh>
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/geom/nsites.hh>
+
#include <mln/accu/count.hh>
@@ -26,6 +30,200 @@
+namespace mln
+{
+
+
+ template <typename T>
+ struct node_pred : Function_p2b< node_pred<T> >
+ {
+ typedef bool result;
+
+ template <typename P>
+ bool operator()(const P& p) const
+ {
+ return t->is_a_node(p);
+ }
+
+ const T* t;
+ };
+
+
+
+ template <typename T, typename I>
+ void depict_tree_attributes(const T& t, // Tree.
+ const I& a) // Attribute image.
+ {
+ typedef mln_site(I) P;
+
+ mln_ch_value(I, bool) deja_vu;
+ initialize(deja_vu, a);
+ data::fill(deja_vu, false);
+
+ typedef typename T::nodes_t nodes_t;
+ mln_fwd_piter(nodes_t) p(t.nodes());
+ for_all(p)
+ {
+ if (deja_vu(p))
+ continue;
+
+ P e = p;
+ do
+ {
+ std::cout << a(e) << ':' << e << " ->
";
+ deja_vu(e) = true;
+ e = t.parent(e);
+ }
+ while (! deja_vu(e));
+ std::cout << a(e) << ':' << e << std::endl;
+ }
+ std::cout << std::endl;
+ }
+
+
+ template <typename T, typename I>
+ mln_concrete(I)
+ change_tree_attributes(const T& t, // Tree.
+ const I& a, // Attribute image.
+ bool echo = false)
+ {
+ typedef mln_site(I) P;
+ typedef mln_value(I) A; // Type of attributes.
+
+ // Test that attributes increase with parenthood.
+ mln_fwd_piter(T) p(t.domain());
+ for_all(p)
+ if (t.is_a_non_root_node(p))
+ {
+ mln_assertion(t.is_a_node(t.parent(p)));
+ mln_invariant(a(t.parent(p)) >= a(p));
+ }
+
+
+ if (echo)
+ depict_tree_attributes(t, a);
+
+
+ node_pred<T> node_only;
+ node_only.t = &t;
+
+ typedef p_array<P> S;
+ S s = level::sort_psites_increasing(a | node_only);
+ mln_invariant(geom::nsites(a | t.nodes()) == s.nsites());
+
+
+ mln_ch_value(I, bool) mark;
+ initialize(mark, a);
+ data::fill(mark, false);
+
+
+ // Modify attributes.
+
+ mln_concrete(I) aa;
+ initialize(aa, a);
+ data::fill(aa, 0);
+
+ {
+
+ P e, par_e;
+ A v;
+ bool found;
+
+ mln_fwd_piter(S) p(s);
+
+ // Initialization.
+ for_all(p)
+ {
+ if (mark(p) == true)
+ continue;
+
+ // First, fetch the attribute value v from p;
+ e = p;
+ found = false;
+ while (mark(e) == false && e != t.parent(e))
+ {
+ par_e = t.parent(e);
+ if (mark(par_e) == true)
+ {
+ v = a(e);
+ found = true;
+ break;
+ }
+ e = par_e;
+ };
+
+ if (! found && e == t.parent(e))
+ {
+ // e is a root node; we get its value:
+ v = a(e);
+
+ if (echo)
+ std::cout << "from p = " << p
+ << " to root e = " << e
+ << " v = " << v
+ << std::endl;
+
+ // we set aa from p to the root node
+ e = p;
+ do
+ {
+ aa(e) = v;
+ mln_invariant(mark(e) == false);
+ mark(e) = true;
+ e = t.parent(e);
+ }
+ while (e != t.parent(e));
+ // handle the root node 'e':
+ aa(e) = v;
+ mln_invariant(mark(e) == false);
+ mark(e) = true;
+ mln_invariant(a(e) == v);
+ }
+ else if (found)
+ {
+ e = p;
+
+ P last_e = P(0,0);
+
+ while (mark(e) == false)
+ {
+ aa(e) = v;
+ mark(e) = true;
+ last_e = e;
+ e = t.parent(e);
+ };
+
+ if (echo)
+ {
+ if (last_e == p)
+ std::cout << "p = " << p
+ << " par(e) = " << par_e
+ << " so keep v = " << v
+ << std::endl;
+ else
+ std::cout << "from p = " << p
+ << " to e = " << last_e
+ << " with par(e) = " << par_e
+ << " v = " << v
+ << std::endl;
+ }
+ }
+ }
+
+ if (echo)
+ depict_tree_attributes(t, aa);
+
+ } // end of Modify attributes.
+
+ return aa;
+ }
+
+
+
+} // mln
+
+
+
template <typename I, typename N, typename L>
void do_it(const I& g, const N& nbh, L& n_labels)
{
@@ -34,7 +232,7 @@
// regional minima
mln_ch_value(I,L) regmin = labeling::regional_minima(g, nbh, n_labels);
- debug::println("regmin(g):", regmin);
+ // debug::println("regmin(g):", regmin);
// watershed
@@ -42,7 +240,7 @@
L n_basins;
mln_ch_value(I,L) w = morpho::meyer_wst(g, nbh, n_basins);
mln_invariant(n_basins == n_labels);
- debug::println("w(g):", w);
+ // debug::println("w(g):", w);
{
@@ -55,12 +253,28 @@
accu::count< util::pix<I> > a_; // Kind of attribute.
mln_ch_value(I,unsigned) a = morpho::tree::compute_attribute_image(a_, t);
- debug::println("a:", a);
+ debug::println("a | nodes:", a | t.nodes());
+
+ mln_ch_value(I,unsigned) aa = change_tree_attributes(t, a);
+ debug::println("aa | nodes:", aa | t.nodes());
+
+ // Back-propagation from nodes to components.
+ {
+ mln_fwd_piter(tree_t) p(t.domain());
+ for_all(p)
+ if (! t.is_a_node(p))
+ {
+ mln_assertion(t.is_a_node(t.parent(p)));
+ aa(p) = aa(t.parent(p));
+ }
+ }
debug::println("a | w line:", a | (pw::value(w) == pw::cst(0)));
- debug::println("a | w basins:", a | (pw::value(w) != pw::cst(0)));
+ debug::println("aa | w line:", aa | (pw::value(w) == pw::cst(0)));
+
+// debug::println("a | w basins:", a | (pw::value(w) != pw::cst(0)));
+// debug::println("a | regmin:", a | (pw::value(regmin) != pw::cst(0)));
- debug::println("a | regmin:", a | (pw::value(regmin) != pw::cst(0)));
}
} // end of do_it
Index: laurent/ismm2009.v2.cc
--- laurent/ismm2009.v2.cc (revision 3172)
+++ laurent/ismm2009.v2.cc (working copy)
@@ -1,10 +1,13 @@
#include "ismm2009.hh"
#include <mln/value/int_u8.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
#include <mln/value/label_8.hh>
#include <mln/value/label_16.hh>
-#include <mln/io/pgm/load.hh>
#include <mln/util/ord_pair.hh>
#include <mln/debug/println.hh>
#include <mln/core/routine/duplicate.hh>
@@ -18,14 +21,9 @@
/*
-
TO-DO list:
- -----------
-
- - having a heap for every lr (support merge)
- handling adjacency on the fly (instead of having an image)
-
*/
@@ -266,7 +264,7 @@
typename N_e2e,
typename L >
mln_ch_value(G, L)
- f_to_wst_unique_g(F& f, // On pixels.
+ compute_wst_g_from_f(F& f, // On pixels.
G& g, // On edges.
const N_e2p& e2p,
const N_e2e& e2e,
@@ -277,7 +275,7 @@
e2p.win()),
g);
- // FIXME: Here, we want a unique value per edge!
+# ifdef MAKE_UNIQUE
if (echo)
debug::println("g (before):", g);
@@ -311,6 +309,9 @@
}
}
+# endif // MAKE_UNIQUE
+
+
mln_VAR( wst_g,
morpho::meyer_wst(g, e2e, n_basins) );
@@ -333,8 +334,9 @@
void usage(char* argv[])
{
- std::cerr << "usage: " << argv[0] << " input.pgm"
<< std::endl;
- std::cerr << "Laurent ISMM 2009 scheme." << std::endl;
+ std::cerr << "usage: " << argv[0] << " input.pgm echo
output.pgm" << std::endl;
+ std::cerr << "Laurent ISMM 2009 scheme with saliency map as output."
<< std::endl;
+ std::cerr << " echo = 0 or 1." << std::endl;
abort();
}
@@ -347,14 +349,20 @@
using value::int_u8;
using value::label_16;
- bool echo = true;
-
- if (argc != 2)
+ if (argc != 4)
usage(argv);
image2d<int_u8> raw_f;
io::pgm::load(raw_f, argv[1]);
+ bool echo;
+ {
+ int echo_ = std::atoi(argv[2]);
+ if (echo_ != 0 && echo_ != 1)
+ usage(argv);
+ echo = bool(echo_);
+ }
+
typedef image2d<int_u8> Complex;
typedef mln_pset_(Complex) full_D;
@@ -372,15 +380,9 @@
L n_basins;
- mln_VAR( wst_g,
- f_to_wst_g(f, g, e2p(), e2e(), n_basins) );
-
- /*
- UNIQUE:
mln_VAR( wst_g,
- f_to_wst_unique_g(f, g, e2p(), e2e(), n_basins, echo) );
- */
+ compute_wst_g_from_f(f, g, e2p(), e2e(), n_basins, echo) );
if (echo)
@@ -501,11 +503,12 @@
std::vector<pair_t> v = sort_attributes(a, n_basins); // Sort regions.
+ // Optional code (for testing purpose): change attributes
+ // so that they are all different.
- // Maybe activate to test purpose:
- /*
+# ifdef MAKE_UNIQUE
make_unique_attribute(a, v, n_basins, echo);
- */
+# endif
// Display attributes.
@@ -796,13 +799,13 @@
// +---------------------------------------------------------------+
- {
-
// Dealing with the watershed line.
mln_VAR(aa_line, aa | is_line);
{
+
+ {
// First, processing the 1D-faces (edges) of the watershed line.
std::vector< std::vector<E> > lca;
@@ -886,16 +889,26 @@
}
if (echo)
- debug::println("aa | basins", aa_basins);
+ debug::println("aa | basins:", aa_basins);
}
-
if (echo)
debug::println("aa:", aa);
+
+ // Output is salency map.
+ {
+
+ image2d<int_u8> output(f_.domain());
+ data::fill(output, 0);
+ data::paste(aa_line, output);
+ io::pgm::save(output, argv[3]);
+ }
+
+
} // end of main