---
.../morpho/artificial_line_graph_image_wst.cc | 22 ++++++++++++++++++
milena/tests/morpho/complex_image_morpho.cc | 4 +++
milena/tests/morpho/complex_image_wst.cc | 5 ++++
milena/tests/morpho/graph_image_morpho.cc | 4 +++
milena/tests/morpho/graph_image_wst.cc | 3 ++
milena/tests/morpho/lena_line_graph_image_wst1.cc | 21 +++++++++++++++++
milena/tests/morpho/lena_line_graph_image_wst2.cc | 24 ++++++++++++++++++++
milena/tests/morpho/line_graph_image_morpho.cc | 4 +++
milena/tests/morpho/line_graph_image_wst.cc | 4 +++
9 files changed, 91 insertions(+), 0 deletions(-)
diff --git a/milena/tests/morpho/artificial_line_graph_image_wst.cc b/milena/tests/morpho/artificial_line_graph_image_wst.cc
index 9d09ab5..3b019ba 100644
--- a/milena/tests/morpho/artificial_line_graph_image_wst.cc
+++ b/milena/tests/morpho/artificial_line_graph_image_wst.cc
@@ -23,6 +23,28 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/* FIXME: We should factor as much things as possible between
+ tests/morpho/lena_line_graph_image_wst1.cc,
+ tests/morpho/lena_line_graph_image_wst2.cc and this file, starting
+ with conversion routines. */
+
+/** \file
+ \brief Tests on the Watershed Transform (WST) on an artificial
+ mln::line_graph_image.
+
+ The scenario is as follows:
+ \li create an artificial (checkboard) 2-D image ;
+ \li convert this 2-D image into a line graph-based one, where values
+ on edges are computed as the absolute value of the difference
+ between the values on the vertices adjacent to the edge, so as to
+ create a (norm of the) gradient ``between the pixels'' of the
+ input image;
+ \li perform a WST on this line graph image;
+ \li create a 2-D, color output image with height and width double
+ the size the original one, and copy the data of the input image
+ in it, interpolating inter-pixel points;
+ \li print the watershed on lines into that same image, and save it. */
+
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/point2d.hh>
#include <mln/core/alias/window2d.hh>
diff --git a/milena/tests/morpho/complex_image_morpho.cc b/milena/tests/morpho/complex_image_morpho.cc
index 31e202d..601b7a9 100644
--- a/milena/tests/morpho/complex_image_morpho.cc
+++ b/milena/tests/morpho/complex_image_morpho.cc
@@ -23,6 +23,10 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// Test of mln::complex_image with morphological filters.
+
#include <iostream>
#include <mln/value/int_u8.hh>
diff --git a/milena/tests/morpho/complex_image_wst.cc b/milena/tests/morpho/complex_image_wst.cc
index 239630b..ef7adea 100644
--- a/milena/tests/morpho/complex_image_wst.cc
+++ b/milena/tests/morpho/complex_image_wst.cc
@@ -23,6 +23,11 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// \brief Testing the Watershed Transform by flooding an
+/// mln::complex_image.
+
#include <iostream>
#include <fstream>
#include <sstream>
diff --git a/milena/tests/morpho/graph_image_morpho.cc b/milena/tests/morpho/graph_image_morpho.cc
index 0a78462..bfa16c6 100644
--- a/milena/tests/morpho/graph_image_morpho.cc
+++ b/milena/tests/morpho/graph_image_morpho.cc
@@ -23,6 +23,10 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// \brief Tests on a graph-based image with morphological filters.
+
#include <mln/accu/shape/bbox.hh>
#include <mln/core/alias/box2d.hh>
#include <mln/core/alias/point2d.hh>
diff --git a/milena/tests/morpho/graph_image_wst.cc b/milena/tests/morpho/graph_image_wst.cc
index bbc9e74..735b648 100644
--- a/milena/tests/morpho/graph_image_wst.cc
+++ b/milena/tests/morpho/graph_image_wst.cc
@@ -23,6 +23,9 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+/// \brief Tests on the Watershed Transform on a graph-based image.
+
#include <vector>
#include <mln/core/alias/point2d.hh>
diff --git a/milena/tests/morpho/lena_line_graph_image_wst1.cc b/milena/tests/morpho/lena_line_graph_image_wst1.cc
index 98d20d8..aef5cc3 100644
--- a/milena/tests/morpho/lena_line_graph_image_wst1.cc
+++ b/milena/tests/morpho/lena_line_graph_image_wst1.cc
@@ -23,6 +23,27 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/* FIXME: We should factor as much things as possible between
+ tests/morpho/lena_line_graph_image_wst1.cc and
+ tests/morpho/lena_line_graph_image_wst2.cc, starting from conversion
+ routines. */
+
+/** \file
+ \brief Tests on the Watershed Transform (WST) on a mln::line_graph_image.
+
+ The scenario is as follows:
+ \li load a 2-D, gray-level image from a PGM file;
+ \li compute a morphological gradient of this image;
+ \li simplify the image to reduce the number of local minima;
+ \li convert this 2-D image into a line graph-based one, where values
+ on edges are computed as the maxmimum of the values on the vertices
+ adjacent to the edge;
+ \li perform a WST on the line graph image;
+ \li create an 2-D, color output image with height and width double
+ the size the original one, and copy the data of the input image
+ in it, interpolating inter-pixel points;
+ \li print the watershed on lines into that same image, and save it. */
+
#include <map>
#include <vector>
diff --git a/milena/tests/morpho/lena_line_graph_image_wst2.cc b/milena/tests/morpho/lena_line_graph_image_wst2.cc
index 697bbfe..ab650b6 100644
--- a/milena/tests/morpho/lena_line_graph_image_wst2.cc
+++ b/milena/tests/morpho/lena_line_graph_image_wst2.cc
@@ -23,6 +23,30 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/* FIXME: We should factor as much things as possible between
+ tests/morpho/lena_line_graph_image_wst1.cc and
+ tests/morpho/lena_line_graph_image_wst2.cc, starting from conversion
+ routines. */
+
+/** \file
+ \brief More tests on the Watershed Transform (WST) on a
+ mln::line_graph_image.
+
+ The scenario is as follows:
+ \li load a 2-D, gray-level image from a PGM file;
+ \li convert this 2-D image into a line graph-based one, where values
+ on edges are computed as the absolute value of the difference
+ between the values on the vertices adjacent to the edge, so as to
+ create a (norm of the) gradient ``between the pixels'' of the
+ input image;
+ \li reduce the number of minima using an area opening (counting the
+ vertices to compute the area, not the edges);
+ \li perform a WST on this simplified line graph image;
+ \li create a 2-D, color output image with height and width double
+ the size the original one, and copy the data of the input image
+ in it, interpolating inter-pixel points;
+ \li print the watershed on lines into that same image, and save it. */
+
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/point2d.hh>
#include <mln/core/alias/window2d.hh>
diff --git a/milena/tests/morpho/line_graph_image_morpho.cc b/milena/tests/morpho/line_graph_image_morpho.cc
index 945a47c..21ce087 100644
--- a/milena/tests/morpho/line_graph_image_morpho.cc
+++ b/milena/tests/morpho/line_graph_image_morpho.cc
@@ -23,6 +23,10 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// Tests on line a graph-based image with morphological filters.
+
#include <mln/core/alias/point2d.hh>
/// Required for line graph images.
diff --git a/milena/tests/morpho/line_graph_image_wst.cc b/milena/tests/morpho/line_graph_image_wst.cc
index 2d10779..2ce2cb6 100644
--- a/milena/tests/morpho/line_graph_image_wst.cc
+++ b/milena/tests/morpho/line_graph_image_wst.cc
@@ -23,6 +23,10 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file tests/morpho/line_graph_image_wst.cc
+///
+/// Tests on the Watershed Transform on a line graph-based image.
+
#include <mln/core/alias/point2d.hh>
/// Required for line graph images.
--
1.6.4.2
---
milena/sandbox/ChangeLog | 4 +
.../sandbox/levillain/constrained-connectivity.cc | 86 +++++++++----------
2 files changed, 45 insertions(+), 45 deletions(-)
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index 4dcc85b..24378ce 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,5 +1,9 @@
2009-09-04 Roland Levillain <roland(a)lrde.epita.fr>
+ * levillain/constrained-connectivity.cc: Aesthetic changes.
+
+2009-09-04 Roland Levillain <roland(a)lrde.epita.fr>
+
Finish the experiment for Laurent.
* levillain/constrained-connectivity.cc: Complete the processing
diff --git a/milena/sandbox/levillain/constrained-connectivity.cc b/milena/sandbox/levillain/constrained-connectivity.cc
index 81c86ca..af5e49a 100644
--- a/milena/sandbox/levillain/constrained-connectivity.cc
+++ b/milena/sandbox/levillain/constrained-connectivity.cc
@@ -102,15 +102,16 @@ int main(int argc, char* argv[])
// Double its resolution.
image2d<int_u8> f(input.nrows() * 2, input.ncols() * 2);
- mln_piter_(image2d<int_u8>) p(f.domain());
- for_all(p)
+ mln_piter_(image2d<int_u8>) p_ima(f.domain());
+ for_all(p_ima)
{
- /* This conversion from ``piter'' to ``point'' is required, since
- an iterator does not expose the interface of the underlying
- point (among which the methods row(), col(), etc.). */
- point2d p_ = p;
- point2d q(p_.row() / 2, p_.col() / 2);
- f(p) = input(q);
+ /* This conversion from a ``piter'' type to point2d is required,
+ since an iterator does not expose the interface of the
+ underlying point (among which the methods row(), col(),
+ etc.). */
+ point2d p_ima_ = p_ima;
+ point2d p_f(p_ima_.row() / 2, p_ima_.col() / 2);
+ f(p_ima) = input(p_f);
}
debug::println(f);
@@ -130,86 +131,81 @@ int main(int argc, char* argv[])
std::set<int_u8> values;
mln_piter_(w_t) p2(w.domain());
for_all(p2)
- values.insert (w(p2));
+ values.insert(w(p2));
- // Thresholding for each value of W.
+ // Thresholding W for each value of the image.
for (std::set<int_u8>::const_iterator alpha = values.begin();
alpha != values.end(); ++alpha)
{
mln_VAR(alpha_cc, w | (pw::value(w) > pw::cst(*alpha)));
+ std::cout << *alpha << "-cc:" << std::endl;
/* FIXME: There should be variants of debug::println allowing
the user to pass an optional ``support'' larger than the
actual domain of the image. For now, use a low-level routine
as a workaround. */
- std::cout << *alpha << "-cc:" << std::endl;
debug::impl::println(w.unmorph_().domain(), alpha_cc);
}
- // Compute attributes on the components of the topological watershed (W).
- typedef p_array<tree_t::site> sites_t;
- sites_t sites = data::sort_psites_decreasing(w);
+ // Compute the height (max - min) of connected components on the line
+ // graph-based watershed, but with min and max values computed on
+ // vertices.
- /* FIXME: Of course, we'd like to be able to reuse the component tree
- within TREE instead of rebuilding a morpho::tree::data... This
- requires some changes in the topological WST implementation to
- make its component tree structure compatible with
+ /* FIXME: Of course, we'd like to be able to reuse the component
+ tree within TREE instead of rebuilding a morpho::tree::data...
+ This requires some changes in the topological WST implementation,
+ to make its component tree structure compatible with
morpho::tree::data. */
+ typedef p_array<tree_t::site> sites_t;
+ sites_t sites = data::sort_psites_decreasing(w);
morpho::tree::data<w_t, sites_t> t(w, sites, cplx2d::e2e());
- // Height (max-min) on the line graph WST, but with min and max
- // values computed on vertices.
+ // Create initial images for min and max values on sites (not components).
mln_ch_value_(w_t, accu::stat::min<int_u8>) init_min_val;
initialize (init_min_val, w);
mln_ch_value_(w_t, accu::stat::max<int_u8>) init_max_val;
initialize (init_max_val, w);
- mln_fwd_piter_(w_t) e(w.domain());
- mln_niter_(cplx2d::dbl_neighb2d) v(cplx2d::e2p(), e);
+ /* Compute the min and max values on vertices (pixels) adjacent to
+ edge E.
+
+ Unfortunately, the data structure G does not record any
+ information from the image F (i.e., the values on
+ vertices/pixels). We have to convert the coordinates of V to its
+ equivalent in F's domain to get the values on vertices. */
+ mln_piter_(w_t) e(w.domain());
+ mln_niter_(cplx2d::dbl_neighb2d) v_g(cplx2d::e2p(), e);
for_all(e)
- {
- // Compute the min and max values on vertices (pixels) adjacent to edge E.
- for_all(v)
+ for_all(v_g)
{
- /* Unfortunately, the data structure G does not record any
- information from the image F (i.e., the values on
- vertices/pixels). We have to convert the coordinates of V
- to its equivalent in F's domain to get the values on
- vertices.
-
- In addition, note that an explicit `to_site()' conversion
- is required here, since an iterator does not expose the
- interface of the underlying point (among which the methods
- row(), col(), etc.). */
- point2d v_(v.to_site().row() / 2, v.to_site().col() / 2);
- init_min_val(e).take(f(v_));
- init_max_val(e).take(f(v_));
+ // Same remark as above avour piter to point2d conversions.
+ point2d v_g_ = v_g;
+ point2d v_f(v_g_.row() / 2, v_g_.col() / 2);
+ init_min_val(e).take(f(v_f));
+ init_max_val(e).take(f(v_f));
}
- }
+ // Attribute images of min and max values on components.
accu::stat::min<int_u8> min_accu;
mln_ch_value_(w_t, int_u8) min_val =
morpho::tree::compute_attribute_image_from(min_accu, t, init_min_val);
accu::stat::max<int_u8> max_accu;
mln_ch_value_(w_t, int_u8) max_val =
morpho::tree::compute_attribute_image_from(max_accu, t, init_max_val);
-
+ // Attribute image of components' height.
mln_ch_value_(w_t, int_u8) height;
initialize(height, w);
for_all(e)
height(e) = max_val(e) - min_val(e);
debug::println(height);
- // Thresholding for the first integer values with a condition on HEIGHT.
+ // Thresholding W using first integer values with a condition on HEIGHT.
for (unsigned alpha = 0; alpha <= 6; ++alpha)
{
mln_VAR(alpha_alpha_cc,
w | (pw::value(w) > pw::cst(alpha)
|| (pw::value(height) > pw::cst(alpha))));
- /* FIXME: There should be variants of debug::println allowing
- the user to pass an optional ``support'' larger than the
- actual domain of the image. For now, use a low-level routine
- as a workaround. */
std::cout << "(" << alpha << ", " << alpha << ")-cc:" << std::endl;
+ // FIXME: Same remark as above about println.
debug::impl::println(w.unmorph_().domain(), alpha_alpha_cc);
}
}
--
1.6.4.2
* levillain/constrained-connectivity.cc: Complete the processing
chain.
Add a copyright header.
Translate the documentation into English.
s/ima/input/g.
s/ima_x2/f/g.
* levillain/soille.pgm: New.
* levillain/Makefile: New.
---
milena/sandbox/ChangeLog | 13 ++
milena/sandbox/levillain/Makefile | 27 +++
.../sandbox/levillain/constrained-connectivity.cc | 175 ++++++++++++++++----
milena/sandbox/levillain/soille.pgm | 11 ++
4 files changed, 197 insertions(+), 29 deletions(-)
create mode 100644 milena/sandbox/levillain/Makefile
create mode 100644 milena/sandbox/levillain/soille.pgm
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index 673d4d8..4dcc85b 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,3 +1,16 @@
+2009-09-04 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Finish the experiment for Laurent.
+
+ * levillain/constrained-connectivity.cc: Complete the processing
+ chain.
+ Add a copyright header.
+ Translate the documentation into English.
+ s/ima/input/g.
+ s/ima_x2/f/g.
+ * levillain/soille.pgm: New.
+ * levillain/Makefile: New.
+
2009-09-03 Roland Levillain <roland(a)lrde.epita.fr>
Start a new experiment for Laurent.
diff --git a/milena/sandbox/levillain/Makefile b/milena/sandbox/levillain/Makefile
new file mode 100644
index 0000000..d95c7a5
--- /dev/null
+++ b/milena/sandbox/levillain/Makefile
@@ -0,0 +1,27 @@
+# FIXME: A part of this should move out of this sandbox and into milena/apps.
+
+milena_dir = ../..
+img_dir = $(milena_dir)/img
+
+CPPFLAGS = -I. -I$(milena_dir)
+CXXFLAGS = -ggdb -Wall -Werror
+
+PROGRAMS = double min-max constrained-connectivity
+
+all: $(PROGRAMS)
+
+check: check-double check-min-max check-constrained-connectivity
+check-double: double
+ ./$<
+check-min-max: min-max
+ ./$<
+check-constrained-connectivity: constrained-connectivity soille.pgm
+ ./$< soille.pgm
+
+CLEANFILES = double min-max constrained-connectivity
+
+clean:
+ rm -f $(CLEANFILES)
+
+.PHONY: all check clean
+.PHONY: check-double check-min-max check-constrained-connectivity
diff --git a/milena/sandbox/levillain/constrained-connectivity.cc b/milena/sandbox/levillain/constrained-connectivity.cc
index d740956..81c86ca 100644
--- a/milena/sandbox/levillain/constrained-connectivity.cc
+++ b/milena/sandbox/levillain/constrained-connectivity.cc
@@ -1,21 +1,65 @@
-/* The Work:
-
- - Prendre une image 2d
- - En doubler les pixels (un pixel -> un carré de quatre pixels)
- - En calculer un graphe d'arrête (passage en complexe cubique)
- - Valuer les arrêtes avec une magnitude de gradient (|v1 - v2|)
- - Calculer une LPE topo sur ce gradient
- - Seuiller les valeurs de cette LPE doit être équivalent aux
- alpha-CC de Pierre Soille (hypothèse de Laurent)
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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 constrained-connectivity.cc
- - Puis, sur l'arbre des coupes (correspondant à la LPE topo
- calculée ci-avant), calculer pour chaque arrête `e' un attribut
- initialisé tel que `a(e) = (min(v1,v2), max(v1,v2))' (couple) où
- `v1' et `v2' sont adjacents à `e', et propager ce min et ce max
- sur tous les noeuds.
- - Il doit normalement être possible d'obtenir les (alpha,
- omega)-CC de Pierre Soille en filtrant cet arbre. */
-
+ \brief A topological watershed-based implementation of Pierre
+ Soille's constrained connectivity segmentation.
+
+ Reference:
+
+ Pierre Soille. Constrained Connectivity for Hierarchical Image
+ Partitioning and Simplification. In: IEEE Transactions on
+ Pattern Analysis and Machine Intelligence, vol. 30, no. 7, July
+ 2008, pages 1132-1145.
+
+
+ The scenario is as follows.
+
+ Part 1.
+ \li Load a 2D image.
+ \li Double its resolution (a pixel becomes a square of four pixels).
+ \li Compute a line graph from this image and
+ \li Assign values of a gradient to the edges (e.g., |v1 - v2|).
+ \li Compute a topological watershed transform on this gradient.
+ \li Thresholding the values of this watershed gives
+ alpha-connected component (alpha-cc) described by Pierre Soille.
+
+ Part 2.
+ \li For each edge of the watershed (line graph-based) image,
+ compute the min and max value of the adjacent vertices (pixels).
+ \li Using the component tree corresponding to the previously
+ computed topological watershed transform, propagate and
+ compute the min and max value for each component of the
+ watershed.
+ \li Create an image of ``heights'' by subtracting the image of min
+ values from the image of max values.
+ \li Thresholding the watershed image (using a parameter alpha)
+ <em>and</em> the height image (using a parameter omega) gives
+ the (alpha, omega)-connected component (alpha-omega cc)
+ described by Pierre Soille. */
#include <cstdio>
@@ -27,15 +71,19 @@
#include <mln/pw/all.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/debug/println.hh>
-
// From Théo's sandbox.
#include <theo/cplx2d.hh>
// From Alexandre Abraham's sandbox.
#include <alexandre/topo_wst.hh>
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include <mln/accu/stat/min.hh>
+#include <mln/accu/stat/max.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
int main(int argc, char* argv[])
{
@@ -49,12 +97,12 @@ int main(int argc, char* argv[])
using mln::value::int_u8;
// Load an image.
- image2d<int_u8> ima;
- io::pgm::load(ima, argv[1]);
+ image2d<int_u8> input;
+ io::pgm::load(input, argv[1]);
// Double its resolution.
- image2d<int_u8> ima_x2 (10, 10);
- mln_piter_(image2d<int_u8>) p(ima_x2.domain());
+ image2d<int_u8> f(input.nrows() * 2, input.ncols() * 2);
+ mln_piter_(image2d<int_u8>) p(f.domain());
for_all(p)
{
/* This conversion from ``piter'' to ``point'' is required, since
@@ -62,16 +110,17 @@ int main(int argc, char* argv[])
point (among which the methods row(), col(), etc.). */
point2d p_ = p;
point2d q(p_.row() / 2, p_.col() / 2);
- ima_x2(p) = ima(q);
+ f(p) = input(q);
}
- debug::println(ima_x2);
+ debug::println(f);
// Compute the associated line graph gradient.
- mln_VAR(g, cplx2d::f_to_g(ima_x2) );
+ mln_VAR(g, cplx2d::f_to_g(f) );
debug::println("g:", g);
// Compute a topological watershed transform on this gradient.
- morpho::topo_wst<g_t, cplx2d::dbl_neighb2d> tree(g, cplx2d::e2e());
+ typedef morpho::topo_wst<g_t, cplx2d::dbl_neighb2d> tree_t;
+ tree_t tree(g, cplx2d::e2e());
tree.go();
mln_VAR(w, morpho::topo_watershed(tree));
debug::println("w:", w);
@@ -84,7 +133,7 @@ int main(int argc, char* argv[])
values.insert (w(p2));
// Thresholding for each value of W.
- for (std::set<int_u8>::iterator alpha = values.begin();
+ for (std::set<int_u8>::const_iterator alpha = values.begin();
alpha != values.end(); ++alpha)
{
mln_VAR(alpha_cc, w | (pw::value(w) > pw::cst(*alpha)));
@@ -95,4 +144,72 @@ int main(int argc, char* argv[])
std::cout << *alpha << "-cc:" << std::endl;
debug::impl::println(w.unmorph_().domain(), alpha_cc);
}
+
+
+ // Compute attributes on the components of the topological watershed (W).
+ typedef p_array<tree_t::site> sites_t;
+ sites_t sites = data::sort_psites_decreasing(w);
+
+ /* FIXME: Of course, we'd like to be able to reuse the component tree
+ within TREE instead of rebuilding a morpho::tree::data... This
+ requires some changes in the topological WST implementation to
+ make its component tree structure compatible with
+ morpho::tree::data. */
+ morpho::tree::data<w_t, sites_t> t(w, sites, cplx2d::e2e());
+
+ // Height (max-min) on the line graph WST, but with min and max
+ // values computed on vertices.
+ mln_ch_value_(w_t, accu::stat::min<int_u8>) init_min_val;
+ initialize (init_min_val, w);
+ mln_ch_value_(w_t, accu::stat::max<int_u8>) init_max_val;
+ initialize (init_max_val, w);
+
+ mln_fwd_piter_(w_t) e(w.domain());
+ mln_niter_(cplx2d::dbl_neighb2d) v(cplx2d::e2p(), e);
+ for_all(e)
+ {
+ // Compute the min and max values on vertices (pixels) adjacent to edge E.
+ for_all(v)
+ {
+ /* Unfortunately, the data structure G does not record any
+ information from the image F (i.e., the values on
+ vertices/pixels). We have to convert the coordinates of V
+ to its equivalent in F's domain to get the values on
+ vertices.
+
+ In addition, note that an explicit `to_site()' conversion
+ is required here, since an iterator does not expose the
+ interface of the underlying point (among which the methods
+ row(), col(), etc.). */
+ point2d v_(v.to_site().row() / 2, v.to_site().col() / 2);
+ init_min_val(e).take(f(v_));
+ init_max_val(e).take(f(v_));
+ }
+ }
+ accu::stat::min<int_u8> min_accu;
+ mln_ch_value_(w_t, int_u8) min_val =
+ morpho::tree::compute_attribute_image_from(min_accu, t, init_min_val);
+ accu::stat::max<int_u8> max_accu;
+ mln_ch_value_(w_t, int_u8) max_val =
+ morpho::tree::compute_attribute_image_from(max_accu, t, init_max_val);
+
+ mln_ch_value_(w_t, int_u8) height;
+ initialize(height, w);
+ for_all(e)
+ height(e) = max_val(e) - min_val(e);
+ debug::println(height);
+
+ // Thresholding for the first integer values with a condition on HEIGHT.
+ for (unsigned alpha = 0; alpha <= 6; ++alpha)
+ {
+ mln_VAR(alpha_alpha_cc,
+ w | (pw::value(w) > pw::cst(alpha)
+ || (pw::value(height) > pw::cst(alpha))));
+ /* FIXME: There should be variants of debug::println allowing
+ the user to pass an optional ``support'' larger than the
+ actual domain of the image. For now, use a low-level routine
+ as a workaround. */
+ std::cout << "(" << alpha << ", " << alpha << ")-cc:" << std::endl;
+ debug::impl::println(w.unmorph_().domain(), alpha_alpha_cc);
+ }
}
diff --git a/milena/sandbox/levillain/soille.pgm b/milena/sandbox/levillain/soille.pgm
new file mode 100644
index 0000000..7b1593b
--- /dev/null
+++ b/milena/sandbox/levillain/soille.pgm
@@ -0,0 +1,11 @@
+P2
+7 7
+255
+
+1 3 8 7 8 8 2
+2 1 9 8 8 9 1
+1 0 4 1 1 2 5
+1 1 9 3 4 2 6
+3 2 7 9 9 1 1
+1 0 8 4 9 6 7
+0 2 9 3 8 5 9
--
1.6.4.2
* levillain/.gitignore: Add constrained-connectivity.
* levillain/alexandre: New symlink to abraham/mln/morpho.
* levillain/theo: New symlink to theo/esiee/laurent/ismm09.
* levillain/constrained-connectivity.cc: New.
---
milena/sandbox/ChangeLog | 9 ++
milena/sandbox/levillain/.gitignore | 1 +
milena/sandbox/levillain/alexandre | 1 +
.../sandbox/levillain/constrained-connectivity.cc | 98 ++++++++++++++++++++
milena/sandbox/levillain/theo | 1 +
5 files changed, 110 insertions(+), 0 deletions(-)
create mode 120000 milena/sandbox/levillain/alexandre
create mode 100644 milena/sandbox/levillain/constrained-connectivity.cc
create mode 120000 milena/sandbox/levillain/theo
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index 83ef8c3..673d4d8 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,5 +1,14 @@
2009-09-03 Roland Levillain <roland(a)lrde.epita.fr>
+ Start a new experiment for Laurent.
+
+ * levillain/.gitignore: Add constrained-connectivity.
+ * levillain/alexandre: New symlink to abraham/mln/morpho.
+ * levillain/theo: New symlink to theo/esiee/laurent/ismm09.
+ * levillain/constrained-connectivity.cc: New.
+
+2009-09-03 Roland Levillain <roland(a)lrde.epita.fr>
+
* theo/esiee/laurent/ismm09/cplx2d.hh: Include mln/core/var.hh.
2009-09-03 Roland Levillain <roland(a)lrde.epita.fr>
diff --git a/milena/sandbox/levillain/.gitignore b/milena/sandbox/levillain/.gitignore
index 627984b..e55cea5 100644
--- a/milena/sandbox/levillain/.gitignore
+++ b/milena/sandbox/levillain/.gitignore
@@ -1,2 +1,3 @@
+constrained-connectivity
double
min-max
diff --git a/milena/sandbox/levillain/alexandre b/milena/sandbox/levillain/alexandre
new file mode 120000
index 0000000..5edb140
--- /dev/null
+++ b/milena/sandbox/levillain/alexandre
@@ -0,0 +1 @@
+../abraham/mln/morpho/
\ No newline at end of file
diff --git a/milena/sandbox/levillain/constrained-connectivity.cc b/milena/sandbox/levillain/constrained-connectivity.cc
new file mode 100644
index 0000000..d740956
--- /dev/null
+++ b/milena/sandbox/levillain/constrained-connectivity.cc
@@ -0,0 +1,98 @@
+/* The Work:
+
+ - Prendre une image 2d
+ - En doubler les pixels (un pixel -> un carré de quatre pixels)
+ - En calculer un graphe d'arrête (passage en complexe cubique)
+ - Valuer les arrêtes avec une magnitude de gradient (|v1 - v2|)
+ - Calculer une LPE topo sur ce gradient
+ - Seuiller les valeurs de cette LPE doit être équivalent aux
+ alpha-CC de Pierre Soille (hypothèse de Laurent)
+
+ - Puis, sur l'arbre des coupes (correspondant à la LPE topo
+ calculée ci-avant), calculer pour chaque arrête `e' un attribut
+ initialisé tel que `a(e) = (min(v1,v2), max(v1,v2))' (couple) où
+ `v1' et `v2' sont adjacents à `e', et propager ce min et ce max
+ sur tous les noeuds.
+ - Il doit normalement être possible d'obtenir les (alpha,
+ omega)-CC de Pierre Soille en filtrant cet arbre. */
+
+
+#include <cstdio>
+
+#include <set>
+#include <iostream>
+
+#include <mln/value/int_u8.hh>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/pw/all.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+
+// From Théo's sandbox.
+#include <theo/cplx2d.hh>
+
+// From Alexandre Abraham's sandbox.
+#include <alexandre/topo_wst.hh>
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ std::cerr << "Usage: " << argv[0] << " input.pbm" << std::endl;
+ std::exit(1);
+ }
+
+ using namespace mln;
+ using mln::value::int_u8;
+
+ // Load an image.
+ image2d<int_u8> ima;
+ io::pgm::load(ima, argv[1]);
+
+ // Double its resolution.
+ image2d<int_u8> ima_x2 (10, 10);
+ mln_piter_(image2d<int_u8>) p(ima_x2.domain());
+ for_all(p)
+ {
+ /* This conversion from ``piter'' to ``point'' is required, since
+ an iterator does not expose the interface of the underlying
+ point (among which the methods row(), col(), etc.). */
+ point2d p_ = p;
+ point2d q(p_.row() / 2, p_.col() / 2);
+ ima_x2(p) = ima(q);
+ }
+ debug::println(ima_x2);
+
+ // Compute the associated line graph gradient.
+ mln_VAR(g, cplx2d::f_to_g(ima_x2) );
+ debug::println("g:", g);
+
+ // Compute a topological watershed transform on this gradient.
+ morpho::topo_wst<g_t, cplx2d::dbl_neighb2d> tree(g, cplx2d::e2e());
+ tree.go();
+ mln_VAR(w, morpho::topo_watershed(tree));
+ debug::println("w:", w);
+
+ // Computing the set of values of W.
+ // FIXME: Milena may provide something simpler than this.
+ std::set<int_u8> values;
+ mln_piter_(w_t) p2(w.domain());
+ for_all(p2)
+ values.insert (w(p2));
+
+ // Thresholding for each value of W.
+ for (std::set<int_u8>::iterator alpha = values.begin();
+ alpha != values.end(); ++alpha)
+ {
+ mln_VAR(alpha_cc, w | (pw::value(w) > pw::cst(*alpha)));
+ /* FIXME: There should be variants of debug::println allowing
+ the user to pass an optional ``support'' larger than the
+ actual domain of the image. For now, use a low-level routine
+ as a workaround. */
+ std::cout << *alpha << "-cc:" << std::endl;
+ debug::impl::println(w.unmorph_().domain(), alpha_cc);
+ }
+}
diff --git a/milena/sandbox/levillain/theo b/milena/sandbox/levillain/theo
new file mode 120000
index 0000000..7612684
--- /dev/null
+++ b/milena/sandbox/levillain/theo
@@ -0,0 +1 @@
+../theo/esiee/laurent/ismm09
\ No newline at end of file
--
1.6.4.2