* apps/papers/,
* apps/papers/levillain.09.ismm/:
New directories.
* apps/papers/levillain.09.ismm/chain.hh,
* apps/papers/levillain.09.ismm/complex.cc,
* apps/papers/levillain.09.ismm/graph.cc,
* apps/papers/levillain.09.ismm/image2d.cc:
New (imported from ISMM 2009).
Adjust.
* apps/Makefile.am (SUBDIRS): Add papers.
* apps/papers/Makefile.am,
* apps/papers/levillain.09.ismm/Makefile.am:
New.
---
milena/ChangeLog | 18 +
milena/apps/Makefile.am | 6 +-
milena/apps/{ => papers}/Makefile.am | 5 +-
.../{ => papers/levillain.09.ismm}/Makefile.am | 16 +-
milena/apps/papers/levillain.09.ismm/chain.hh | 42 ++
milena/apps/papers/levillain.09.ismm/complex.cc | 130 +++++
milena/apps/papers/levillain.09.ismm/graph.cc | 497 ++++++++++++++++++++
milena/apps/papers/levillain.09.ismm/image2d.cc | 103 ++++
8 files changed, 809 insertions(+), 8 deletions(-)
copy milena/apps/{ => papers}/Makefile.am (84%)
copy milena/apps/{ => papers/levillain.09.ismm}/Makefile.am (65%)
create mode 100644 milena/apps/papers/levillain.09.ismm/chain.hh
create mode 100644 milena/apps/papers/levillain.09.ismm/complex.cc
create mode 100644 milena/apps/papers/levillain.09.ismm/graph.cc
create mode 100644 milena/apps/papers/levillain.09.ismm/image2d.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 6d1aa08..3cb555a 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,21 @@
+2009-10-02 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Import the code of the illustrations of the ISMM 2009 paper.
+
+ * apps/papers/,
+ * apps/papers/levillain.09.ismm/:
+ New directories.
+ * apps/papers/levillain.09.ismm/chain.hh,
+ * apps/papers/levillain.09.ismm/complex.cc,
+ * apps/papers/levillain.09.ismm/graph.cc,
+ * apps/papers/levillain.09.ismm/image2d.cc:
+ New (imported from ISMM 2009).
+ Adjust.
+ * apps/Makefile.am (SUBDIRS): Add papers.
+ * apps/papers/Makefile.am,
+ * apps/papers/levillain.09.ismm/Makefile.am:
+ New.
+
2009-10-28 Guillaume Lazzara <z(a)lrde.epita.fr>
Small fixes.
diff --git a/milena/apps/Makefile.am b/milena/apps/Makefile.am
index dc39cff..c42ffd7 100644
--- a/milena/apps/Makefile.am
+++ b/milena/apps/Makefile.am
@@ -15,6 +15,8 @@
# along with Olena. If not, see <http://www.gnu.org/licenses/>.
#
-## Process this file through Automake to produce Makefile.in.
-
+# Applied examples of Milena.
SUBDIRS = mesh-segm-skel graph-morpho constrained-connectivity
+
+# Examples from papers.
+SUBDIRS += papers
diff --git a/milena/apps/Makefile.am b/milena/apps/papers/Makefile.am
similarity index 84%
copy from milena/apps/Makefile.am
copy to milena/apps/papers/Makefile.am
index dc39cff..d2ae9bc 100644
--- a/milena/apps/Makefile.am
+++ b/milena/apps/papers/Makefile.am
@@ -13,8 +13,7 @@
#
# You should have received a copy of the GNU General Public License
# along with Olena. If not, see <http://www.gnu.org/licenses/>.
-#
-## Process this file through Automake to produce Makefile.in.
+# Examples from papers.
-SUBDIRS = mesh-segm-skel graph-morpho constrained-connectivity
+SUBDIRS = levillain.09.ismm
diff --git a/milena/apps/Makefile.am b/milena/apps/papers/levillain.09.ismm/Makefile.am
similarity index 65%
copy from milena/apps/Makefile.am
copy to milena/apps/papers/levillain.09.ismm/Makefile.am
index dc39cff..5bcacd3 100644
--- a/milena/apps/Makefile.am
+++ b/milena/apps/papers/levillain.09.ismm/Makefile.am
@@ -13,8 +13,18 @@
#
# You should have received a copy of the GNU General Public License
# along with Olena. If not, see <http://www.gnu.org/licenses/>.
-#
-## Process this file through Automake to produce Makefile.in.
+# Illustrations from the ISMM 2009 paper.
+
+# Find Milena headers.
+AM_CPPFLAGS = -I$(top_srcdir)/milena -I$(top_builddir)/milena
+# Produce fast code.
+APPS_CXXFLAGS = @APPS_CXXFLAGS@
+AM_CXXFLAGS = $(APPS_CXXFLAGS)
+
+noinst_HEADERS = chain.hh
-SUBDIRS = mesh-segm-skel graph-morpho constrained-connectivity
+noinst_PROGRAMS = image2d graph complex
+image2d_SOURCES = image2d.cc
+graph_SOURCES = graph.cc
+complex_SOURCES = complex.cc
diff --git a/milena/apps/papers/levillain.09.ismm/chain.hh
b/milena/apps/papers/levillain.09.ismm/chain.hh
new file mode 100644
index 0000000..d7ee28c
--- /dev/null
+++ b/milena/apps/papers/levillain.09.ismm/chain.hh
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef CHAIN_HH
+# define CHAIN_HH
+
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/watershed/flooding.hh>
+
+template <typename I, typename N, typename L>
+mln_ch_value(I, L)
+chain(const mln::Image<I>& ima, const mln::Neighborhood<N>& nbh,
+ unsigned lambda, L& nbasins)
+{
+ mln_concrete(I) c = mln::morpho::closing::area(ima, nbh, lambda);
+ mln_ch_value(I, L) s = mln::morpho::watershed::flooding(c, nbh, nbasins);
+ return s;
+}
+
+#endif // ! CHAIN_HH
diff --git a/milena/apps/papers/levillain.09.ismm/complex.cc
b/milena/apps/papers/levillain.09.ismm/complex.cc
new file mode 100644
index 0000000..22bd139
--- /dev/null
+++ b/milena/apps/papers/levillain.09.ismm/complex.cc
@@ -0,0 +1,130 @@
+// Copyright (C) 2009 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.
+
+#include <cstdlib>
+
+#include <string>
+
+#include <mln/core/image/complex_image.hh>
+#include <mln/core/image/complex_neighborhoods.hh>
+#include <mln/core/image/complex_windows.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/data/fill.hh>
+#include <mln/math/diff_abs.hh>
+#include <mln/literal/zero.hh>
+
+#include <mln/io/off/load.hh>
+#include <mln/io/off/save.hh>
+#include <mln/labeling/colorize.hh>
+
+#include "chain.hh"
+
+
+// FIXME: Should be rewritten using a diff_abs-based accumulator
+// taking values from triangles (and checking that exactly two values
+// where taken, of course).
+template <unsigned D, typename G, typename V>
+inline
+mln::complex_image<D, G, V>
+gradient_on_edges(const mln::complex_image<D, G, V>& input)
+{
+ typedef mln::complex_image<D, G, V> ima_t;
+ ima_t output (input.domain());
+ mln::data::fill(output, mln::literal::zero);
+
+ // Values on edges.
+ mln::p_n_faces_fwd_piter<D, G> e(input.domain(), 1);
+ // Edge-to-triangle adjacency.
+ typedef mln::complex_higher_neighborhood<D, G> e2t_t;
+ e2t_t e2t;
+ mln_niter(e2t_t) t(e2t, e);
+ // Iterate on edges (1-faces).
+ for_all(e)
+ {
+ t.start();
+ // An edge should be adjacent to at least one triangle.
+ if (!t.is_valid())
+ abort();
+ V v1 = input(t);
+ t.next();
+ // If E is adjacent to two triangles, compute the absolute
+ // difference between their values.
+ if (t.is_valid())
+ {
+ V v2 = input(t);
+ output(e) = mln::math::diff_abs(v1, v2);
+ // There should be no more adjacent triangles.
+ t.next();
+ mln_assertion(!t.is_valid());
+ }
+ }
+ return output;
+}
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ std::cerr << "usage: " << argv[0] << " input.off
lambda output.off"
+ << std::endl;
+ std::exit(1);
+ }
+ std::string input_filename = argv[1];
+ unsigned lambda = atoi(argv[2]);
+ std::string output_filename = argv[3];
+
+ using namespace mln;
+
+ typedef float val;
+ typedef value::label_16 label;
+ // Input and output types.
+ typedef mln::float_2complex_image3df input;
+ typedef mln_ch_value_(input, label) output;
+ static const unsigned dim = input::dim;
+ typedef mln_geom_(input) geom;
+ complex_lower_dim_connected_n_face_neighborhood<dim, geom> nbh;
+ complex_lower_dim_connected_n_face_window_p<dim, geom> win;
+ label nbasins;
+
+ // Load, process, save.
+ /* FIXME: The domain of IMA should be limited to 2-faces. Alas, we
+ do not have (yet) an mln::pcomplex_subset site set type. Anyway,
+ this should not alter the results, only slow the computation
+ down. */
+ input ima;
+ io::off::load(ima, input_filename);
+
+ // Gradient on edges.
+ input g = gradient_on_edges(ima);
+ output s = chain(ima, nbh, lambda, nbasins);
+ io::off::save(labeling::colorize(value::rgb8(), s, nbasins),
+ output_filename);
+}
diff --git a/milena/apps/papers/levillain.09.ismm/graph.cc
b/milena/apps/papers/levillain.09.ismm/graph.cc
new file mode 100644
index 0000000..bd6f983
--- /dev/null
+++ b/milena/apps/papers/levillain.09.ismm/graph.cc
@@ -0,0 +1,497 @@
+// Copyright (C) 2008, 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.
+
+#include <iostream>
+#include <iomanip>
+
+#include <vector>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/site_set/p_queue_fast.hh>
+#include <mln/labeling/blobs.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/debug/println.hh>
+#include <mln/draw/line.hh>
+#include <mln/pw/all.hh>
+#include <mln/binarization/threshold.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_8.hh>
+#include <mln/core/alias/point2d.hh>
+
+#include <mln/core/site_set/p_faces.hh>
+#include <mln/core/image/complex_image.hh>
+#include <mln/core/alias/complex_geometry.hh>
+#include <mln/core/alias/complex_image.hh>
+
+// FIXME: Include these elsewhere? (In complex_image.hh?)
+#include <mln/core/image/complex_neighborhoods.hh>
+#include <mln/core/image/complex_neighborhood_piter.hh>
+#include <mln/core/image/complex_windows.hh>
+
+#include <mln/data/fill.hh>
+#include <mln/morpho/gradient.hh>
+#include <mln/labeling/colorize.hh>
+
+#include "chain.hh"
+
+
+// FIXME: Copied and adjusted from pics/graph.cc; factor.
+
+namespace mln
+{
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ influence_zones(const I& input, const N& nbh)
+ {
+ mln_concrete(I) output = duplicate(input);
+
+ p_queue_fast<mln_site(I)> q;
+
+ {
+ // Initialization.
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if (input(p) != 0)
+ for_all(n) if (input.has(n))
+ if (input(n) == 0)
+ {
+ q.push(p);
+ break;
+ }
+ }
+ {
+ // Body.
+ mln_site(I) p;
+ mln_niter(N) n(nbh, p);
+ while (! q.is_empty())
+ {
+ p = q.pop_front();
+ mln_invariant(output(p) != 0);
+ for_all(n) if (input.has(n))
+ if (output(n) == 0)
+ {
+ output(n) = output(p);
+ q.push(n);
+ }
+ }
+ }
+
+ return output;
+
+ }
+
+
+ namespace io
+ {
+
+ namespace neato
+ {
+
+ /* FIXME: This is just the gray-level version. Handle other value
+ types as well. */
+ void
+ save(const complex_image<1, discrete_plane_1complex_geometry,
+ value::int_u8>& ima,
+ const std::string& filename,
+ const std::string& bgcolor = "#0000C0",
+ const std::string& fontcolor = "#0000C0",
+ bool empty_vertex_label = true)
+ {
+ typedef value::int_u8 V;
+ typedef complex_image<1, discrete_plane_1complex_geometry, V> I;
+ const unsigned D = 1;
+ typedef discrete_plane_1complex_geometry G;
+
+ std::ofstream g(filename.c_str());
+ g << "graph wst" << std::endl
+ << "{" << std::endl
+ << " graph [bgcolor = \"" << bgcolor <<
"\"]" << std::endl
+ << " edge [color = \"#FFFFFF\"]" << std::endl
+ << " node [color = \"#FFFFFF\", height=\"5\",
width=\"5\","
+ << " fontsize=\"100\", fontcolor = \"" <<
fontcolor << "\"]"
+ << std::endl;
+
+ // Vertices.
+ p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
+ typedef complex_higher_neighborhood<D, G> e_nbh_t;
+ e_nbh_t e_nbh;
+ for_all(v)
+ {
+ V vertex_color = ima(v);
+ std::ostringstream vertex_color_str;
+ // FIXME: Only valid for gray-level images.
+ vertex_color_str << '#'
+ << std::hex
+ << std::setfill('0')
+ << std::setw(2) << vertex_color
+ << std::setw(2) << vertex_color
+ << std::setw(2) << vertex_color
+ << std::dec;
+
+ g << " v" << v.unproxy_().face_id()
+ << " [pos = \""
+ << std::fixed << std::setprecision(1)
+ << (float)v.to_site().front()[1] << ", "
+ << -(float)v.to_site().front()[0]
+ << "\", color = \"" << vertex_color_str.str()
+ << "\", fillcolor = \"" << vertex_color_str.str()
+ << "\", pin = \"true\",
style=\"filled,setlinewidth(3)\"";
+ if (empty_vertex_label)
+ g << ", label = \"\"";
+ g << "];"
+ << std::endl;
+ }
+
+ // Edges.
+ p_n_faces_fwd_piter<D, G> e(ima.domain(), 1);
+ typedef complex_lower_neighborhood<D, G> v_nbh_t;
+ v_nbh_t v_nbh;
+ mln_niter_(v_nbh_t) adj_v(v_nbh, e);
+ for_all(e)
+ {
+ V edge_color = ima(e);
+ std::ostringstream edge_color_str;
+ edge_color_str << '#'
+ << std::hex
+ << std::setfill('0')
+ << std::setw(2) << edge_color
+ << std::setw(2) << edge_color
+ << std::setw(2) << edge_color
+ << std::dec;
+
+ // Adjacent vertices.
+ adj_v.start();
+ topo::face<1> v1 = adj_v.unproxy_().face();
+ point2d p1 = adj_v.to_site().front();
+ adj_v.next();
+ topo::face<1> v2 = adj_v.unproxy_().face();
+ point2d p2 = adj_v.to_site().front();
+ adj_v.next();
+ mln_invariant(!adj_v.is_valid());
+
+ g << " v" << v1.face_id() << " -- v" <<
v2.face_id() << " ";
+ g << "[color = \"" << edge_color_str.str()
+ << "\", style=\"setlinewidth(10)\"];" <<
std::endl;
+ }
+
+ g << "}" << std::endl;
+ g.close();
+ }
+
+ // FIXME: Factor with the previous version.
+ void
+ save(const complex_image<1, discrete_plane_1complex_geometry,
+ value::rgb8>& ima,
+ const std::string& filename,
+ const std::string& bgcolor = "#0000C0",
+ const std::string& fontcolor = "#0000C0",
+ bool empty_vertex_label = true)
+ {
+ typedef value::rgb8 V;
+ typedef complex_image<1, discrete_plane_1complex_geometry, V> I;
+ const unsigned D = 1;
+ typedef discrete_plane_1complex_geometry G;
+
+ std::ofstream g(filename.c_str());
+ g << "graph wst" << std::endl
+ << "{" << std::endl
+ << " graph [bgcolor = \"" << bgcolor <<
"\"]" << std::endl
+ << " edge [color = \"#FFFFFF\"]" << std::endl
+ << " node [color = \"#FFFFFF\", height=\"5\",
width=\"5\","
+ << " fontsize=\"100\", fontcolor = \"" <<
fontcolor << "\"]"
+ << std::endl;
+
+ // Vertices.
+ p_n_faces_fwd_piter<D, G> v(ima.domain(), 0);
+ typedef complex_higher_neighborhood<D, G> e_nbh_t;
+ e_nbh_t e_nbh;
+ for_all(v)
+ {
+ V vertex_color = ima(v);
+ std::ostringstream vertex_color_str;
+ // FIXME: Only valid for gray-level images.
+ vertex_color_str << '#'
+ << std::hex
+ << std::setfill('0')
+ << std::setw(2) << vertex_color.red()
+ << std::setw(2) << vertex_color.green()
+ << std::setw(2) << vertex_color.blue()
+ << std::dec;
+
+ g << " v" << v.unproxy_().face_id()
+ << " [pos = \""
+ << std::fixed << std::setprecision(1)
+ << (float)v.to_site().front()[1] << ", "
+ << -(float)v.to_site().front()[0]
+ << "\", color = \"" << vertex_color_str.str()
+ << "\", fillcolor = \"" << vertex_color_str.str()
+ << "\", pin = \"true\",
style=\"filled,setlinewidth(3)\"";
+ if (empty_vertex_label)
+ g << ", label = \"\"";
+ g << "];"
+ << std::endl;
+ }
+
+ // Edges.
+ p_n_faces_fwd_piter<D, G> e(ima.domain(), 1);
+ typedef complex_lower_neighborhood<D, G> v_nbh_t;
+ v_nbh_t v_nbh;
+ mln_niter_(v_nbh_t) adj_v(v_nbh, e);
+ for_all(e)
+ {
+ V edge_color = ima(e);
+ std::ostringstream edge_color_str;
+ edge_color_str << '#'
+ << std::hex
+ << std::setfill('0')
+ << std::setw(2) << edge_color.red()
+ << std::setw(2) << edge_color.green()
+ << std::setw(2) << edge_color.blue()
+ << std::dec;
+
+ // Adjacent vertices.
+ adj_v.start();
+ topo::face<1> v1 = adj_v.unproxy_().face();
+ point2d p1 = adj_v.to_site().front();
+ adj_v.next();
+ topo::face<1> v2 = adj_v.unproxy_().face();
+ point2d p2 = adj_v.to_site().front();
+ adj_v.next();
+ mln_invariant(!adj_v.is_valid());
+
+ g << " v" << v1.face_id() << " -- v" <<
v2.face_id() << " ";
+ g << "[color = \"" << edge_color_str.str()
+ << "\", style=\"setlinewidth(10)\"];" <<
std::endl;
+ }
+
+ g << "}" << std::endl;
+ g.close();
+ }
+
+ } // end of namespace mln::io::neato
+
+ } // end of namespace mln::io
+
+} // end of namespace mln
+
+
+// FIXME: Clean up and move into Milena?
+mln::int_u8_1complex_image2d
+make_complex_image(const mln::image2d<mln::value::int_u8>& input)
+{
+ using namespace mln;
+ using mln::value::int_u8;
+
+ /*----------------------------------------.
+ | Complex + complex geometry (location). |
+ `----------------------------------------*/
+
+ border::thickness = 0;
+
+ unsigned nlabels;
+ image2d<unsigned> label =
+ labeling::blobs(mln::binarization::threshold(input, 1), c4(), nlabels);
+
+ std::cout << "n seeds = " << nlabels << std::endl;
+ {
+ image2d<int_u8> lab(label.domain());
+ data::paste(label, lab);
+ }
+
+ image2d<unsigned> iz = influence_zones(label, c4());
+ {
+ image2d<int_u8> IZ(iz.domain());
+ data::paste(iz, IZ);
+ }
+
+
+ // Make graph/complex.
+
+ std::vector< std::vector<bool> > adj(nlabels + 1);
+ for (unsigned l = 1; l <= nlabels; ++l)
+ adj[l].resize(nlabels + 1, false);
+
+ {
+ box2d::piter p(iz.domain());
+ for_all(p)
+ {
+ point2d r = p + right, b = p + down;
+ if (iz.has(r) && iz(p) != iz(r))
+ {
+ if (iz(p) <= iz(r))
+ adj[iz(p)][iz(r)] = true;
+ else
+ adj[iz(r)][iz(p)] = true;
+ }
+ if (iz.has(b) && iz(p) != iz(b))
+ {
+ if (iz(p) <= iz(b))
+ adj[iz(p)][iz(b)] = true;
+ else
+ adj[iz(b)][iz(p)] = true;
+ }
+ }
+ }
+
+ // end of mk_graph
+
+
+ const unsigned D = 1;
+
+ topo::complex<D> c;
+
+ typedef point2d P;
+ typedef geom::complex_geometry<D, P> G;
+ G geom;
+
+ // Convenience typedefs.
+ typedef topo::n_face<0, D> vertex;
+ typedef topo::n_face<1, D> edge;
+
+ {
+
+ // 0-faces (vertices).
+ std::vector<vertex> v;
+ {
+ box2d::piter p(label.domain());
+ for_all(p)
+ if (label(p) != 0)
+ {
+ geom.add_location(p);
+ v.push_back(c.add_face());
+ }
+ }
+
+ std::cout << "v size = " << v.size() << std::endl;
+
+ // 1-faces (edges).
+ std::vector<edge> e;
+ {
+ for (unsigned l = 1; l <= nlabels; ++l)
+ for (unsigned ll = l + 1; ll <= nlabels; ++ll)
+ if (adj[l][ll])
+ e.push_back( c.add_face(-v[l-1] + v[ll-1]) );
+ }
+
+ std::cout << "e size = " << e.size() << std::endl;
+
+ }
+
+
+ /*---------------------.
+ | Complex-based pset. |
+ `---------------------*/
+
+ p_complex<D, G> pc(c, geom);
+
+ /*----------------------.
+ | Complex-based image. |
+ `----------------------*/
+
+ // An image type built on a 1-complex with unsigned values on each
+ // face (both vertices and edges).
+ typedef complex_image<D, G, int_u8> output_t;
+
+ // Create and initialize an image based on PC.
+ output_t output(pc);
+
+ // Color OUTPUT's vertices with INPUT's values.
+ p_n_faces_fwd_piter<D, G> v(output.domain(), 0);
+ for_all(v)
+ output(v) = input(v.to_site().front());
+
+ // Use a medium gray to color edges.
+ p_n_faces_fwd_piter<D, G> e(output.domain(), 1);
+ for_all(e)
+ output(e) = 128;
+
+ return output;
+}
+
+
+// FIXME: Move to Milena?
+template <unsigned D, typename G, typename V>
+mln::complex_higher_dim_connected_n_face_window_p<D, G>
+make_elt_win(const mln::complex_image<D, G, V>& /* ima */)
+{
+ return mln::complex_higher_dim_connected_n_face_window_p<D, G>();
+}
+
+// FIXME: Move to Milena?
+template <unsigned D, typename G, typename V>
+mln::complex_higher_dim_connected_n_face_neighborhood<D, G>
+make_elt_nbh(const mln::complex_image<D, G, V>& /* ima */)
+{
+ return mln::complex_higher_dim_connected_n_face_neighborhood<D, G>();
+}
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ std::cerr << "usage: " << argv[0] << " seeds.pgm
lambda output.neato"
+ << std::endl;
+ std::exit(1);
+ }
+ std::string input_filename = argv[1];
+ unsigned lambda = atoi(argv[2]);
+ std::string output_filename = argv[3];
+
+ using namespace mln;
+ using mln::value::int_u8;
+ // Use clearer names.
+ typedef int_u8_1complex_image2d int_u8_graph_image2d;
+
+ typedef int_u8_graph_image2d input;
+ typedef value::label_8 label;
+ typedef mln_ch_value_(input, label) output;
+ label nbasins;
+
+ // Seeds.
+ image2d<int_u8> seeds = io::pgm::load<int_u8>(input_filename);
+ // Input image computed from the graph of influence zones (IZ) of seeds.
+ typedef int_u8_graph_image2d ima_t;
+ ima_t ima = make_complex_image(seeds);
+ io::neato::save(ima, "apps/graph.neato");
+
+ // Gradient.
+ input g = morpho::gradient(ima, make_elt_win(ima));
+
+#if 0
+ // FIXME: get the name as argument.
+ io::neato::save(g, "apps/graph-g.neato");
+#endif
+
+ // Chain.
+ output s = chain(g, make_elt_nbh(g), lambda, nbasins);
+ io::neato::save(labeling::colorize(value::rgb8(), s, nbasins),
+ output_filename);
+}
diff --git a/milena/apps/papers/levillain.09.ismm/image2d.cc
b/milena/apps/papers/levillain.09.ismm/image2d.cc
new file mode 100644
index 0000000..c1a7d3c
--- /dev/null
+++ b/milena/apps/papers/levillain.09.ismm/image2d.cc
@@ -0,0 +1,103 @@
+// Copyright (C) 2009 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.
+
+#include <cstdlib>
+
+#include <string>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_8.hh>
+
+#include <mln/morpho/gradient.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/labeling/colorize.hh>
+
+#include "chain.hh"
+
+int main(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ std::cerr << "usage: " << argv[0] << " input.pgm
lambda output.ppm"
+ << std::endl;
+ std::exit(1);
+ }
+ std::string input_filename = argv[1];
+ unsigned lambda = atoi(argv[2]);
+ std::string output_filename = argv[3];
+
+ using namespace mln;
+
+ typedef value::int_u8 val;
+ typedef value::label_8 label;
+ // Input and output types.
+ typedef image2d<val> input;
+ typedef mln_ch_value_(input, label) output;
+ neighb2d nbh = c4();
+ window2d win = win_c4p();
+ label nbasins;
+
+ std::cout << c4() << std::endl;
+ std::cout << win_c4p() << std::endl;
+
+ // Load, process, save.
+ input ima = io::pgm::load<val>(input_filename);
+ // Gradient.
+ /* FIXME: Unfortunately, we cannot write
+
+ morpho::gradient(ima, win)
+
+ here, since MM only uses windows (yet?), not neighborhoods. And
+ we cannot either write
+
+ morpho::gradient(ima, nbh.win()),
+
+ since that window would not contain the center site...
+ Therefore, this function asks for a window WIN matching the
+ neighborhood NBH, plus the center site.
+
+ A neighborhood `n' should provide a method `win_p()' returning a
+ window corresponding to `n' plus the center site. */
+ input g = morpho::gradient(ima, win);
+
+#if 0
+ // FIXME: get the name as argument.
+ io::pgm::save(g, "apps/lena-g.pgm");
+#endif
+
+ // Chain.
+ output s = chain(g, nbh, lambda, nbasins);
+ io::ppm::save(labeling::colorize(value::rgb8(), s, nbasins),
+ output_filename);
+}
--
1.6.5