URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-09-11 Simon Nivault <simon.nivault(a)lrde.epita.fr>
Optims for erosion and dilation on octagons
* mln/core/win/octagon2d.hh: Well created.
* mln/morpho/dilation.hh: Fill and Optim.
* mln/morpho/erosion.hh: Optim.
* tests/morpho_dilation.cc: New.
* tests/morpho_erosion.cc: Update.
* tests/win_octagon2d.cc: New.
---
mln/core/win/octagon2d.hh | 35 ++++++++++++--
mln/morpho/dilation.hh | 111 +++++++++++++++++++++++++++++++++++++++++++---
mln/morpho/erosion.hh | 31 +++++++++---
tests/morpho_dilation.cc | 100 +++++++++++++++++++++++++++++++++++++++++
tests/morpho_erosion.cc | 12 ++++
tests/win_octagon2d.cc | 48 +++++++++++++++++++
6 files changed, 316 insertions(+), 21 deletions(-)
Index: trunk/milena/tests/win_octagon2d.cc
===================================================================
--- trunk/milena/tests/win_octagon2d.cc (revision 0)
+++ trunk/milena/tests/win_octagon2d.cc (revision 1103)
@@ -0,0 +1,48 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+/*! \file tests/win_octagon2d.cc
+ *
+ * \brief Tests on mln::win::octagon2d.
+ */
+
+#include <mln/core/win/octagon2d.hh>
+
+#include <mln/convert/to_image.hh>
+
+#include <mln/debug/println.hh>
+
+int main()
+{
+ using namespace mln;
+
+ const unsigned l = 13;
+ win::octagon2d oct(l);
+
+ debug::println(convert::to_image(oct));
+}
+
Index: trunk/milena/tests/morpho_erosion.cc
===================================================================
--- trunk/milena/tests/morpho_erosion.cc (revision 1102)
+++ trunk/milena/tests/morpho_erosion.cc (revision 1103)
@@ -32,6 +32,9 @@
#include <mln/core/image2d_b.hh>
#include <mln/core/win/rectangle2d.hh>
+#include <mln/core/win/octagon2d.hh>
+#include <mln/core/win/diag2d.hh>
+#include <mln/core/win/backdiag2d.hh>
#include <mln/core/window2d.hh>
#include <mln/io/pgm/load.hh>
@@ -62,7 +65,14 @@
{
image2d_b<int_u8> out(lena.domain());
morpho::erosion(lena, rec, out);
- io::pgm::save(out, "out.pgm");
+ io::pgm::save(out, "out1.pgm");
+ }
+
+ {
+ win::octagon2d oct(31);
+ image2d_b<int_u8> out(lena.domain());
+ morpho::erosion(lena, oct, out);
+ io::pgm::save(out, "out2.pgm");
}
// {
Index: trunk/milena/tests/morpho_dilation.cc
===================================================================
--- trunk/milena/tests/morpho_dilation.cc (revision 0)
+++ trunk/milena/tests/morpho_dilation.cc (revision 1103)
@@ -0,0 +1,100 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+/*! \file tests/morpho_dilation.cc
+ *
+ * \brief Test on mln::morpho::dilation.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/core/win/rectangle2d.hh>
+#include <mln/core/win/octagon2d.hh>
+#include <mln/core/win/diag2d.hh>
+#include <mln/core/win/backdiag2d.hh>
+#include <mln/core/window2d.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/level/fill.hh>
+#include <mln/morpho/dilation.hh>
+
+#include <mln/pw/value.hh>
+#include <mln/pw/cst.hh>
+#include <mln/fun/ops.hh>
+
+#include <mln/convert/to_vec_p.hh>
+#include <mln/convert/to_window.hh>
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ win::rectangle2d rec(21, 21);
+ border::thickness = 66;
+
+ image2d_b<int_u8> lena = io::pgm::load("../img/lena.pgm");
+
+// {
+// image2d_b<int_u8> out(lena.domain());
+// morpho::dilation(lena, rec, out);
+// io::pgm::save(out, "out1.pgm");
+// }
+
+ {
+ win::octagon2d oct(31);
+ image2d_b<int_u8> out(lena.domain());
+ morpho::dilation(lena, oct, out);
+ io::pgm::save(out, "out2.pgm");
+ }
+
+// {
+// vec_p<point2d> vec = convert::to_vec_p(rec, point2d::zero);
+// window2d win = convert::to_window(vec);
+
+// image2d_b<int_u8> out(lena.domain());
+// level::ero(lena, win, out);
+// morpho::dilation(lena, win, out);
+// io::pgm::save(out, "out.pgm");
+// }
+
+// {
+// image2d_b<bool> bin(lena.domain()), out(lena.domain());
+// level::fill(bin, pw::value(lena) > pw::cst(127));
+// morpho::dilation(bin, rec, out);
+
+// image2d_b<int_u8> test(lena.domain());
+// image2d_b<int_u8>::fwd_piter p(lena.domain());
+// for_all(p)
+// test(p) = out(p) ? 255 : 0;
+// io::pgm::save(test, "test.pgm");
+// }
+
+}
Index: trunk/milena/mln/core/win/octagon2d.hh
===================================================================
--- trunk/milena/mln/core/win/octagon2d.hh (revision 1102)
+++ trunk/milena/mln/core/win/octagon2d.hh (revision 1103)
@@ -48,8 +48,8 @@
/*! \brief Octagon window defined on the 2D square grid.
*
* An octagon2d is centered and symmetrical.
- * The length l of the octagon is such as l = 2*x + 1
- * where x is odd;
+ * The length l of the octagon is such as l = 6*x + 1
+ * where 0 <= x.
*
* For instance: \n
* o o o \n
@@ -59,7 +59,7 @@
* o o o o o o o \n
* o o o o o \n
* o o o \n
- * is defined with length = 7 (x = 3).
+ * is defined with length = 7 (x = 0).
*/
struct octagon2d : public Window< octagon2d >,
public internal::dpoints_base_< dpoint2d, octagon2d >
@@ -88,7 +88,7 @@
*
* \param[in] lenght Length, of the octagon.
*
- * \pre \p length is such as length = 2*x + 1 where x is odd.
+ * \pre \p length is such as length = 6*x + 1 where x >= 0.
*/
octagon2d(unsigned length);
@@ -140,8 +140,31 @@
octagon2d::octagon2d(unsigned length)
: length_(length)
{
- mln_precondition(length % 2 == 1 && (length / 2) % 2 == 1);
- insert(dpoint2d::zero); // FIXME : Do the right insert.
+ mln_precondition(length % 6 == 1);
+ const int y = length / 6;
+ const int x = y * 2;
+ const int z = y + x;
+ insert(dpoint2d::zero);
+ for (int a = 1; a <= x; ++a)
+ for (int b = 0; b <= x; ++b)
+ {
+ insert(make::dpoint2d(a, b));
+ insert(make::dpoint2d(-b, a));
+ insert(make::dpoint2d(b, -a));
+ insert(make::dpoint2d(-a, -b));
+ }
+ for (int a = x + 1; a <= z; ++a)
+ for (int b = -2 * x + a; b <= 2 * x - a; ++b)
+ {
+ insert(make::dpoint2d(a, b));
+ insert(make::dpoint2d(a, -b));
+ insert(make::dpoint2d(-a, b));
+ insert(make::dpoint2d(-a, -b));
+ insert(make::dpoint2d(b, a));
+ insert(make::dpoint2d(b, -a));
+ insert(make::dpoint2d(-b, a));
+ insert(make::dpoint2d(-b, -a));
+ }
}
bool octagon2d::is_centered() const
Index: trunk/milena/mln/morpho/dilation.hh
===================================================================
--- trunk/milena/mln/morpho/dilation.hh (revision 1102)
+++ trunk/milena/mln/morpho/dilation.hh (revision 1103)
@@ -32,17 +32,11 @@
*
* \brief Morphological dilation.
*
- * \todo Mimic erosion.hh when completed.
*/
# include <mln/morpho/includes.hh>
-
-// todo simon
-// this file should be like erosion
-
-
namespace mln
{
@@ -50,6 +44,9 @@
{
/*! Morphological dilation.
+ *
+ * \todo Overload dilation_wrt_win for hline and vline and for fast
+ * images.
*/
template <typename I, typename W, typename O>
void dilation(const Image<I>& input, const Window<W>& win,
Image<O>& output);
@@ -60,6 +57,8 @@
namespace impl
{
+ // On function.
+
template <typename I, typename W, typename O>
void dilation_on_function(const Image<I>& input_, const
Window<W>& win_, Image<O>& output_)
{
@@ -80,6 +79,104 @@
}
}
+ // On set.
+
+ template <typename I, typename W, typename O>
+ void dilation_on_set(const Image<I>& input_, const Window<W>&
win_, Image<O>& output_)
+ {
+ const I& input = exact(input_);
+ const W& win = exact(win_);
+ O& output = exact(output_);
+
+ level::fill(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_qiter(W) q(win, p);
+ for_all(p)
+ if (input(p))
+ for_all(q) if (input.has(q))
+ if (! input(q))
+ {
+ output(p) = true;
+ break;
+ }
+ }
+
+
+ // ...
+
+
+ // FIXME: Stage 3: dispatch w.r.t. fast property
+
+
+ // Stage 2: dispatch w.r.t. the value kind.
+
+ template <typename I, typename W, typename O>
+ void dilation_wrt_value(value::binary_kind, // binary => morphology on sets
+ const Image<I>& input, const Window<W>& win,
Image<O>& output)
+ {
+ return impl::dilation_on_set(exact(input), exact(win), output);
+ }
+
+ template <typename K, typename I, typename W, typename O>
+ void dilation_wrt_value(K, // otherwise => morphology on functions
+ const Image<I>& input, const Window<W>& win,
Image<O>& output)
+ {
+ return impl::dilation_on_function(exact(input), exact(win), output);
+ }
+
+
+
+ // Stage 1: dispatch w.r.t. the window type.
+ // |
+ // V
+
+ template <typename I, typename W, typename O>
+ void dilation_wrt_win(const Image<I>& input, const Window<W>&
win, Image<O>& output)
+ {
+ dilation_wrt_value(mln_value_kind(I)(), exact(input), exact(win), output);
+ // |
+ // --> call stage 2: dispatch w.r.t. the value kind
+ }
+
+# ifdef MLN_CORE_WIN_RECTANGLE2D_HH
+
+ template <typename I, typename O>
+ void dilation_wrt_win(const Image<I>& input, const win::rectangle2d&
win, Image<O>& output)
+ {
+ O temp(exact(output).domain());
+ morpho::dilation(input, win::hline2d(win.width()), temp);
+ morpho::dilation(temp, win::vline2d(win.height()), output);
+ }
+
+# endif // MLN_CORE_WIN_RECTANGLE2D_HH
+
+
+# ifdef MLN_CORE_WIN_OCTAGON2D_HH
+# ifdef MLN_CORE_WIN_DIAG2D_HH
+# ifdef MLN_CORE_WIN_BACKDIAG2D_HH
+
+ template <typename I, typename O>
+ void dilation_wrt_win(const Image<I>& input, const win::octagon2d&
win, Image<O>& output)
+ {
+ const unsigned len = win.length() / 3 + 1;
+
+ O temp1(exact(output).domain());
+ O temp2(exact(output).domain());
+ morpho::dilation(input, win::hline2d(len), temp1);
+ morpho::dilation(temp1, win::vline2d(len), temp2);
+ morpho::dilation(temp2, win::diag2d(len), temp1);
+ morpho::dilation(temp1, win::backdiag2d(len), output);
+ }
+
+# endif // MLN_CORE_WIN_BACKDIAG2D_HH
+# endif // MLN_CORE_WIN_DIAG2D_HH
+# endif // MLN_CORE_WIN_OCTAGON2D_HH
+
+ // ^
+ // |
+ // end of stage1 (dispatch w.r.t. the window type)
+
} // end of namespace mln::morpho::impl
@@ -91,7 +188,7 @@
mln_precondition(exact(output).domain() == exact(input).domain());
mln_precondition(! exact(win).is_empty());
- impl::dilation_on_function(input, win, output);
+ impl::dilation_wrt_win(input, exact(win), output);
if (exact(win).is_centered())
mln_postcondition(output >= input);
Index: trunk/milena/mln/morpho/erosion.hh
===================================================================
--- trunk/milena/mln/morpho/erosion.hh (revision 1102)
+++ trunk/milena/mln/morpho/erosion.hh (revision 1103)
@@ -28,6 +28,12 @@
#ifndef MLN_MORPHO_EROSION_HH
# define MLN_MORPHO_EROSION_HH
+/*! \file mln/morpho/erosion.hh
+ *
+ * \brief Morphological erosion.
+ *
+ */
+
# include <mln/morpho/includes.hh>
@@ -149,15 +155,26 @@
# endif // MLN_CORE_WIN_RECTANGLE2D_HH
-// ifdef MLN_CORE_WIN_RECTANGLE2D_HH
+# ifdef MLN_CORE_WIN_OCTAGON2D_HH
+# ifdef MLN_CORE_WIN_DIAG2D_HH
+# ifdef MLN_CORE_WIN_BACKDIAG2D_HH
-// template <typename I, typename O>
-// void erosion_wrt_win(const Image<I>& input, const win::octagon2d&
win, Image<O>& output)
-// {
-// todo simon
-// }
+ template <typename I, typename O>
+ void erosion_wrt_win(const Image<I>& input, const win::octagon2d&
win, Image<O>& output)
+ {
+ const unsigned len = win.length() / 3 + 1;
+
+ O temp1(exact(output).domain());
+ O temp2(exact(output).domain());
+ morpho::erosion(input, win::hline2d(len), temp1);
+ morpho::erosion(temp1, win::vline2d(len), temp2);
+ morpho::erosion(temp2, win::diag2d(len), temp1);
+ morpho::erosion(temp1, win::backdiag2d(len), output);
+ }
-// endif MLN_CORE_WIN_RECTANGLE2D_HH
+# endif // MLN_CORE_WIN_BACKDIAG2D_HH
+# endif // MLN_CORE_WIN_DIAG2D_HH
+# endif // MLN_CORE_WIN_OCTAGON2D_HH
// ^
// |