[PATCH 1/3] 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. --- 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@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@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
participants (1)
-
Roland Levillain