[PATCH 1/6] Simplify graph-based image I/O in apps/graph-morpho.

* apps/graph-morpho/complex1d.cc (make_regular_complex1d_image): New function. Use it... (main): ...here, to simplify the construction of the input image, by reading it from... * apps/graph-morpho/x.pbm: ...this (new) image. * apps/data.hh.in: New. * apps/graph-morpho/Makefile.am (AM_CPPFLAGS): Add -I$(top_builddir)/milena. (bin_PROGRAMS): Rename as... (noinst_PROGRAMS): ...this. (EXTRA_DIST): New. Add x.pbm. --- milena/ChangeLog | 18 ++++ milena/apps/data.hh.in | 41 ++++++++ milena/apps/graph-morpho/Makefile.am | 6 +- milena/apps/graph-morpho/complex1d.cc | 162 ++++++++++++++++---------------- milena/apps/graph-morpho/x.pbm | 20 ++++ 5 files changed, 164 insertions(+), 83 deletions(-) create mode 100644 milena/apps/data.hh.in create mode 100644 milena/apps/graph-morpho/x.pbm diff --git a/milena/ChangeLog b/milena/ChangeLog index 700906c..3f74480 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,21 @@ +2009-09-10 Roland Levillain <roland@lrde.epita.fr> + + Simplify graph-based image I/O in apps/graph-morpho. + + * apps/graph-morpho/complex1d.cc (make_regular_complex1d_image): + New function. + Use it... + (main): ...here, to simplify the construction of the input image, + by reading it from... + * apps/graph-morpho/x.pbm: ...this (new) image. + * apps/data.hh.in: New. + * apps/graph-morpho/Makefile.am (AM_CPPFLAGS): + Add -I$(top_builddir)/milena. + (bin_PROGRAMS): Rename as... + (noinst_PROGRAMS): ...this. + (EXTRA_DIST): New. + Add x.pbm. + 2009-09-10 Fabien Freling <fabien.freling@lrde.epita.fr> Fix luminance value computation for RGB to HSL. diff --git a/milena/apps/data.hh.in b/milena/apps/data.hh.in new file mode 100644 index 0000000..8adb35f --- /dev/null +++ b/milena/apps/data.hh.in @@ -0,0 +1,41 @@ +// 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. + +#ifndef APPS_DATA_HH +# define APPS_DATA_HH + +# include <string> + +/* Macros are evil, but they save us an extra compilation unit here + (as well as additional burden in Makefiles, too.). */ + +/// The absolute path to the img directory of Milena. +# define MLN_IMG_DIR "@abs_top_srcdir@/milena/img" + +/// The absolute path to the apps directory of Milena. +# define MLN_APPS_DIR "@abs_top_srcdir@/milena/apps/" + +#endif // ! APPS_DATA_HH diff --git a/milena/apps/graph-morpho/Makefile.am b/milena/apps/graph-morpho/Makefile.am index 590e756..0d7f9e7 100644 --- a/milena/apps/graph-morpho/Makefile.am +++ b/milena/apps/graph-morpho/Makefile.am @@ -15,12 +15,14 @@ # along with Olena. If not, see <http://www.gnu.org/licenses/>. # Find Milena headers. -AM_CPPFLAGS = -I$(top_srcdir)/milena +AM_CPPFLAGS = -I$(top_srcdir)/milena -I$(top_builddir)/milena # Produce fast code. APPS_CXXFLAGS = @APPS_CXXFLAGS@ AM_CXXFLAGS = $(APPS_CXXFLAGS) -bin_PROGRAMS = complex1d +noinst_PROGRAMS = complex1d complex1d_SOURCES = complex1d.cc TESTS = complex1d + +EXTRA_DIST = x.pbm diff --git a/milena/apps/graph-morpho/complex1d.cc b/milena/apps/graph-morpho/complex1d.cc index 93eab21..6e98310 100644 --- a/milena/apps/graph-morpho/complex1d.cc +++ b/milena/apps/graph-morpho/complex1d.cc @@ -42,6 +42,11 @@ #include <mln/core/site_set/p_set.hh> #include <mln/util/site_pair.hh> +#include <mln/math/abs.hh> + +#include <mln/io/pbm/load.hh> + +#include "apps/data.hh" using namespace mln; @@ -120,6 +125,54 @@ build_regular_complex1d_image(const box2d& support) return ima; } +template <typename I> +ima_t +make_regular_complex1d_image(const Image<I>& input_) +{ + const I& input = exact(input_); + const box2d& input_box = input.domain(); + // The input image must have an odd number of rows and columns. + mln_precondition(input_box.nrows() % 2 == 1); + mln_precondition(input_box.ncols() % 2 == 1); + + // The domain of the graph image is twice as small, since we + // consider only vertices (edges are set ``between'' vertices). + box2d output_box(input_box.nrows() / 2 + 1, + input_box.ncols() / 2 + 1); + ima_t output = build_regular_complex1d_image(output_box); + + // Add values on vertices. + p_n_faces_fwd_piter<dim, geom_t> v(output.domain(), 0); + for_all(v) + { + mln_site_(geom_t) s(v); + // Site S is point2d multi-site and should be a singleton (since V + // iterates on vertices). + mln_invariant(s.size() == 1); + point2d p = s.front(); + point2d q(p.row() * 2, p.col() * 2); + output(v) = input(q); + } + + // Add values on edges. + p_n_faces_fwd_piter<dim, geom_t> e(output.domain(), 1); + for_all(e) + { + mln_site_(geom_t) s(e); + // Site S is point2d multi-site and should be a pair (since E + // iterates on vertices). + mln_invariant(s.size() == 2); + point2d p1 = s[0]; + point2d p2 = s[1]; + mln_invariant(math::abs(p1.row() - p2.row()) == 1 + || math::abs(p1.col() - p2.col()) == 1); + point2d q (p1.row() + p2.row(), p1.col() + p2.col()); + output(e) = input(q); + } + + return output; +} + template <typename T> void @@ -370,104 +423,51 @@ erosion_graph(const Image<I>& input) } +/*-----------------------------------. +| Applying morphological operators. | +`-----------------------------------*/ int main() { - /*--------------. - | Input image. | - `--------------*/ - /* Build a ``regular'' graph image. Of course, it would have been better, simpler and faster to use a cubical 1-complex here, but - they are not yet available. */ - box2d b(9, 6); - ima_t ima = build_regular_complex1d_image(b); - - /* Set the values so that IMA corresponds to the graph X of the ISMM - 2009 paper from Jean Cousty et al. */ - - // The set of vertices of the graph. - p_set<point2d> vertices; - vertices.insert(point2d(1, 2)); - vertices.insert(point2d(2, 1)); - vertices.insert(point2d(2, 2)); - vertices.insert(point2d(3, 4)); - vertices.insert(point2d(5, 2)); - vertices.insert(point2d(5, 3)); - vertices.insert(point2d(5, 4)); - vertices.insert(point2d(6, 1)); - vertices.insert(point2d(6, 2)); - vertices.insert(point2d(6, 3)); - vertices.insert(point2d(6, 4)); - vertices.insert(point2d(7, 2)); - vertices.insert(point2d(7, 3)); - // Add vertices. - p_n_faces_fwd_piter<dim, geom_t> v(ima.domain(), 0); - for_all(v) - { - mln_site_(geom_t) s(v); - // Site S is point2d multi-site and should be a singleton (since V - // iterates on vertices). - mln_invariant(s.size() == 1); - point2d p = s.front(); - ima(v) = vertices.has(p); - } - - // The set of edges of the graph. - typedef util::site_pair<point2d> point2d_pair; - p_set< util::site_pair<point2d> > edges; - edges.insert(point2d_pair(point2d(2, 1), point2d(2, 2))); - edges.insert(point2d_pair(point2d(5, 3), point2d(5, 4))); - edges.insert(point2d_pair(point2d(5, 2), point2d(6, 2))); - edges.insert(point2d_pair(point2d(5, 3), point2d(6, 3))); - edges.insert(point2d_pair(point2d(6, 1), point2d(6, 2))); - edges.insert(point2d_pair(point2d(6, 2), point2d(6, 3))); - edges.insert(point2d_pair(point2d(6, 3), point2d(6, 4))); - edges.insert(point2d_pair(point2d(6, 2), point2d(7, 2))); - edges.insert(point2d_pair(point2d(6, 3), point2d(7, 3))); - edges.insert(point2d_pair(point2d(7, 2), point2d(7, 3))); - // Add edges. - p_n_faces_fwd_piter<dim, geom_t> e(ima.domain(), 1); - for_all(e) - { - mln_site_(geom_t) s(e); - // Site S is point2d multi-site and should be a pair (since E - // iterates on vertices). - mln_invariant(s.size() == 2); - point2d p1 = s[0]; - point2d p2 = s[1]; - ima(e) = - edges.has(point2d_pair(p1, p2)) || edges.has(point2d_pair(p2, p1)); - } - std::cout << "ima:" << std::endl; - println(ima, b); + they are not yet available (as of 2009-09-10). */ - /*-----------------------------------. - | Applying morphological operators. | - `-----------------------------------*/ + // ------------------------ // + // Dilations and erosions. // + // ------------------------ // - ima_t dil_e2v_ima = dilation_e2v(ima); + /* Set the values so that X corresponds to the graph X of the ISMM + 2009 paper from Jean Cousty et al. */ + image2d<bool> x_pbm = io::pbm::load(MLN_APPS_DIR "/graph-morpho/x.pbm"); + ima_t x = make_regular_complex1d_image(x_pbm); + box2d x_box(x_pbm.nrows() / 2 + 1, x_pbm.ncols() / 2 + 1); + std::cout << "x:" << std::endl; + println(x, x_box); + + ima_t dil_e2v_ima = dilation_e2v(x); std::cout << "dil_e2v_ima:" << std::endl; - println(dil_e2v_ima, b); + println(dil_e2v_ima, x_box); - ima_t ero_v2e_ima = erosion_v2e(ima); + ima_t ero_v2e_ima = erosion_v2e(x); std::cout << "ero_v2e_ima:" << std::endl; - println(ero_v2e_ima, b); + println(ero_v2e_ima, x_box); + - ima_t ero_e2v_ima = erosion_e2v(ima); + ima_t ero_e2v_ima = erosion_e2v(x); std::cout << "ero_e2v_ima:" << std::endl; - println(ero_e2v_ima, b); + println(ero_e2v_ima, x_box); - ima_t dil_v2e_ima = dilation_v2e(ima); + ima_t dil_v2e_ima = dilation_v2e(x); std::cout << "dil_v2e_ima:" << std::endl; - println(dil_v2e_ima, b); + println(dil_v2e_ima, x_box); - ima_t dil_ima = dilation_graph(ima); + ima_t dil_ima = dilation_graph(x); std::cout << "dil_ima:" << std::endl; - println(dil_ima, b); + println(dil_ima, x_box); - ima_t ero_ima = erosion_graph(ima); + ima_t ero_ima = erosion_graph(x); std::cout << "ero_ima:" << std::endl; - println(ero_ima, b); + println(ero_ima, x_box); } diff --git a/milena/apps/graph-morpho/x.pbm b/milena/apps/graph-morpho/x.pbm new file mode 100644 index 0000000..5bbea77 --- /dev/null +++ b/milena/apps/graph-morpho/x.pbm @@ -0,0 +1,20 @@ +P1 +# x.pbm +11 17 +1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 0 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 +1 1 0 0 0 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 0 1 1 +1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 0 1 0 0 0 1 1 +1 1 1 1 0 1 0 1 1 1 1 +1 1 0 0 0 0 0 0 0 1 1 +1 1 1 1 0 1 0 1 1 1 1 +1 1 1 1 0 0 0 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 -- 1.6.4.2
participants (1)
-
Roland Levillain