* apps/morphers/mask+channel.cc,
* apps/morphers/recorder.cc,
* apps/morphers/mask+recorder.cc:
New.
* apps/morphers/Makefile.am: New.
* apps/Makefile.am (SUBDIRS): Add morphers.
---
milena/ChangeLog | 11 ++
milena/apps/Makefile.am | 5 +-
.../Makefile.am | 24 +++-
.../morphers/mask+channel.cc} | 76 +++++------
milena/apps/morphers/mask+recorder.cc | 140 ++++++++++++++++++++
milena/apps/morphers/recorder.cc | 135 +++++++++++++++++++
6 files changed, 338 insertions(+), 53 deletions(-)
copy milena/apps/{constrained-connectivity => morphers}/Makefile.am (62%)
copy milena/{doc/examples/tuto3_rw_image.cc => apps/morphers/mask+channel.cc} (58%)
create mode 100644 milena/apps/morphers/mask+recorder.cc
create mode 100644 milena/apps/morphers/recorder.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 544cc30..c10deb8 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,14 @@
+2011-11-14 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Add examples of morphers.
+
+ * apps/morphers/mask+channel.cc,
+ * apps/morphers/recorder.cc,
+ * apps/morphers/mask+recorder.cc:
+ New.
+ * apps/morphers/Makefile.am: New.
+ * apps/Makefile.am (SUBDIRS): Add morphers.
+
2011-10-04 Roland Levillain <roland(a)lrde.epita.fr>
Handle the case of filling an empty border.
diff --git a/milena/apps/Makefile.am b/milena/apps/Makefile.am
index c42ffd7..465f1db 100644
--- a/milena/apps/Makefile.am
+++ b/milena/apps/Makefile.am
@@ -1,4 +1,5 @@
-# Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2008, 2009, 2011 EPITA Research and Development
+# Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -16,7 +17,7 @@
#
# Applied examples of Milena.
-SUBDIRS = mesh-segm-skel graph-morpho constrained-connectivity
+SUBDIRS = mesh-segm-skel graph-morpho constrained-connectivity morphers
# Examples from papers.
SUBDIRS += papers
diff --git a/milena/apps/constrained-connectivity/Makefile.am
b/milena/apps/morphers/Makefile.am
similarity index 62%
copy from milena/apps/constrained-connectivity/Makefile.am
copy to milena/apps/morphers/Makefile.am
index c0dfb0d..d7af433 100644
--- a/milena/apps/constrained-connectivity/Makefile.am
+++ b/milena/apps/morphers/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -14,17 +14,27 @@
# You should have received a copy of the GNU General Public License
# along with Olena. If not, see <http://www.gnu.org/licenses/>.
+# Illustrations of morphers.
+
# 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_PROGRAMS = constrained-connectivity
-constrained_connectivity_SOURCES = constrained-connectivity.cc
-constrained_connectivity_CXXFLAGS = $(AM_CXXFLAGS) $(STRICT_ALIASING_CXXFLAGS)
+noinst_PROGRAMS = \
+ mask+channel \
+ recorder \
+ mask+recorder
+
+mask_channel_SOURCES = mask+channel.cc
+recorder_SOURCES = recorder.cc
+mask_recorder_SOURCES = mask+recorder.cc
-TESTS = test-constrained-connectivity
+MOSTLYCLEANFILES = \
+ lena-mask-channel.ppm \
+ lena-fill??????.ppm \
+ lena-roi-fill??????.ppm
-# The sample image form Pierre Soille's PAMI 2008 article.
-EXTRA_DIST = soille.pgm
+# FIXME: Also produce movies (see comments in recorder.cc and
+# mask+recorder.cc.)
diff --git a/milena/doc/examples/tuto3_rw_image.cc b/milena/apps/morphers/mask+channel.cc
similarity index 58%
copy from milena/doc/examples/tuto3_rw_image.cc
copy to milena/apps/morphers/mask+channel.cc
index 14ba056..ffbe023 100644
--- a/milena/doc/examples/tuto3_rw_image.cc
+++ b/milena/apps/morphers/mask+channel.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -24,58 +24,46 @@
// executable file might be covered by the GNU General Public License.
/// \file
+/// \brief Example projecting a RGB image to the green channel and
+/// then applying a domain restricting with a mask.
-#include <mln/core/image/image2d.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/data/fill.hh>
-#include <mln/data/paste.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/literal/colors.hh>
-#include <mln/opt/at.hh>
+#include <sstream>
+#include <iomanip>
-#include <tests/data.hh>
-#include <doc/tools/sample_utils.hh>
+#include <string>
-int main()
-{
- using namespace mln;
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/fun/component/green.hh>
- // \{
- image2d<value::rgb8> ima(40, 40);
- // \}
+#include <mln/value/rgb8.hh>
+
+/* FIXME: We wanted to use `fun_image' and `operator<<' from
+ <mln/core/image/vmorph/fun_image.hh, but they only create read-only
+ images. Use `thru_image' instead. */
+#include <mln/core/image/vmorph/thru_image.hh>
- // \{
- data::fill(ima, literal::red);
- // \}
+#include <mln/core/routine/duplicate.hh>
- // \{
- for (def::coord row = 20; row < 30; ++row)
- for (def::coord col = 20; col < 30; ++col)
- ima(point2d(row, col)) = literal::blue;
- // \}
+#include <mln/literal/colors.hh>
+#include <mln/data/fill.hh>
- // \{
- for (def::coord row = 20; row < 30; ++row)
- for (def::coord col = 20; col < 30; ++col)
- opt::at(ima, row, col) = literal::blue;
- // \}
- doc::ppmsave(ima, "tuto3_rw_image");
+#include <mln/io/ppm/all.hh>
- image2d<value::rgb8> ima2 = duplicate(ima);
+#include "apps/data.hh"
- // \{
- image2d<value::rgb8> lena;
- io::ppm::load(lena, MLN_IMG_DIR "/small.ppm");
- // \}
- // \{
- data::fill(ima, lena);
- // \}
- doc::ppmsave(ima, "tuto3_rw_image");
+int main()
+{
+ using namespace mln;
+ using mln::value::rgb8;
- ima = ima2;
- // \{
- data::paste(ima, lena);
- // \}
- doc::ppmsave(lena, "tuto3_rw_image");
+ image2d<rgb8> lena = io::ppm::load<rgb8>(MLN_IMG_DIR
"/tiny.ppm");
+ fun::green green;
+ /* FIXME: Cheat: use generic fill as mln::decorated_image does not
+ define properly its properties. */
+ data::impl::generic::fill_with_value((thru(green, lena).rw() |
+ box2d(point2d(5,5), point2d(10,10))).rw(),
+ 255);
+ io::ppm::save(lena, "lena-mask-channel.ppm");
}
diff --git a/milena/apps/morphers/mask+recorder.cc
b/milena/apps/morphers/mask+recorder.cc
new file mode 100644
index 0000000..d697451
--- /dev/null
+++ b/milena/apps/morphers/mask+recorder.cc
@@ -0,0 +1,140 @@
+// Copyright (C) 2011 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
+/// \brief Morpher recording every change in the morphed image
+/// followed by the application of a domain restriction with a mask.
+///
+/// To produce an AVI movie from the `lena-roi-fill*.ppm' files, use:
+///
+/// for f in lena-roi-fill*ppm; convert $f -scale 2500% $(basename $f .ppm).png
+/// mencoder "mf://lena-roi-fill*.png" -o lena-roi-fill.avi -ovc lavc
-lavcopts vcodec=mjpeg
+///
+/// The output `lena-roi-fill.avi' can be embedded in a PDF file. */
+
+// FIXME: Factor with recorder.cc.
+
+#include <sstream>
+#include <iomanip>
+
+#include <string>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/core/image/imorph/decorated_image.hh>
+
+#include <mln/value/rgb8.hh>
+
+#include <mln/core/routine/duplicate.hh>
+
+#include <mln/literal/colors.hh>
+#include <mln/data/fill.hh>
+
+#include <mln/io/ppm/all.hh>
+
+#include "apps/data.hh"
+
+
+// FIXME: mln::decorated_image lacks a proper definition of
+// properties! (see mln/core/image/imorph/decorated_image.hh
+namespace mln
+{
+
+ namespace trait
+ {
+
+ template <typename I, typename D>
+ struct image_< decorated_image<I,D> >
+ : default_image_morpher< I,
+ mln_value(I),
+ decorated_image<I,D> >
+ {
+ typedef trait::image::category::identity_morpher category;
+ };
+
+ } // end of namespace mln::trait
+
+} // end of namespace mln
+
+
+// Recorder.
+template <typename I>
+struct recorder
+{
+ void reading(const I&, const mln_psite(I)&) const
+ {
+ // N/A.
+ }
+
+ void writing(I& ima, const mln_psite(I)&, const mln_value(I)&)
+ {
+ sequence.push_back(mln::duplicate(ima));
+ }
+
+ std::vector<I> sequence;
+};
+
+template <typename I>
+mln::decorated_image< I, recorder<I> >
+record(mln::Image<I>& ima)
+{
+ return mln::decorate(ima, recorder<I>());
+}
+
+
+// I/O.
+namespace ppm
+{
+ template <typename I>
+ void
+ save(const mln::decorated_image< I, recorder<I> >& rec,
+ const std::string& prefix)
+ {
+ for (size_t i = 0; i < rec.decoration().sequence.size(); ++i)
+ {
+ std::stringstream s;
+ s << std::setfill ('0') << std::setw (6) << i;
+ mln::io::ppm::save(rec.decoration().sequence[i],
+ prefix + s.str() + ".ppm");
+ }
+ }
+}
+
+
+int main()
+{
+ using namespace mln;
+ using mln::value::rgb8;
+
+ typedef image2d<rgb8> I;
+ I lena = io::ppm::load<rgb8>(MLN_IMG_DIR "/tiny.ppm");
+ decorated_image< I, recorder<I> > lena_rec = record(lena);
+ /* FIXME: Cheat: use generic fill as mln::decorated_image does not
+ define properly its properties. */
+ data::impl::generic::fill_with_value((lena_rec | box2d(point2d(5,5),
+ point2d(10,10))).rw(),
+ literal::green);
+ ppm::save(lena_rec, "lena-roi-fill");
+}
diff --git a/milena/apps/morphers/recorder.cc b/milena/apps/morphers/recorder.cc
new file mode 100644
index 0000000..195f24c
--- /dev/null
+++ b/milena/apps/morphers/recorder.cc
@@ -0,0 +1,135 @@
+// Copyright (C) 2011 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
+/// \brief Morpher recording every change in the morphed image.
+///
+/// To produce an AVI movie from the `lena-fill*.ppm' files, use:
+///
+/// for f in lena-fill*ppm; convert $f -scale 2500% $(basename $f .ppm).png
+/// mencoder "mf://lena-fill*.png" -o lena-fill.avi -ovc lavc -lavcopts
vcodec=mjpeg
+///
+/// The output `lena-fill.avi' can be embedded in a PDF file. */
+
+#include <sstream>
+#include <iomanip>
+
+#include <string>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/imorph/decorated_image.hh>
+
+#include <mln/value/rgb8.hh>
+
+#include <mln/core/routine/duplicate.hh>
+
+#include <mln/literal/colors.hh>
+#include <mln/data/fill.hh>
+
+#include <mln/io/ppm/all.hh>
+
+#include "apps/data.hh"
+
+
+// FIXME: mln::decorated_image lacks a proper definition of
+// properties! (see mln/core/image/imorph/decorated_image.hh
+namespace mln
+{
+
+ namespace trait
+ {
+
+ template <typename I, typename D>
+ struct image_< decorated_image<I,D> >
+ : default_image_morpher< I,
+ mln_value(I),
+ decorated_image<I,D> >
+ {
+ typedef trait::image::category::identity_morpher category;
+ };
+
+ } // end of namespace mln::trait
+
+} // end of namespace mln
+
+
+// Recorder.
+template <typename I>
+struct recorder
+{
+ void reading(const I&, const mln_psite(I)&) const
+ {
+ // N/A.
+ }
+
+ void writing(I& ima, const mln_psite(I)&, const mln_value(I)&)
+ {
+ sequence.push_back(mln::duplicate(ima));
+ }
+
+ std::vector<I> sequence;
+};
+
+template <typename I>
+mln::decorated_image< I, recorder<I> >
+record(mln::Image<I>& ima)
+{
+ return mln::decorate(ima, recorder<I>());
+}
+
+
+// I/O.
+namespace ppm
+{
+ template <typename I>
+ void
+ save(const mln::decorated_image< I, recorder<I> >& rec,
+ const std::string& prefix)
+ {
+ for (size_t i = 0; i < rec.decoration().sequence.size(); ++i)
+ {
+ std::stringstream s;
+ s << std::setfill ('0') << std::setw (6) << i;
+ mln::io::ppm::save(rec.decoration().sequence[i],
+ prefix + s.str() + ".ppm");
+ }
+ }
+}
+
+
+int main()
+{
+ using namespace mln;
+ using mln::value::rgb8;
+
+ typedef image2d<rgb8> I;
+ I lena = io::ppm::load<rgb8>(MLN_IMG_DIR "/tiny.ppm");
+ decorated_image< I, recorder<I> > lena_rec = record(lena);
+ /* FIXME: Cheat: use generic fill as mln::decorated_image does not
+ define properly its properties. */
+ data::impl::generic::fill_with_value(lena_rec,
+ literal::green);
+ ppm::save(lena_rec, "lena-fill");
+}
--
1.7.2.5