Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- 9625 discussions
* tests/core/alias/dpoint2d.cc: Exercise the substraction of a
dpoint2d from a point2d.
* tests/core/alias/neighb2d.cc: New.
* tests/core/alias/Makefile.am (check_PROGRAMS): Add neighb2d.
(neighb2d_SOURCES): New.
* tests/io/dump/dump.cc: Exercise mln::io::dump::load and
mln::io::dump::save with 3D binary images.
* tests/io/dump/Makefile.am (MOSTLYCLEANFILES):
Add dump-bool-3d.dump
* tests/value/int_u32.cc: New test (known to fail).
* tests/value/Makefile.am (check_PROGRAMS): Add int_u32.
(int_u32_SOURCES): New.
(XFAIL_TESTS): New.
Add int_u32.
---
milena/ChangeLog | 19 +++++++++++
milena/tests/core/alias/Makefile.am | 5 ++-
milena/tests/core/alias/dpoint2d.cc | 4 ++-
.../tests/core/alias/{window2d.cc => neighb2d.cc} | 27 +++++++++------
milena/tests/io/dump/Makefile.am | 7 ++--
milena/tests/io/dump/dump.cc | 35 +++++++++++++++++++-
milena/tests/value/Makefile.am | 6 +++-
milena/tests/value/{float01_f.cc => int_u32.cc} | 15 ++++----
8 files changed, 93 insertions(+), 25 deletions(-)
copy milena/tests/core/alias/{window2d.cc => neighb2d.cc} (74%)
copy milena/tests/value/{float01_f.cc => int_u32.cc} (81%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index f329d34..632bacd 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,24 @@
2011-07-12 Roland Levillain <roland(a)lrde.epita.fr>
+ Add more tests.
+
+ * tests/core/alias/dpoint2d.cc: Exercise the substraction of a
+ dpoint2d from a point2d.
+ * tests/core/alias/neighb2d.cc: New.
+ * tests/core/alias/Makefile.am (check_PROGRAMS): Add neighb2d.
+ (neighb2d_SOURCES): New.
+ * tests/io/dump/dump.cc: Exercise mln::io::dump::load and
+ mln::io::dump::save with 3D binary images.
+ * tests/io/dump/Makefile.am (MOSTLYCLEANFILES):
+ Add dump-bool-3d.dump
+ * tests/value/int_u32.cc: New test (known to fail).
+ * tests/value/Makefile.am (check_PROGRAMS): Add int_u32.
+ (int_u32_SOURCES): New.
+ (XFAIL_TESTS): New.
+ Add int_u32.
+
+2011-07-12 Roland Levillain <roland(a)lrde.epita.fr>
+
* apps/generic-skel/image3d-skel.hh: Add `inline' qualifiers.
2011-07-11 Roland Levillain <roland(a)lrde.epita.fr>
diff --git a/milena/tests/core/alias/Makefile.am b/milena/tests/core/alias/Makefile.am
index 9c47da2..de78866 100644
--- a/milena/tests/core/alias/Makefile.am
+++ b/milena/tests/core/alias/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.
#
@@ -23,6 +24,7 @@ box3d \
dpoint1d \
dpoint2d \
dpoint3d \
+neighb2d \
point1d \
point2d \
point3d \
@@ -39,6 +41,7 @@ box3d_SOURCES = box3d.cc
dpoint1d_SOURCES = dpoint1d.cc
dpoint2d_SOURCES = dpoint2d.cc
dpoint3d_SOURCES = dpoint3d.cc
+neighb2d_SOURCES = neighb2d.cc
point1d_SOURCES = point1d.cc
point2d_SOURCES = point2d.cc
point3d_SOURCES = point3d.cc
diff --git a/milena/tests/core/alias/dpoint2d.cc b/milena/tests/core/alias/dpoint2d.cc
index 3accb81..07623c9 100644
--- a/milena/tests/core/alias/dpoint2d.cc
+++ b/milena/tests/core/alias/dpoint2d.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -40,6 +41,7 @@ int main()
mln_assertion(dp == q - p);
mln_assertion(q == p + dp);
+ mln_assertion(p == q - dp);
algebra::vec<2, float> v = dp;
mln_assertion(v[0] / 2 == 1.5);
diff --git a/milena/tests/core/alias/window2d.cc b/milena/tests/core/alias/neighb2d.cc
similarity index 74%
copy from milena/tests/core/alias/window2d.cc
copy to milena/tests/core/alias/neighb2d.cc
index 8940321..3590d90 100644
--- a/milena/tests/core/alias/window2d.cc
+++ b/milena/tests/core/alias/neighb2d.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -23,7 +24,10 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#include <mln/core/alias/window2d.hh>
+/// \file
+/// \brief Exercise mln::neighb2d.
+
+#include <mln/core/alias/neighb2d.hh>
#include <mln/convert/to_image.hh>
@@ -31,19 +35,20 @@ int main()
{
using namespace mln;
- window2d w;
-
- mln_assertion(w.is_centered() == false);
- mln_assertion(w.is_symmetric() == true);
+ neighb2d nbh;
- w .insert(-1,-1)
- .insert( 1, 1);
+ bool vals[] = { 0, 1, 0,
+ 1, 0, 1,
+ 0, 1, 0 };
+ convert::from_to(vals, nbh);
- mln_assertion(w.delta() == 1);
+ mln_assertion(nbh.delta() == 1);
+ mln_assertion(nbh.size() == 4);
+ mln_assertion(nbh == c4());
// The code below is equivalent to:
// image2d<bool> ima;
- // convert::from_to(w, ima);
- image2d<bool> ima = convert::to_image(w);
+ // convert::from_to(nbh, ima);
+ image2d<bool> ima = convert::to_image(nbh);
(void) ima;
}
diff --git a/milena/tests/io/dump/Makefile.am b/milena/tests/io/dump/Makefile.am
index dedd818..38cb55d 100644
--- a/milena/tests/io/dump/Makefile.am
+++ b/milena/tests/io/dump/Makefile.am
@@ -1,4 +1,5 @@
-# Copyright (C) 2009, 2010 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+# Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -16,8 +17,7 @@
include $(top_srcdir)/milena/tests/tests.mk
-check_PROGRAMS = \
- dump
+check_PROGRAMS = dump
dump_SOURCES = dump.cc
@@ -25,6 +25,7 @@ TESTS = $(check_PROGRAMS)
MOSTLYCLEANFILES = \
dump-bool.dump \
+ dump-bool-3d.dump \
dump-float.dump \
dump-int_u8.dump \
dump-rgb8.dump \
diff --git a/milena/tests/io/dump/dump.cc b/milena/tests/io/dump/dump.cc
index f8b8f66..780c2b8 100644
--- a/milena/tests/io/dump/dump.cc
+++ b/milena/tests/io/dump/dump.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -23,7 +24,15 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+/// \brief Exercise mln::io::dump::load and mln::io::dump::save.
+
#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/make/image3d.hh>
+
+#include <mln/debug/println.hh>
+
#include <mln/io/dump/load.hh>
#include <mln/io/dump/save.hh>
@@ -36,6 +45,7 @@
#include <mln/debug/println.hh>
+
int main()
{
using namespace mln;
@@ -57,6 +67,29 @@ int main()
mln_assertion(pic == pic2);
}
+ /// Value: bool (in 3D).
+ {
+ bool data[4] = { 0, 1,
+ 1, 0 };
+ image2d<bool> slice = make::image2d(data);
+
+ // Create a 3D image where each slice is a copy of SLICE.
+ util::array< image2d<bool> > slices;
+ for (unsigned i = 0; i < 3; ++i)
+ slices.append(slice);
+ image3d<bool> pic = make::image3d(slices);
+
+ debug::println(pic);
+
+ io::dump::save(pic, "dump-bool-3d.dump");
+
+ image3d<bool> pic2;
+ io::dump::load(pic2, "dump-bool-3d.dump");
+
+ mln_assertion(pic.domain() == pic2.domain());
+ mln_assertion(pic == pic2);
+ }
+
/// Value: int_u8
{
value::int_u8 data[4] = { 5, 1,
diff --git a/milena/tests/value/Makefile.am b/milena/tests/value/Makefile.am
index 975d471..4b03bab 100644
--- a/milena/tests/value/Makefile.am
+++ b/milena/tests/value/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+# Copyright (C) 2007, 2008, 2009, 2011 EPITA Research and Development
# Laboratory (LRDE).
#
# This file is part of Olena.
@@ -28,6 +28,7 @@ check_PROGRAMS = \
int_s \
int_s16 \
int_u8 \
+ int_u32 \
interop \
label \
proxy \
@@ -51,6 +52,7 @@ equiv_SOURCES = equiv.cc
int_s_SOURCES = int_s.cc
int_s16_SOURCES = int_s16.cc
int_u8_SOURCES = int_u8.cc
+int_u32_SOURCES = int_u32.cc
interop_SOURCES = interop.cc
label_SOURCES = label.cc
proxy_SOURCES = proxy.cc
@@ -59,6 +61,8 @@ scalar_SOURCES = scalar.cc
set_SOURCES = set.cc
sign_SOURCES = sign.cc
+XFAIL_TESTS = int_u32
+
#<<lrde
# FIXME: Not distributed (yet).
check_PROGRAMS += stack
diff --git a/milena/tests/value/float01_f.cc b/milena/tests/value/int_u32.cc
similarity index 81%
copy from milena/tests/value/float01_f.cc
copy to milena/tests/value/int_u32.cc
index 7ca1e7a..61eb6e5 100644
--- a/milena/tests/value/float01_f.cc
+++ b/milena/tests/value/int_u32.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -23,14 +23,15 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+/// \brief Exercise mln::value::int_u32.
+
#include <iostream>
-#include <mln/value/float01_f.hh>
+#include <mln/value/int_u32.hh>
int main()
{
- using mln::value::float01_f;
-
- float01_f x = 0.5;
- std::cout << x + 21.25 << std::endl;
- x = x + 34;
+ // FIXME: This traits return `-1'.
+ std::cerr << mln::trait::value_<mln::value::int_u<32u> >::max()
+ << std::endl;
}
--
1.7.2.5
1
0
last-svn-commit-281-g03fc660 Fix and improve the (fast) computation of 2D connectivity numbers.
by Roland Levillain 15 Jun '12
by Roland Levillain 15 Jun '12
15 Jun '12
* mln/topo/is_simple_2d.hh (mln::connectivity_number_2d): Create
the configuration number by considering that the first (resp.
last) neighbors (in the forward browsing order) represent the
least (resp. most) significant bits of the configuration number,
as does the algorithm that computed the 8-c and 4-c LUTs (arrays
mln::connectivity_number_c8 and mln::connectivity_number_c4).
* mln/topo/connectivity_number_2d.hh: New.
* mln/topo/is_simple_point2d.hh: Fix dates in copyright header.
* tests/topo/connectivity_numbers_2d.cc: New.
* tests/topo/Makefile.am (check_PROGRAMS):
Add connectivity_numbers_2d.
(connectivity_numbers_2d_SOURCES): New.
---
milena/ChangeLog | 17 +++
milena/mln/topo/connectivity_number_2d.hh | 130 ++++++++++++++++++++
milena/mln/topo/is_simple_2d.hh | 17 ++-
milena/mln/topo/is_simple_point2d.hh | 2 +-
milena/tests/topo/Makefile.am | 5 +
.../topo/connectivity_numbers_2d.cc} | 94 +++++++-------
6 files changed, 212 insertions(+), 53 deletions(-)
create mode 100644 milena/mln/topo/connectivity_number_2d.hh
copy milena/{sandbox/lazzara/afp/micro_films/keep_background.cc => tests/topo/connectivity_numbers_2d.cc} (51%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 632bacd..1df7452 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,22 @@
2011-07-12 Roland Levillain <roland(a)lrde.epita.fr>
+ Fix and improve the (fast) computation of 2D connectivity numbers.
+
+ * mln/topo/is_simple_2d.hh (mln::connectivity_number_2d): Create
+ the configuration number by considering that the first (resp.
+ last) neighbors (in the forward browsing order) represent the
+ least (resp. most) significant bits of the configuration number,
+ as does the algorithm that computed the 8-c and 4-c LUTs (arrays
+ mln::connectivity_number_c8 and mln::connectivity_number_c4).
+ * mln/topo/connectivity_number_2d.hh: New.
+ * mln/topo/is_simple_point2d.hh: Fix dates in copyright header.
+ * tests/topo/connectivity_numbers_2d.cc: New.
+ * tests/topo/Makefile.am (check_PROGRAMS):
+ Add connectivity_numbers_2d.
+ (connectivity_numbers_2d_SOURCES): New.
+
+2011-07-12 Roland Levillain <roland(a)lrde.epita.fr>
+
Add more tests.
* tests/core/alias/dpoint2d.cc: Exercise the substraction of a
diff --git a/milena/mln/topo/connectivity_number_2d.hh b/milena/mln/topo/connectivity_number_2d.hh
new file mode 100644
index 0000000..221ca26
--- /dev/null
+++ b/milena/mln/topo/connectivity_number_2d.hh
@@ -0,0 +1,130 @@
+// 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.
+
+#ifndef MLN_TOPO_CONNECTIVITY_NUMBER_2D_HH
+# define MLN_TOPO_CONNECTIVITY_NUMBER_2D_HH
+
+/// \file
+/// \brief 2D connectivity numbers computation.
+
+# include <mln/core/concept/image.hh>
+
+# include <mln/core/alias/neighb2d.hh>
+
+# include <mln/value/int_u8.hh>
+
+// FIXME: This file includes the routine mln::connectivity_number_2d,
+// which should be moved into its own file.
+# include <mln/topo/is_simple_2d.hh>
+
+
+// FIXME: This implementation used the LUT-based (mask-based)
+// computation of 2D connectivity numbers, which may is fast but may
+// be inexact on the border of an image. We shoud rename these
+// routines with a `_fast' suffix.
+
+namespace mln
+{
+
+ namespace topo
+ {
+
+ /** Type of a connectivity number.
+
+ Note: The maximun number of connected components in the
+ neighborhood of a point is necessarily lower or equal to half
+ the number of neighbors. This number fits on an
+ mln::value::int_u8 when the dimension is lower or equal to
+ 5. */
+ typedef mln::value::int_u8 conn_number_t;
+
+
+ /** Compute the 2D connectivity number of \a p within \a ima
+ according to the 4-connectivity. If \a ref_val is set to \c
+ true, compute the number w.r.t. the foreground, otherwise
+ compute it w.r.t. the background.
+
+ \param ima The image on which the connectivity number is
+ computed.
+ \param p The site the connectivity number of which is
+ computed.
+ \param ref_val The reference value, telling whether the
+ foreground (true) or the background (false) is
+ considered. */
+ template<typename I>
+ conn_number_t
+ connectivity_number_2d_c4(const Image<I>& ima, const mln_psite(I)& p,
+ bool ref_val);
+
+ /** Compute the 2D connectivity number of \a p within \a ima
+ according to the 8-connectivity. If \a ref_val is set to \c
+ true, compute the number w.r.t. the foreground, otherwise
+ compute it w.r.t. the background.
+
+ \param ima The image on which the connectivity number is
+ computed.
+ \param p The site the connectivity number of which is
+ computed.
+ \param ref_val The reference value, telling whether the
+ foreground (true) or the background (false) is
+ considered. */
+ template<typename I>
+ conn_number_t
+ connectivity_number_2d_c8(const Image<I>& ima, const mln_psite(I)& p,
+ bool ref_val);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template<typename I>
+ conn_number_t
+ connectivity_number_2d_c4(const Image<I>& ima, const mln_psite(I)& p,
+ bool ref_val)
+ {
+ // Create a copy of mln::c4()'s own neighborhood to avoid
+ // thread-unsafe accesses to this neighborhood.
+ neighb2d nbh = c4();
+ return mln::connectivity_number_2d(ima, nbh, p, ref_val);
+ }
+
+ template<typename I>
+ conn_number_t
+ connectivity_number_2d_c8(const Image<I>& ima, const mln_psite(I)& p,
+ bool ref_val)
+ {
+ // Create a copy of mln::c8()'s own neighborhood to avoid
+ // thread-unsafe accesses to this neighborhood.
+ neighb2d nbh = c8();
+ return mln::connectivity_number_2d(ima, nbh, p, ref_val);
+ }
+
+# endif // MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::topo
+
+} // end of namespace mln
+
+#endif // ! MLN_TOPO_CONNECTIVITY_NUMBER_2D_HH
diff --git a/milena/mln/topo/is_simple_2d.hh b/milena/mln/topo/is_simple_2d.hh
index 18ffe78..f93bc7c 100644
--- a/milena/mln/topo/is_simple_2d.hh
+++ b/milena/mln/topo/is_simple_2d.hh
@@ -1,4 +1,4 @@
-// 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.
//
@@ -139,13 +139,18 @@ namespace mln
const N& nbh = exact(nbh_);
unsigned res = 0;
+ unsigned mask = 1;
mln_fwd_niter(neighb2d) n(c8(), p);
for_all(n)
- {
- res = (res << 1);
- if (ima.has(n) && ima(n) == b)
- res = res | 1;
- }
+ {
+ /* FIXME: The `ima.has(n)' predicate is not meaningful, as the
+ computation below is wrong as soon as `p' has a number of
+ neighbors other than 8. We should instead abort or warn if
+ for any `n' we don't have `ima.has(n)'. */
+ if (ima.has(n) && ima(n) == b)
+ res = res | mask;
+ mask = mask << 1;
+ }
unsigned number;
if (nbh == c4())
diff --git a/milena/mln/topo/is_simple_point2d.hh b/milena/mln/topo/is_simple_point2d.hh
index 219789e..8d0d7dd 100644
--- a/milena/mln/topo/is_simple_point2d.hh
+++ b/milena/mln/topo/is_simple_point2d.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2010, 2011 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
diff --git a/milena/tests/topo/Makefile.am b/milena/tests/topo/Makefile.am
index 608ac92..d9d2096 100644
--- a/milena/tests/topo/Makefile.am
+++ b/milena/tests/topo/Makefile.am
@@ -19,13 +19,18 @@ include $(top_srcdir)/milena/tests/tests.mk
SUBDIRS = skeleton
+## FIXME: Also add tests for is_simple_cell, detach_cell,
+## is_simple_point2d and detach_point.
+
check_PROGRAMS = \
complex \
+ connectivity_numbers_2d \
detach_pair \
is_facet \
is_simple_pair
complex_SOURCES = complex.cc
+connectivity_numbers_2d_SOURCES = connectivity_numbers_2d.cc
detach_pair_SOURCES = detach_pair.cc
is_facet_SOURCES = is_facet.cc
is_simple_pair_SOURCES = is_simple_pair.cc
diff --git a/milena/sandbox/lazzara/afp/micro_films/keep_background.cc b/milena/tests/topo/connectivity_numbers_2d.cc
similarity index 51%
copy from milena/sandbox/lazzara/afp/micro_films/keep_background.cc
copy to milena/tests/topo/connectivity_numbers_2d.cc
index 78373ad..599c02a 100644
--- a/milena/sandbox/lazzara/afp/micro_films/keep_background.cc
+++ b/milena/tests/topo/connectivity_numbers_2d.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.
//
@@ -23,63 +23,65 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-
/// \file
-///
-/// Keep the background from a binary image.
+/// \brief Exercise the fast (LUT-based) computation of 2D
+/// connectivity numbers.
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/neighb2d.hh>
+#include <mln/make/box2d.hh>
-#include <mln/pw/all.hh>
-#include <mln/core/image/dmorph/image_if.hh>
+#include <mln/topo/connectivity_number_2d.hh>
#include <mln/data/fill.hh>
-#include <mln/io/pbm/all.hh>
-#include <mln/labeling/blobs.hh>
#include <mln/logical/not.hh>
-#include <mln/value/label_16.hh>
-
-#include <tools/usage.hh>
-
-
-const char *args_desc[][2] =
-{
- { "input.pbm", "A binary image. Objects are set to 'true'." },
- { 0, 0 }
-};
-
-
-int main(int argc, char *argv[])
+int
+main()
{
using namespace mln;
- if (argc != 3)
- return tools::usage(argv,
- "Extract the background from a binary image.",
- "input.pbm output.pbm",
- args_desc, "A binary image. Background is set to 'false'.");
-
- image2d<bool> input;
- io::pbm::load(input, argv[1]);
-
- logical::not_inplace(input);
-
- typedef value::label_16 V;
- V nlabels;
- image2d<V> lbl = labeling::blobs(input, c8(), nlabels);
-
- image2d<bool> output;
- initialize(output, input);
-
- V bg_lbl = lbl(literal::origin);
-
- data::fill(output, false);
- data::fill((output | (pw::value(lbl) == pw::cst(bg_lbl))).rw(), true);
-
- io::pbm::save(output, argv[2]);
+ // Exercise the computation of 2D connectivity numbers using the
+ // look-up table.
+ box2d b = make::box2d(-1, -1,
+ +1, +1);
+ image2d<bool> ima(b);
+ data::fill(ima, false);
+
+ point2d p(0, 0);
+ mln_niter_(neighb2d) n(c4(), p);
+ for_all(n)
+ ima(n) = true;
+ /* Test case 1.
+ ima =
+
+ - | -
+ | - |
+ - | -
+ */
+ mln_assertion(topo::connectivity_number_2d_c4(ima, p, true) == 4);
+ mln_assertion(topo::connectivity_number_2d_c8(ima, p, true) == 1);
+
+ logical::not_inplace(ima);
+ ima.at_ (0, 0) = false;
+ /* Test case 2.
+ ima =
+
+ | - |
+ - - -
+ | - |
+ */
+ mln_assertion(topo::connectivity_number_2d_c4(ima, p, true) == 0);
+ mln_assertion(topo::connectivity_number_2d_c8(ima, p, true) == 4);
+
+
+ /* FIXME: Also exercise the direct computation of connectivity
+ numbers, using the number of connected components around the
+ point in the foreground and the background.
+
+ Possibly move this part in another test, especially if the
+ corresponding routine is located in another file. */
+ // ...
}
-
--
1.7.2.5
1
0
last-svn-commit-282-g3351dd9 Check the consistency of tools/simple_point3d_lut_26_6.hh.
by Roland Levillain 15 Jun '12
by Roland Levillain 15 Jun '12
15 Jun '12
* tools/simple_point3d_lut_26_6.cc: New.
* tools/test_simple_point3d_lut_26_6.cc: New.
* tools/tools.mk (AM_CPPFLAGS): Add -I$(top_builddir)/milena.
* tools/Makefile.am (noinst_LTLIBRARIES): New.
Add libsimple_point3d_lut_26_6.la.
(libsimple_point3d_lut_26_6_la_SOURCES): New.
(EXTRA_PROGRAMS): Add test_simple_point3d_lut_26_6.
(test_simple_point3d_lut_26_6_SOURCES)
(test_simple_point3d_lut_26_6_LDADD):
New.
---
milena/ChangeLog | 15 ++
milena/tools/Makefile.am | 10 ++
.../simple_point3d_lut_26_6.cc} | 13 +--
milena/tools/test_simple_point3d_lut_26_6.cc | 136 ++++++++++++++++++++
milena/tools/tools.mk | 6 +-
5 files changed, 168 insertions(+), 12 deletions(-)
copy milena/{tests/value/int_u32.cc => tools/simple_point3d_lut_26_6.cc} (84%)
create mode 100644 milena/tools/test_simple_point3d_lut_26_6.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 1df7452..9c667b6 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,20 @@
2011-07-12 Roland Levillain <roland(a)lrde.epita.fr>
+ Check the consistency of tools/simple_point3d_lut_26_6.hh.
+
+ * tools/simple_point3d_lut_26_6.cc: New.
+ * tools/test_simple_point3d_lut_26_6.cc: New.
+ * tools/tools.mk (AM_CPPFLAGS): Add -I$(top_builddir)/milena.
+ * tools/Makefile.am (noinst_LTLIBRARIES): New.
+ Add libsimple_point3d_lut_26_6.la.
+ (libsimple_point3d_lut_26_6_la_SOURCES): New.
+ (EXTRA_PROGRAMS): Add test_simple_point3d_lut_26_6.
+ (test_simple_point3d_lut_26_6_SOURCES)
+ (test_simple_point3d_lut_26_6_LDADD):
+ New.
+
+2011-07-12 Roland Levillain <roland(a)lrde.epita.fr>
+
Fix and improve the (fast) computation of 2D connectivity numbers.
* mln/topo/is_simple_2d.hh (mln::connectivity_number_2d): Create
diff --git a/milena/tools/Makefile.am b/milena/tools/Makefile.am
index b93d92b..6caec62 100644
--- a/milena/tools/Makefile.am
+++ b/milena/tools/Makefile.am
@@ -73,3 +73,13 @@ simple_point3d_lut_26_6.hh: simple_point3d_lut_26_6.txt $(srcdir)/gen_cxx_lut
rm -f $@.tmp
$(srcdir)/gen_cxx_lut simple_point3d_lut_26_6 "(26, 6)" <$< >$@.tmp
mv $@.tmp $@
+
+# Very long (both to compile and execute) optional test, checking the
+# consistency of the LUT in simple_point3d_lut_26_6.hh. Moreover, it
+# should be turned into a parallel program.
+noinst_LTLIBRARIES = libsimple_point3d_lut_26_6.la
+libsimple_point3d_lut_26_6_la_SOURCES = \
+ simple_point3d_lut_26_6.hh simple_point3d_lut_26_6.cc
+EXTRA_PROGRAMS += test_simple_point3d_lut_26_6
+test_simple_point3d_lut_26_6_SOURCES = test_simple_point3d_lut_26_6.cc
+test_simple_point3d_lut_26_6_LDADD = libsimple_point3d_lut_26_6.la
diff --git a/milena/tests/value/int_u32.cc b/milena/tools/simple_point3d_lut_26_6.cc
similarity index 84%
copy from milena/tests/value/int_u32.cc
copy to milena/tools/simple_point3d_lut_26_6.cc
index 61eb6e5..8fb24c6 100644
--- a/milena/tests/value/int_u32.cc
+++ b/milena/tools/simple_point3d_lut_26_6.cc
@@ -24,14 +24,7 @@
// executable file might be covered by the GNU General Public License.
/// \file
-/// \brief Exercise mln::value::int_u32.
+/// \brief A C++ source file to produce a compiled version of
+/// tools/simple_point3d_lut_26_6.hh.
-#include <iostream>
-#include <mln/value/int_u32.hh>
-
-int main()
-{
- // FIXME: This traits return `-1'.
- std::cerr << mln::trait::value_<mln::value::int_u<32u> >::max()
- << std::endl;
-}
+#include <tools/simple_point3d_lut_26_6.hh>
diff --git a/milena/tools/test_simple_point3d_lut_26_6.cc b/milena/tools/test_simple_point3d_lut_26_6.cc
new file mode 100644
index 0000000..c3afb23
--- /dev/null
+++ b/milena/tools/test_simple_point3d_lut_26_6.cc
@@ -0,0 +1,136 @@
+// 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.
+
+#include <mln/core/image/image3d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/make/box3d.hh>
+
+#include "tools/connectivity_numbers_3d.hh"
+
+// To avoid heavy recompilation times due to the huge size of the
+// look-up table, only fetch the table's declaration. Its
+// implementation is compiled separately and linked to this program.
+#define MLN_INCLUDE_ONLY
+# include "tools/simple_point3d_lut_26_6.hh"
+#undef MLN_INCLUDE_ONLY
+
+
+int
+main()
+{
+ using namespace mln;
+
+ // FIXME: This part is very similar to
+ // milena/tests/topo/connectivity_numbers_2d.cc and
+ // milena/tools/connectivity_numbers_3d.hh. Factor.
+
+ typedef image3d<bool> I;
+ // B must be a model of mln::Box.
+ typedef mln_domain_(I) B;
+ typedef mln_psite_(I) P;
+
+ B b = make::box3d(-1,-1,-1, 1,1,1);
+ I fg_ima(b, 0);
+ I bg_ima(b, 0);
+ P p(0, 0, 0);
+
+ const unsigned dim = 3;
+ const unsigned max_nneighbs = mlc_pow_int(3, dim) - 1;
+ const unsigned nconfigs = mlc_pow_int(2, max_nneighbs);
+
+ typedef neighb3d N;
+ N nbh = c26();
+
+ int exit_status = EXIT_SUCCESS;
+
+ for (config_3d_t i = 0; i < nconfigs; ++i)
+ {
+ /* Create the local i-th configuration around P.
+
+ Note that the value corresponding to P is always `false', to
+ prevent the connection of two components through P. */
+ data::fill(fg_ima, false);
+ data::fill(bg_ima, false);
+ config_3d_t tmp = i;
+ mln_fwd_niter_(N) n(nbh, p);
+ for_all(n)
+ {
+ if (tmp % 2)
+ fg_ima(n) = true;
+ else
+ bg_ima(n) = true;
+ tmp = tmp >> 1;
+ }
+
+ // Compute the simple point criterion for (26, 6)-connectivity
+ conn_number_t conn_number_fg = connectivity_number_3d__26_6_one(fg_ima);
+ conn_number_t conn_number_bg = connectivity_number_3d__6_26_one(bg_ima);
+ bool conn_number_computed = conn_number_fg == 1 &&conn_number_bg == 1;
+
+
+ // Retrieve the simple point criterion for (26, 6)-connectivity
+ // number using the LUT.
+ conn_number_t conn_number_from_lut;
+ {
+ // ``Unpack'' the i-th value.
+
+ // FIXME: Redundant with some code from
+ // mln/topo/is_simple_point3d.hh.
+
+ size_t pos = i;
+
+ /* `simple_point3d_lut_26_6' is a packed bit array. We must
+ first retrieve the cell ``containing'' the index `pos'. */
+ size_t cell = pos / 8;
+ /* FIXME: We use hard-coded neighborhoods here instead of using
+ nbh_fg_ and nbh_bg_ (for this first test version). */
+ unsigned char pack = mln::topo::simple_point3d_lut_26_6[cell];
+
+ /* Compute the position of the neighborhood configuration within
+ the packed set of valued and create a mask corresponding to
+ this position (offset). */
+ size_t offset = pos % 8;
+ unsigned char mask = 1 << offset;
+
+ /* If the pack contains a 1 at position `offset', then `pack &
+ mask' is a non-null value. Otherwise it is zero. We can
+ therefore use it to create a boolean return value. */
+ bool result = pack & mask;
+ conn_number_from_lut = result;
+ }
+
+ // Compare them.
+ if (conn_number_computed != conn_number_from_lut)
+ {
+ std::cout
+ << "Inconsistency for the " << i << "-th configuration: "
+ << conn_number_computed << " != " << conn_number_from_lut
+ << std::endl;
+ exit_status = EXIT_FAILURE;
+ }
+ }
+
+ return exit_status;
+}
diff --git a/milena/tools/tools.mk b/milena/tools/tools.mk
index 9d9a046..878c687 100644
--- a/milena/tools/tools.mk
+++ b/milena/tools/tools.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+# Copyright (C) 2009, 2011 EPITA Research and Development Laboratory (LRDE)
#
# This file is part of Olena.
#
@@ -17,8 +17,10 @@
## FIXME: Revamp (see Olena 0.11's test suite).
-# Look for Milena header in srcdir.
+# Look for Milena headers in srcdir.
AM_CPPFLAGS = -I$(top_srcdir)/milena
+# Look for Milena headers in builddir.
+AM_CPPFLAGS += -I$(top_builddir)/milena
# FIXME: Add
#
--
1.7.2.5
1
0
last-svn-commit-283-gbced3c0 Add a non 1D isthmus predicate for (2D and 3D) binary images.
by Roland Levillain 15 Jun '12
by Roland Levillain 15 Jun '12
15 Jun '12
* mln/topo/is_not_1d_isthmus.hh: New.
* headers.mk, tests/unit_test/unit-tests.mk: Regen.
---
milena/ChangeLog | 7 +
milena/headers.mk | 2 +
milena/mln/topo/is_not_1d_isthmus.hh | 210 ++++++++++++++++++++++++++++++++++
milena/tests/unit_test/unit-tests.mk | 4 +
4 files changed, 223 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/topo/is_not_1d_isthmus.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 9c667b6..8c49faa 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,10 @@
+2011-07-13 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Add a non 1D isthmus predicate for (2D and 3D) binary images.
+
+ * mln/topo/is_not_1d_isthmus.hh: New.
+ * headers.mk, tests/unit_test/unit-tests.mk: Regen.
+
2011-07-12 Roland Levillain <roland(a)lrde.epita.fr>
Check the consistency of tools/simple_point3d_lut_26_6.hh.
diff --git a/milena/headers.mk b/milena/headers.mk
index 4dcc0fc..906bd32 100644
--- a/milena/headers.mk
+++ b/milena/headers.mk
@@ -999,6 +999,7 @@ mln/topo/center_only_iter.hh \
mln/topo/centered_iter_adapter.hh \
mln/topo/complex.hh \
mln/topo/complex_iterators.hh \
+mln/topo/connectivity_number_2d.hh \
mln/topo/connectivity_number_3d.hh \
mln/topo/detach_cell.hh \
mln/topo/detach_pair.hh \
@@ -1013,6 +1014,7 @@ mln/topo/internal/complex_relative_iterator_sequence.hh \
mln/topo/internal/complex_set_iterator_base.hh \
mln/topo/is_facet.hh \
mln/topo/is_n_face.hh \
+mln/topo/is_not_1d_isthmus.hh \
mln/topo/is_not_end_point.hh \
mln/topo/is_simple_2d.hh \
mln/topo/is_simple_cell.hh \
diff --git a/milena/mln/topo/is_not_1d_isthmus.hh b/milena/mln/topo/is_not_1d_isthmus.hh
new file mode 100644
index 0000000..9ed7468
--- /dev/null
+++ b/milena/mln/topo/is_not_1d_isthmus.hh
@@ -0,0 +1,210 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Milena 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.
+
+#ifndef MLN_TOPO_IS_NOT_1D_ISTHMUS_HH
+# define MLN_TOPO_IS_NOT_1D_ISTHMUS_HH
+
+/// \file
+/// \brief Non 1D isthmus predicate for (2D and 3D) binary images.
+
+# include <mln/core/concept/function.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/topo/connectivity_number_2d.hh>
+# include <mln/topo/connectivity_number_3d.hh>
+
+
+namespace mln
+{
+
+ namespace topo
+ {
+
+ template <typename I, typename N>
+ struct is_not_1d_isthmus
+ : public Function_v2b< is_not_1d_isthmus<I, N> >
+ {
+ /// Build a functor.
+ ///
+ /// \param nbh_fg The foreground neighborhood.
+ /// \param nbh_bg The background neighborhood.
+ is_not_1d_isthmus(const Neighborhood<N>& nbh_fg,
+ const Neighborhood<N>& nbh_bg);
+
+ /// Build a functor, and assign an image to it.
+ ///
+ /// \param nbh_fg The foreground neighborhood.
+ /// \param nbh_bg The background neighborhood.
+ /// \apram ima The image.
+ is_not_1d_isthmus(const Neighborhood<N>& nbh_fg,
+ const Neighborhood<N>& nbh_bg,
+ const Image<I>& ima);
+
+ /// Set the underlying image.
+ void set_image(Image<I>& ima);
+
+ // Is \a p not a 1D isthmus point?
+ bool operator()(const mln_psite(I)& p) const;
+
+ private:
+ /// The foreground neighborhood.
+ const N& nbh_fg_;
+ /// The background neighborhood.
+ const N& nbh_bg_;
+ /// The image.
+ const I* ima_;
+
+ /// The type of pointer on function computing a 3D connectivity
+ /// number.
+ typedef conn_number_t (*connectivity_number_fun_t)(const Image<I>&,
+ const mln_psite(I)&,
+ bool);
+ /// The function (pointer) computing the (foreground) connectivity
+ /// number.
+ connectivity_number_fun_t connectivity_number_fg_;
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ /* FIXME: This is way too complicated. Maybe the simplest thing
+ is to create two functors is_not_1d_isthmus_point2d and
+ is_not_1d_isthmus_point3d and factor common parts. */
+ namespace internal
+ {
+
+ template <typename I>
+ struct conn_number_fun
+ {
+ typedef conn_number_t (*connectivity_number_fun_t)(const Image<I>&,
+ const mln_psite(I)&,
+ bool);
+
+ // Default case.
+ template <typename N>
+ static connectivity_number_fun_t get(const N& /* nbh_fg */,
+ const N& /* nbh_bg */)
+ {
+ // We only handle the cases where N is either neighb2d or neighb3d.
+ abort();
+ return 0;
+ }
+
+ // 2D cases.
+ static connectivity_number_fun_t get(const neighb2d& nbh_fg,
+ const neighb2d& nbh_bg)
+ {
+ // 2D neighborhoods.
+ if (nbh_fg == c4() && nbh_bg == c8())
+ return connectivity_number_2d_c4<I>;
+ else if (nbh_fg == c8() && nbh_bg == c4())
+ return connectivity_number_2d_c8<I>;
+ else
+ {
+ // Bad or unknown combination.
+ abort();
+ return 0;
+ }
+ }
+
+ // 3D cases.
+ static connectivity_number_fun_t get(const neighb3d& nbh_fg,
+ const neighb3d& nbh_bg)
+ {
+ // 3D neighborhoods.
+ if (nbh_fg == c6() && nbh_bg == c26())
+ return connectivity_number_3d_c6<I>;
+ else if (nbh_fg == c26() && nbh_bg == c6())
+ return connectivity_number_3d_c26<I>;
+ else if (nbh_fg == c6() && nbh_bg == c18())
+ return connectivity_number_3d_c6p<I>;
+ else if (nbh_fg == c18() && nbh_bg == c6())
+ return connectivity_number_3d_c18<I>;
+ else
+ {
+ // Bad or unknown combination.
+ abort();
+ return 0;
+ }
+ }
+
+ };
+
+
+ } // end of namespace mln::io::topo::internal
+
+
+ template <typename I, typename N>
+ inline
+ is_not_1d_isthmus<I, N>::is_not_1d_isthmus(const Neighborhood<N>& nbh_fg,
+ const Neighborhood<N>& nbh_bg)
+ : nbh_fg_(exact(nbh_fg)),
+ nbh_bg_(exact(nbh_bg)),
+ connectivity_number_fg_(internal::conn_number_fun<I>::get(nbh_fg_,
+ nbh_bg_))
+ {
+ }
+
+ template <typename I, typename N>
+ inline
+ is_not_1d_isthmus<I, N>::is_not_1d_isthmus(const Neighborhood<N>& nbh_fg,
+ const Neighborhood<N>& nbh_bg,
+ const Image<I>& ima)
+ : nbh_fg_(exact(nbh_fg)),
+ nbh_bg_(exact(nbh_bg)),
+ ima_(exact(&ima)),
+ connectivity_number_fg_(internal::conn_number_fun<I>::get(nbh_fg_,
+ nbh_bg_))
+ {
+ }
+
+ template <typename I, typename N>
+ inline
+ void
+ is_not_1d_isthmus<I, N>::set_image(Image<I>& ima)
+ {
+ ima_ = exact(&ima);
+ }
+
+ template <typename I, typename N>
+ inline
+ bool
+ is_not_1d_isthmus<I, N>::operator()(const mln_psite(I)& p) const
+ {
+ mln_precondition(ima_);
+ return connectivity_number_fg_(*ima_, p, true) < 2;
+ }
+
+# endif // MLN_INCLUDE_ONLY
+
+ } // end of namespace topo
+
+} // end of namespace mln
+
+#endif // ! MLN_TOPO_IS_NOT_1D_ISTHMUS_HH
diff --git a/milena/tests/unit_test/unit-tests.mk b/milena/tests/unit_test/unit-tests.mk
index 12795ff..b589365 100644
--- a/milena/tests/unit_test/unit-tests.mk
+++ b/milena/tests/unit_test/unit-tests.mk
@@ -1029,6 +1029,7 @@ mln_topo_center_only_iter \
mln_topo_centered_iter_adapter \
mln_topo_complex \
mln_topo_complex_iterators \
+mln_topo_connectivity_number_2d \
mln_topo_connectivity_number_3d \
mln_topo_detach_cell \
mln_topo_detach_pair \
@@ -1043,6 +1044,7 @@ mln_topo_internal_complex_relative_iterator_sequence \
mln_topo_internal_complex_set_iterator_base \
mln_topo_is_facet \
mln_topo_is_n_face \
+mln_topo_is_not_1d_isthmus \
mln_topo_is_not_end_point \
mln_topo_is_simple_2d \
mln_topo_is_simple_cell \
@@ -2340,6 +2342,7 @@ mln_topo_center_only_iter_SOURCES = mln_topo_center_only_iter.cc
mln_topo_centered_iter_adapter_SOURCES = mln_topo_centered_iter_adapter.cc
mln_topo_complex_SOURCES = mln_topo_complex.cc
mln_topo_complex_iterators_SOURCES = mln_topo_complex_iterators.cc
+mln_topo_connectivity_number_2d_SOURCES = mln_topo_connectivity_number_2d.cc
mln_topo_connectivity_number_3d_SOURCES = mln_topo_connectivity_number_3d.cc
mln_topo_detach_cell_SOURCES = mln_topo_detach_cell.cc
mln_topo_detach_pair_SOURCES = mln_topo_detach_pair.cc
@@ -2354,6 +2357,7 @@ mln_topo_internal_complex_relative_iterator_sequence_SOURCES = mln_topo_internal
mln_topo_internal_complex_set_iterator_base_SOURCES = mln_topo_internal_complex_set_iterator_base.cc
mln_topo_is_facet_SOURCES = mln_topo_is_facet.cc
mln_topo_is_n_face_SOURCES = mln_topo_is_n_face.cc
+mln_topo_is_not_1d_isthmus_SOURCES = mln_topo_is_not_1d_isthmus.cc
mln_topo_is_not_end_point_SOURCES = mln_topo_is_not_end_point.cc
mln_topo_is_simple_2d_SOURCES = mln_topo_is_simple_2d.cc
mln_topo_is_simple_cell_SOURCES = mln_topo_is_simple_cell.cc
--
1.7.2.5
1
0
last-svn-commit-284-g7633d6b Exercise breadth-first thinning with predicate is_not_1d_isthmus.
by Roland Levillain 15 Jun '12
by Roland Levillain 15 Jun '12
15 Jun '12
* apps/generic-skel/image3d-skel-with-1d-isthmuses.cc: New.
* apps/generic-skel/Makefile.am (bin_PROGRAMS):
Add image3d-skel-with-1d-isthmuses.
(image3d_skel_with_1d_isthmuses_SOURCES): New.
(TESTS): Add image3d-skel-with-1d-isthmuses.
(MOSTLYCLEANFILES): Add
image3d-skel-with-1d-isthmuses-input.raw,
image3d-skel-with-1d-isthmuses-input.vtk,
image3d-skel-with-1d-isthmuses-skel.raw and
image3d-skel-with-1d-isthmuses-skel.vtk.
---
milena/ChangeLog | 15 +++++++++++++++
milena/apps/generic-skel/Makefile.am | 13 ++++++++++---
...points.cc => image3d-skel-with-1d-isthmuses.cc} | 16 ++++++++--------
3 files changed, 33 insertions(+), 11 deletions(-)
copy milena/apps/generic-skel/{image3d-skel-with-end-points.cc => image3d-skel-with-1d-isthmuses.cc} (88%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 8c49faa..3e2adbf 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,20 @@
2011-07-13 Roland Levillain <roland(a)lrde.epita.fr>
+ Exercise breadth-first thinning with predicate is_not_1d_isthmus.
+
+ * apps/generic-skel/image3d-skel-with-1d-isthmuses.cc: New.
+ * apps/generic-skel/Makefile.am (bin_PROGRAMS):
+ Add image3d-skel-with-1d-isthmuses.
+ (image3d_skel_with_1d_isthmuses_SOURCES): New.
+ (TESTS): Add image3d-skel-with-1d-isthmuses.
+ (MOSTLYCLEANFILES): Add
+ image3d-skel-with-1d-isthmuses-input.raw,
+ image3d-skel-with-1d-isthmuses-input.vtk,
+ image3d-skel-with-1d-isthmuses-skel.raw and
+ image3d-skel-with-1d-isthmuses-skel.vtk.
+
+2011-07-13 Roland Levillain <roland(a)lrde.epita.fr>
+
Add a non 1D isthmus predicate for (2D and 3D) binary images.
* mln/topo/is_not_1d_isthmus.hh: New.
diff --git a/milena/apps/generic-skel/Makefile.am b/milena/apps/generic-skel/Makefile.am
index ad89544..961fef2 100644
--- a/milena/apps/generic-skel/Makefile.am
+++ b/milena/apps/generic-skel/Makefile.am
@@ -29,7 +29,8 @@ bin_PROGRAMS = \
image2d-skel-with-end-points \
\
image3d-skel-unconstrained \
- image3d-skel-with-end-points
+ image3d-skel-with-end-points \
+ image3d-skel-with-1d-isthmuses
# 2D cases.
image2d_skel_unconstrained_SOURCES = image2d-skel-unconstrained.cc image2d-skel.hh
@@ -37,8 +38,9 @@ image2d_skel_with_end_points_SOURCES = image2d-skel-with-end-points.cc image2d-s
# 3D cases, slow versions.
noinst_HEADERS = image3d-skel.hh
-image3d_skel_with_end_points_SOURCES = image3d-skel-with-end-points.cc
image3d_skel_unconstrained_SOURCES = image3d-skel-unconstrained.cc
+image3d_skel_with_end_points_SOURCES = image3d-skel-with-end-points.cc
+image3d_skel_with_1d_isthmuses_SOURCES = image3d-skel-with-1d-isthmuses.cc
EXTRA_DIST = \
test-image2d-skel-unconstrained.in \
@@ -74,7 +76,8 @@ TESTS = $(generated_tests)
# FIXME: Create real test cases with inputs passed as argument.
TESTS += \
image3d-skel-unconstrained \
- image3d-skel-with-end-points
+ image3d-skel-with-end-points \
+ image3d-skel-with-1d-isthmuses
# FIXME: Rename all outputs to have their names use their generator as prefix.
MOSTLYCLEANFILES = \
@@ -86,6 +89,10 @@ MOSTLYCLEANFILES = \
image3d-skel-with-end-points-input.vtk \
image3d-skel-with-end-points-skel.raw \
image3d-skel-with-end-points-skel.vtk \
+ image3d-skel-with-1d-isthmuses-input.raw \
+ image3d-skel-with-1d-isthmuses-input.vtk \
+ image3d-skel-with-1d-isthmuses-skel.raw \
+ image3d-skel-with-1d-isthmuses-skel.vtk \
picasso-skel-unconstrained.pbm \
picasso-skel-with-end-points.pbm \
tiny-skel-unconstrained.pbm \
diff --git a/milena/apps/generic-skel/image3d-skel-with-end-points.cc b/milena/apps/generic-skel/image3d-skel-with-1d-isthmuses.cc
similarity index 88%
copy from milena/apps/generic-skel/image3d-skel-with-end-points.cc
copy to milena/apps/generic-skel/image3d-skel-with-1d-isthmuses.cc
index 32f3634..fc1ad61 100644
--- a/milena/apps/generic-skel/image3d-skel-with-end-points.cc
+++ b/milena/apps/generic-skel/image3d-skel-with-1d-isthmuses.cc
@@ -25,7 +25,7 @@
/// \file
/// \brief A program computing a binary skeleton of a 3D image,
-/// preserving end points.
+/// preserving 1D isthmuses.
#include <fstream>
@@ -44,7 +44,7 @@
#include <mln/topo/is_simple_point3d.hh>
#include <mln/topo/detach_point.hh>
-#include <mln/topo/is_not_end_point.hh>
+#include <mln/topo/is_not_1d_isthmus.hh>
#include "apps/data.hh"
@@ -76,8 +76,8 @@ int main()
I input = make_triple_torus(20);
std::cerr << input.domain() << std::endl;
- save_raw_3d(input, "image3d-skel-with-end-points-input.raw");
- save_vtk_polyhedrons(input, "image3d-skel-with-end-points-input.vtk");
+ save_raw_3d(input, "image3d-skel-with-1d-isthmuses-input.raw");
+ save_vtk_polyhedrons(input, "image3d-skel-with-1d-isthmuses-input.vtk");
// FIXME: Debug.
unsigned n_fg_comps;
@@ -98,17 +98,17 @@ int main()
topo::is_simple_point3d<I, N> is_simple(nbh_fg, nbh_bg);
// Simple point detach procedure.
topo::detach_point<I> detach;
- // Constraint: do not collapse end points.
+ // Constraint: do not remove 1D isthmuses.
/* FIXME: This criterion is static, e.g. it is attached to INPUT
(fixed), not OUTPUT (changing during the thinning). This is not
as good as a dynamic critertion (attached to OUTPUT). Maybe it
is time to introduce/use `breadth_first_thinning_inplace'. */
- topo::is_not_end_point<I, N> constraint(c6(), input);
+ topo::is_not_1d_isthmus<I, N> constraint(c6(), c26(), input);
I output = topo::skeleton::breadth_first_thinning(input, nbh_fg,
is_simple,
detach,
constraint);
- save_raw_3d(output, "image3d-skel-with-end-points-skel.raw");
- save_vtk_polyhedrons(output, "image3d-skel-with-end-points-skel.vtk");
+ save_raw_3d(output, "image3d-skel-with-1d-isthmuses-skel.raw");
+ save_vtk_polyhedrons(output, "image3d-skel-with-1d-isthmuses-skel.vtk");
}
--
1.7.2.5
1
0
last-svn-commit-285-g010c8ad Misc changes in apps/generic-skel/ and tools/.
by Roland Levillain 15 Jun '12
by Roland Levillain 15 Jun '12
15 Jun '12
* apps/generic-skel/image3d-skel-unconstrained.cc:
Remove a useless header inclusion.
* apps/generic-skel/image3d-skel-with-end-points.cc:
Fix a comment.
* tools/compute_local_configurations.cc:
Add a comment.
* tools/connectivity_numbers_3d.hh: Add a FIXME.
---
milena/ChangeLog | 12 ++++++++++++
.../generic-skel/image3d-skel-unconstrained.cc | 1 -
.../generic-skel/image3d-skel-with-end-points.cc | 2 +-
milena/tools/compute_local_configurations.cc | 2 +-
milena/tools/connectivity_numbers_3d.hh | 2 ++
5 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 3e2adbf..95a51a4 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,17 @@
2011-07-13 Roland Levillain <roland(a)lrde.epita.fr>
+ Misc changes in apps/generic-skel/ and tools/.
+
+ * apps/generic-skel/image3d-skel-unconstrained.cc:
+ Remove a useless header inclusion.
+ * apps/generic-skel/image3d-skel-with-end-points.cc:
+ Fix a comment.
+ * tools/compute_local_configurations.cc:
+ Add a comment.
+ * tools/connectivity_numbers_3d.hh: Add a FIXME.
+
+2011-07-13 Roland Levillain <roland(a)lrde.epita.fr>
+
Exercise breadth-first thinning with predicate is_not_1d_isthmus.
* apps/generic-skel/image3d-skel-with-1d-isthmuses.cc: New.
diff --git a/milena/apps/generic-skel/image3d-skel-unconstrained.cc b/milena/apps/generic-skel/image3d-skel-unconstrained.cc
index 236361d..0a16232 100644
--- a/milena/apps/generic-skel/image3d-skel-unconstrained.cc
+++ b/milena/apps/generic-skel/image3d-skel-unconstrained.cc
@@ -43,7 +43,6 @@
#include <mln/topo/is_simple_point3d.hh>
#include <mln/topo/detach_point.hh>
-#include <mln/topo/is_not_end_point.hh>
#include "apps/data.hh"
diff --git a/milena/apps/generic-skel/image3d-skel-with-end-points.cc b/milena/apps/generic-skel/image3d-skel-with-end-points.cc
index 32f3634..82f3e78 100644
--- a/milena/apps/generic-skel/image3d-skel-with-end-points.cc
+++ b/milena/apps/generic-skel/image3d-skel-with-end-points.cc
@@ -98,7 +98,7 @@ int main()
topo::is_simple_point3d<I, N> is_simple(nbh_fg, nbh_bg);
// Simple point detach procedure.
topo::detach_point<I> detach;
- // Constraint: do not collapse end points.
+ // Constraint: do not remove end points.
/* FIXME: This criterion is static, e.g. it is attached to INPUT
(fixed), not OUTPUT (changing during the thinning). This is not
as good as a dynamic critertion (attached to OUTPUT). Maybe it
diff --git a/milena/tools/compute_local_configurations.cc b/milena/tools/compute_local_configurations.cc
index 41dbdc3..e06477b 100644
--- a/milena/tools/compute_local_configurations.cc
+++ b/milena/tools/compute_local_configurations.cc
@@ -59,11 +59,11 @@ int main()
Note that the value corresponding to P is always `false', to
prevent the connection of two components through P. */
data::fill(ima, false);
-
int_u8 tmp = i;
mln_fwd_niter_(neighb2d) n(c8(), p);
for_all(n)
{
+ // Inspect the least significant bit.
if (tmp % 2)
ima(n) = true;
tmp = tmp >> 1;
diff --git a/milena/tools/connectivity_numbers_3d.hh b/milena/tools/connectivity_numbers_3d.hh
index c1dfb19..8b577c6 100644
--- a/milena/tools/connectivity_numbers_3d.hh
+++ b/milena/tools/connectivity_numbers_3d.hh
@@ -245,6 +245,8 @@ connectivity_numbers_3d(F f)
| background. |
`-------------------------------------------------------------*/
+// FIXME: Factor these using mln/topo/connectivity_number_3d.hh
+
conn_number_t
connectivity_number_3d__6_26_one(const mln::image3d<bool>& ima)
{
--
1.7.2.5
1
0
last-svn-commit-286-g4f66070 Factor code of 2D skeletonizations in apps/generic-skel/.
by Roland Levillain 15 Jun '12
by Roland Levillain 15 Jun '12
15 Jun '12
* mln/topo/is_not_end_point.hh: s/nbh/nbh_fg/.
(is_not_end_point<I, N>::is_not_end_point(const Neighborhood<N>&)):
New ctor.
(is_not_end_point<I, N>::set_image): New method.
(is_not_end_point<I, N>::ima_): Turn this reference into a pointer.
Adjust.
* mln/topo/is_simple_point2d.hh
(mln::topo::is_simple_point2d<I, N>::operator())
* mln/topo/detach_point.hh
(mln::topo::detach_point<I>::operator()):
Add preconditions.
* apps/generic-skel/image2d-skel-with-end-points.cc:
Use `mln::topo::is_simple_point2d' and `mln:: topo::detach_point'
from mln/topo/, instead of `is_simple_2d' and `detach' from
image2d-skel.hh
* apps/generic-skel/image2d-skel-unconstrained.cc: Likewise.
Remove the (lack of) constraint, as
mln::topo::skeleton::breadth_first_thinning already takes care of
this.
* apps/generic-skel/image2d-skel.hh: Remove.
* apps/generic-skel/Makefile.am
(image2d_skel_unconstrained_SOURCES)
(image2d_skel_with_end_points_SOURCES):
Remove image2d-skel.hh.
---
milena/ChangeLog | 29 ++++
milena/apps/generic-skel/Makefile.am | 4 +-
.../generic-skel/image2d-skel-unconstrained.cc | 19 +-
.../generic-skel/image2d-skel-with-end-points.cc | 14 +-
milena/apps/generic-skel/image2d-skel.hh | 174 --------------------
milena/mln/topo/detach_point.hh | 1 +
milena/mln/topo/is_not_end_point.hh | 42 ++++-
milena/mln/topo/is_simple_point2d.hh | 1 +
8 files changed, 84 insertions(+), 200 deletions(-)
delete mode 100644 milena/apps/generic-skel/image2d-skel.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 95a51a4..d5db5e7 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,34 @@
2011-07-13 Roland Levillain <roland(a)lrde.epita.fr>
+ Factor code of 2D skeletonizations in apps/generic-skel/.
+
+ * mln/topo/is_not_end_point.hh: s/nbh/nbh_fg/.
+ (is_not_end_point<I, N>::is_not_end_point(const Neighborhood<N>&)):
+ New ctor.
+ (is_not_end_point<I, N>::set_image): New method.
+ (is_not_end_point<I, N>::ima_): Turn this reference into a pointer.
+ Adjust.
+ * mln/topo/is_simple_point2d.hh
+ (mln::topo::is_simple_point2d<I, N>::operator())
+ * mln/topo/detach_point.hh
+ (mln::topo::detach_point<I>::operator()):
+ Add preconditions.
+ * apps/generic-skel/image2d-skel-with-end-points.cc:
+ Use `mln::topo::is_simple_point2d' and `mln:: topo::detach_point'
+ from mln/topo/, instead of `is_simple_2d' and `detach' from
+ image2d-skel.hh
+ * apps/generic-skel/image2d-skel-unconstrained.cc: Likewise.
+ Remove the (lack of) constraint, as
+ mln::topo::skeleton::breadth_first_thinning already takes care of
+ this.
+ * apps/generic-skel/image2d-skel.hh: Remove.
+ * apps/generic-skel/Makefile.am
+ (image2d_skel_unconstrained_SOURCES)
+ (image2d_skel_with_end_points_SOURCES):
+ Remove image2d-skel.hh.
+
+2011-07-13 Roland Levillain <roland(a)lrde.epita.fr>
+
Misc changes in apps/generic-skel/ and tools/.
* apps/generic-skel/image3d-skel-unconstrained.cc:
diff --git a/milena/apps/generic-skel/Makefile.am b/milena/apps/generic-skel/Makefile.am
index 961fef2..fd9febc 100644
--- a/milena/apps/generic-skel/Makefile.am
+++ b/milena/apps/generic-skel/Makefile.am
@@ -33,8 +33,8 @@ bin_PROGRAMS = \
image3d-skel-with-1d-isthmuses
# 2D cases.
-image2d_skel_unconstrained_SOURCES = image2d-skel-unconstrained.cc image2d-skel.hh
-image2d_skel_with_end_points_SOURCES = image2d-skel-with-end-points.cc image2d-skel.hh
+image2d_skel_unconstrained_SOURCES = image2d-skel-unconstrained.cc
+image2d_skel_with_end_points_SOURCES = image2d-skel-with-end-points.cc
# 3D cases, slow versions.
noinst_HEADERS = image3d-skel.hh
diff --git a/milena/apps/generic-skel/image2d-skel-unconstrained.cc b/milena/apps/generic-skel/image2d-skel-unconstrained.cc
index 4459ba4..7a33334 100644
--- a/milena/apps/generic-skel/image2d-skel-unconstrained.cc
+++ b/milena/apps/generic-skel/image2d-skel-unconstrained.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2010, 2011 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Milena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -33,9 +33,10 @@
#include <mln/topo/skeleton/breadth_first_thinning.hh>
-#include <mln/io/pbm/all.hh>
+#include <mln/topo/is_simple_point2d.hh>
+#include <mln/topo/detach_point.hh>
-#include "image2d-skel.hh"
+#include <mln/io/pbm/all.hh>
int
@@ -72,14 +73,12 @@ main(int argc, char* argv[])
neighb2d nbh_bg = c8();
// Simplicity criterion functor.
- ::is_simple_2d<I, N> is_simple(nbh_fg, nbh_bg);
- // Detach procedure.
- ::detach<I> detach;
- // (Lack of) constraint.
- fun::p2b::tautology constraint;
+ topo::is_simple_point2d<I, N> is_simple(nbh_fg, nbh_bg);
+ // Simple point detach procedure.
+ topo::detach_point<I> detach;
I output = topo::skeleton::breadth_first_thinning(input, nbh_fg,
- is_simple, detach,
- constraint);
+ is_simple,
+ detach);
io::pbm::save(output, output_filename);
}
diff --git a/milena/apps/generic-skel/image2d-skel-with-end-points.cc b/milena/apps/generic-skel/image2d-skel-with-end-points.cc
index 604b065..d22f281 100644
--- a/milena/apps/generic-skel/image2d-skel-with-end-points.cc
+++ b/milena/apps/generic-skel/image2d-skel-with-end-points.cc
@@ -34,9 +34,11 @@
#include <mln/topo/skeleton/breadth_first_thinning.hh>
-#include <mln/io/pbm/all.hh>
+#include <mln/topo/is_simple_point2d.hh>
+#include <mln/topo/detach_point.hh>
+#include <mln/topo/is_not_end_point.hh>
-#include "image2d-skel.hh"
+#include <mln/io/pbm/all.hh>
int
@@ -71,11 +73,11 @@ main(int argc, char* argv[])
neighb2d nbh_bg = c8();
// Simplicity criterion functor.
- ::is_simple_2d<I, N> is_simple(nbh_fg, nbh_bg);
- // Detach procedure.
- ::detach<I> detach;
+ topo::is_simple_point2d<I, N> is_simple(nbh_fg, nbh_bg);
+ // Simple point detach procedure.
+ topo::detach_point<I> detach;
// Constraint: do not remove end points.
- is_not_end_point<I, N> constraint(nbh_fg, input);
+ topo::is_not_end_point<I, N> constraint(nbh_fg, input);
I output = topo::skeleton::breadth_first_thinning(input, nbh_fg,
is_simple, detach,
diff --git a/milena/apps/generic-skel/image2d-skel.hh b/milena/apps/generic-skel/image2d-skel.hh
deleted file mode 100644
index 6cd8c50..0000000
--- a/milena/apps/generic-skel/image2d-skel.hh
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
-//
-// This file is part of the Milena 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.
-
-#ifndef APPS_GENERIC_SKEL_IMAGE2D_SKEL_HH
-# define APPS_GENERIC_SKEL_IMAGE2D_SKEL_HH
-
-/// \file
-/// \brief Definitions for a simplicity criterion and a constraint
-/// to be used in the breadth-first thinning of a 2D regular image.
-
-# include <mln/topo/is_simple_2d.hh>
-
-
-// FIXME: Split this file?
-
-
-/** \brief An equivalent (for mln::image2d) of the
- mln::topo::is_simple_cell functor, based on the mask-based
- criterion mln::topo::is_simple_2d.
-
- This functor acts as an adapter, since mln::topo::is_simple_2d
- does not fit (yet) in the canvas of
- mln::topo::skeleton::breadth_first_thinning. Moreover, this code
- is a bit easier to read since it does not make use of a dual
- neighborhood (having a long and complex type). */
-template <typename I, typename N>
-class is_simple_2d : public mln::Function_v2b< is_simple_2d<I, N> >
-{
-public:
- /// Result type of the functor.
- typedef bool result;
-
- /// Build a functor.
- ///
- /// \param nbh_fg The foreground neighborhood.
- /// \param nbh_bg The background neighborhood.
- is_simple_2d(const mln::Neighborhood<N>& nbh_fg,
- const mln::Neighborhood<N>& nbh_bg)
- : nbh_fg_(mln::exact(nbh_fg)), nbh_bg_(mln::exact(nbh_bg)),
- ima_(0)
- {
- }
-
- /// Build a functor, and assign an image to it.
- ///
- /// \param nbh_fg The foreground neighborhood.
- /// \param nbh_bg The background neighborhood.
- /// \apram ima The image.
- is_simple_2d(const mln::Neighborhood<N>& nbh_fg,
- const mln::Neighborhood<N>& nbh_bg,
- const mln::Image<I>& ima)
- : nbh_fg_(mln::exact(nbh_fg)), nbh_bg_(mln::exact(nbh_bg)),
- ima_(mln::exact(&ima))
- {
- }
-
- /// Set the underlying image.
- void set_image(const mln::Image<I>& ima)
- {
- ima_ = mln::exact(&ima);
- }
-
- /// Based on connectivity numbers.
- bool operator()(const mln_psite(I)& p) const
- {
- return
- mln::connectivity_number_2d(*ima_, nbh_fg_, p, true ) == 1 &&
- mln::connectivity_number_2d(*ima_, nbh_bg_, p, false) == 1;
- }
-
-private:
- /// The foreground neighborhood.
- const N& nbh_fg_;
- /// The background neighborhood.
- const N& nbh_bg_;
- /// The image.
- const I* ima_;
-};
-
-
-template <typename I>
-class detach
-{
-public:
- /// Build a functor.
- detach()
- : ima_(0)
- {
- }
-
- /// Build a functor, and assign an image to it.
- ///
- /// \apram ima The image.
- detach(mln::Image<I>& ima)
- : ima_(mln::exact(&ima))
- {
- }
-
- /// Set the underlying image.
- void set_image(mln::Image<I>& ima)
- {
- ima_ = mln::exact(&ima);
- }
-
- void operator()(const mln_psite(I)& p) const
- {
- (*ima_)(p) = false;
- }
-
-private:
- /// The image.
- I* ima_;
-};
-
-
-template <typename I, typename N>
-struct is_not_end_point : public mln::Function_v2b< is_not_end_point<I, N> >
-{
- /// Build a functor, and assign an image to it.
- ///
- /// \param nbh_fg The foreground neighborhood.
- /// \apram ima The image.
- is_not_end_point(const mln::Neighborhood<N>& nbh,
- const mln::Image<I>& ima)
- : nbh_(mln::exact(nbh)),
- ima_(mln::exact(ima))
- {
- }
-
- // Is \a p not a end point?
- bool operator()(const mln_psite(I)& p) const
- {
- // Number of foreground neighbors pixels.
- unsigned nneighbs = 0;
- mln_niter(N) n(nbh_, p);
- for_all(n)
- if (ima_.has(n) && ima_(n))
- ++nneighbs;
- return nneighbs != 1;
- }
-
-private:
- /// The foreground neighborhood.
- const N& nbh_;
- /// The image.
- const I& ima_;
-};
-
-
-#endif // ! APPS_GENERIC_SKEL_IMAGE2D_SKEL_HH
diff --git a/milena/mln/topo/detach_point.hh b/milena/mln/topo/detach_point.hh
index 6e4d22d..c361e11 100644
--- a/milena/mln/topo/detach_point.hh
+++ b/milena/mln/topo/detach_point.hh
@@ -101,6 +101,7 @@ namespace mln
void
detach_point<I>::operator()(const mln_psite(I)& p) const
{
+ mln_precondition(ima_);
(*ima_)(p) = false;
}
diff --git a/milena/mln/topo/is_not_end_point.hh b/milena/mln/topo/is_not_end_point.hh
index 62561fa..f958a59 100644
--- a/milena/mln/topo/is_not_end_point.hh
+++ b/milena/mln/topo/is_not_end_point.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2010, 2011 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Milena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -45,20 +45,28 @@ namespace mln
template <typename I, typename N>
struct is_not_end_point : public Function_v2b< is_not_end_point<I, N> >
{
+ /// Build a functor.
+ ///
+ /// \param nbh The (foreground) neighborhood.
+ is_not_end_point(const Neighborhood<N>& nbh);
+
/// Build a functor, and assign an image to it.
///
- /// \param nbh_fg The foreground neighborhood.
- /// \apram ima The image.
+ /// \param nbh The (foreground) neighborhood.
+ /// \apram ima The image.
is_not_end_point(const Neighborhood<N>& nbh, const Image<I>& ima);
- // Is \a p not an end point?
+ /// Set the underlying image.
+ void set_image(const Image<I>& ima);
+
+ /// Is \a p not an end point?
bool operator()(const mln_psite(I)& p) const;
private:
- /// The foreground neighborhood.
+ /// The (foreground) neighborhood.
const N& nbh_;
/// The image.
- const I& ima_;
+ const I* ima_;
};
@@ -67,11 +75,27 @@ namespace mln
template <typename I, typename N>
inline
+ is_not_end_point<I, N>::is_not_end_point(const Neighborhood<N>& nbh)
+ : nbh_(exact(nbh)),
+ ima_(0)
+ {
+ }
+
+ template <typename I, typename N>
+ inline
is_not_end_point<I, N>::is_not_end_point(const Neighborhood<N>& nbh,
const Image<I>& ima)
: nbh_(exact(nbh)),
- ima_(exact(ima))
+ ima_(exact(&ima))
+ {
+ }
+
+ template <typename I, typename N>
+ inline
+ void
+ is_not_end_point<I, N>::set_image(const Image<I>& ima)
{
+ ima_ = exact(&ima);
}
template <typename I, typename N>
@@ -79,11 +103,13 @@ namespace mln
bool
is_not_end_point<I, N>::operator()(const mln_psite(I)& p) const
{
+ mln_precondition(ima_);
+ const I& ima = *ima_;
// Number of foreground neighbors pixels.
unsigned nneighbs = 0;
mln_niter(N) n(nbh_, p);
for_all(n)
- if (ima_.has(n) && ima_(n))
+ if (ima.has(n) && ima(n))
++nneighbs;
return nneighbs != 1;
}
diff --git a/milena/mln/topo/is_simple_point2d.hh b/milena/mln/topo/is_simple_point2d.hh
index 8d0d7dd..1f9683c 100644
--- a/milena/mln/topo/is_simple_point2d.hh
+++ b/milena/mln/topo/is_simple_point2d.hh
@@ -126,6 +126,7 @@ namespace mln
bool
is_simple_point2d<I, N>::operator()(const mln_psite(I)& p) const
{
+ mln_precondition(ima_);
return
connectivity_number_2d(*ima_, nbh_fg_, p, true ) == 1 &&
connectivity_number_2d(*ima_, nbh_bg_, p, false) == 1;
--
1.7.2.5
1
0
last-svn-commit-288-g4909e37 Add tests to generate figures for the WADGMM 2010/LNCS submission.
by Roland Levillain 15 Jun '12
by Roland Levillain 15 Jun '12
15 Jun '12
* apps/generic-skel/image2d-skel-unconstrained.cc,
* apps/generic-skel/image2d-skel-with-end-points.cc,
* apps/generic-skel/image3d-skel-unconstrained.cc,
* apps/mesh-segm-skel/mesh-complex-max-curv-1-collapse.cc,
* apps/mesh-segm-skel/mesh-complex-max-curv-2-collapse.cc,
* apps/mesh-segm-skel/mesh-complex-pinv-curv-skel.cc:
Display the size of the input.
Time the thinning step.
* milena/apps/generic-skel/test-mixed.in,
* milena/apps/mesh-segm-skel/test-mixed.in:
New.
* apps/generic-skel/Makefile.am (generated_tests): Add test-mixed.
(test-mixed): New target.
(check-mixed): New (phony) target.
* apps/mesh-segm-skel/Makefile.am: Likewise.
($(generated_tests)): New target.
(AM_CPPFLAGS): Add -I$(top_builddir)/milena so that
mln/version.hh, which is a generated header, can be found by the
compiler.
---
milena/ChangeLog | 24 +++++++++++++++
milena/apps/generic-skel/Makefile.am | 11 ++++++-
.../generic-skel/image2d-skel-unconstrained.cc | 12 +++++++-
.../generic-skel/image2d-skel-with-end-points.cc | 12 +++++++-
.../generic-skel/image3d-skel-unconstrained.cc | 21 +++++++------
...age2d-skel-with-end-points.in => test-mixed.in} | 5 ++-
milena/apps/mesh-segm-skel/Makefile.am | 31 ++++++++++++++++++-
.../mesh-complex-max-curv-1-collapse.cc | 15 ++++++++-
.../mesh-complex-max-curv-2-collapse.cc | 15 ++++++++-
.../mesh-segm-skel/mesh-complex-pinv-curv-skel.cc | 14 ++++++++-
...omplex-max-curv-2-collapse.in => test-mixed.in} | 7 ++--
11 files changed, 143 insertions(+), 24 deletions(-)
copy milena/apps/generic-skel/{test-image2d-skel-with-end-points.in => test-mixed.in} (81%)
copy milena/apps/mesh-segm-skel/{test-mesh-complex-max-curv-2-collapse.in => test-mixed.in} (62%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index c990714..2599894 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,27 @@
+2012-02-17 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Add tests to generate figures for the WADGMM 2010/LNCS submission.
+
+ * apps/generic-skel/image2d-skel-unconstrained.cc,
+ * apps/generic-skel/image2d-skel-with-end-points.cc,
+ * apps/generic-skel/image3d-skel-unconstrained.cc,
+ * apps/mesh-segm-skel/mesh-complex-max-curv-1-collapse.cc,
+ * apps/mesh-segm-skel/mesh-complex-max-curv-2-collapse.cc,
+ * apps/mesh-segm-skel/mesh-complex-pinv-curv-skel.cc:
+ Display the size of the input.
+ Time the thinning step.
+ * milena/apps/generic-skel/test-mixed.in,
+ * milena/apps/mesh-segm-skel/test-mixed.in:
+ New.
+ * apps/generic-skel/Makefile.am (generated_tests): Add test-mixed.
+ (test-mixed): New target.
+ (check-mixed): New (phony) target.
+ * apps/mesh-segm-skel/Makefile.am: Likewise.
+ ($(generated_tests)): New target.
+ (AM_CPPFLAGS): Add -I$(top_builddir)/milena so that
+ mln/version.hh, which is a generated header, can be found by the
+ compiler.
+
2011-06-13 Roland Levillain <roland(a)lrde.epita.fr>
Introduce a no-constraint functor to replace fun::p2b::tautology.
diff --git a/milena/apps/generic-skel/Makefile.am b/milena/apps/generic-skel/Makefile.am
index fd9febc..41f022e 100644
--- a/milena/apps/generic-skel/Makefile.am
+++ b/milena/apps/generic-skel/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2010, 2011 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2010-2012 EPITA Research and Development Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -97,3 +97,12 @@ MOSTLYCLEANFILES = \
picasso-skel-with-end-points.pbm \
tiny-skel-unconstrained.pbm \
tiny-skel-with-end-points.pbm
+
+# Mixed tests corresponding to illustrations of the WADGMM 2010/LNCS
+# submission. Not part of the `check' target; triggered by the
+# `check-mixed' target.
+generated_tests += test-mixed
+test-mixed: $(srcdir)/test-mixed.in
+.PHONY: check-mixed
+check-mixed: test-mixed $(bin_PROGRAMS)
+ ./test-mixed
diff --git a/milena/apps/generic-skel/image2d-skel-unconstrained.cc b/milena/apps/generic-skel/image2d-skel-unconstrained.cc
index 7a33334..68578f6 100644
--- a/milena/apps/generic-skel/image2d-skel-unconstrained.cc
+++ b/milena/apps/generic-skel/image2d-skel-unconstrained.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2010, 2011 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2010-2012 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Milena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -38,6 +38,8 @@
#include <mln/io/pbm/all.hh>
+#include <mln/util/timer.hh>
+
int
main(int argc, char* argv[])
@@ -64,6 +66,9 @@ main(int argc, char* argv[])
border::thickness = 1;
I input = io::pbm::load(input_filename);
+ std::cout << input.nrows() << " x " << input.ncols() << " = "
+ << input.nrows() * input.ncols() << " pixels"
+ << std::endl;
// FIXME: Use a dual neighborhood instead?
@@ -77,8 +82,13 @@ main(int argc, char* argv[])
// Simple point detach procedure.
topo::detach_point<I> detach;
+ util::timer t;
+ t.start();
I output = topo::skeleton::breadth_first_thinning(input, nbh_fg,
is_simple,
detach);
+ t.stop();
+ std::cout << t.read() << " s" << std::endl;
+
io::pbm::save(output, output_filename);
}
diff --git a/milena/apps/generic-skel/image2d-skel-with-end-points.cc b/milena/apps/generic-skel/image2d-skel-with-end-points.cc
index d22f281..ed7fc22 100644
--- a/milena/apps/generic-skel/image2d-skel-with-end-points.cc
+++ b/milena/apps/generic-skel/image2d-skel-with-end-points.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2010, 2012 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Milena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -40,6 +40,8 @@
#include <mln/io/pbm/all.hh>
+#include <mln/util/timer.hh>
+
int
main(int argc, char* argv[])
@@ -66,6 +68,9 @@ main(int argc, char* argv[])
border::thickness = 1;
I input = io::pbm::load(input_filename);
+ std::cout << input.nrows() << " x " << input.ncols() << " = "
+ << input.nrows() * input.ncols() << " pixels"
+ << std::endl;
// Foreground neighborhood.
neighb2d nbh_fg = c4();
@@ -79,8 +84,13 @@ main(int argc, char* argv[])
// Constraint: do not remove end points.
topo::is_not_end_point<I, N> constraint(nbh_fg, input);
+ util::timer t;
+ t.start();
I output = topo::skeleton::breadth_first_thinning(input, nbh_fg,
is_simple, detach,
constraint);
+ t.stop();
+ std::cout << t.read() << " s" << std::endl;
+
io::pbm::save(output, output_filename);
}
diff --git a/milena/apps/generic-skel/image3d-skel-unconstrained.cc b/milena/apps/generic-skel/image3d-skel-unconstrained.cc
index 0a16232..986782f 100644
--- a/milena/apps/generic-skel/image3d-skel-unconstrained.cc
+++ b/milena/apps/generic-skel/image3d-skel-unconstrained.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2011-2012 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -44,6 +44,8 @@
#include <mln/topo/is_simple_point3d.hh>
#include <mln/topo/detach_point.hh>
+#include <mln/util/timer.hh>
+
#include "apps/data.hh"
#include "image3d-skel.hh"
@@ -72,19 +74,15 @@ int main()
// program does not use the fast version of the simple 3D point
// criterion.
I input = make_triple_torus(20);
+ std::cout
+ << input.nslices() << " x " << input.nrows() << " x " << input.ncols()
+ << " = " << input.nslices() * input.nrows() * input.ncols() << " voxels"
+ << std::endl;
std::cerr << input.domain() << std::endl;
save_raw_3d(input, "image3d-skel-unconstrained-input.raw");
save_vtk_polyhedrons(input, "image3d-skel-unconstrained-input.vtk");
- // FIXME: Debug.
- unsigned n_fg_comps;
- labeling::blobs(input, c26(), n_fg_comps);
- unsigned n_bg_comps;
- labeling::blobs((fun::v2b::lnot<bool>() << input), c6(), n_bg_comps);
- std::cerr << "n_fg_comps = " << n_fg_comps << std::endl;
- std::cerr << "n_bg_comps = " << n_bg_comps << std::endl;
-
// FIXME: Use a dual neighborhood instead?
// Foreground neighborhood.
@@ -97,9 +95,14 @@ int main()
// Simple point detach procedure.
topo::detach_point<I> detach;
+ util::timer t;
+ t.start();
I output = topo::skeleton::breadth_first_thinning(input, nbh_fg,
is_simple,
detach);
+ t.stop();
+ std::cout << t.read() << " s" << std::endl;
+
save_raw_3d(output, "image3d-skel-unconstrained-skel.raw");
save_vtk_polyhedrons(output, "image3d-skel-unconstrained-skel.vtk");
}
diff --git a/milena/apps/generic-skel/test-image2d-skel-with-end-points.in b/milena/apps/generic-skel/test-mixed.in
similarity index 81%
copy from milena/apps/generic-skel/test-image2d-skel-with-end-points.in
copy to milena/apps/generic-skel/test-mixed.in
index 946e8fd..4fa67bb 100644
--- a/milena/apps/generic-skel/test-image2d-skel-with-end-points.in
+++ b/milena/apps/generic-skel/test-mixed.in
@@ -1,6 +1,6 @@
#! /bin/sh
-# Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2012 EPITA Research and Development Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -20,5 +20,6 @@ set -ex
img_dir=@top_srcdir@/milena/img
-./image2d-skel-with-end-points $img_dir/tiny.pbm tiny-skel-with-end-points.pbm
+./image2d-skel-unconstrained $img_dir/picasso.pbm picasso-skel-unconstrained.pbm
./image2d-skel-with-end-points $img_dir/picasso.pbm picasso-skel-with-end-points.pbm
+./image3d-skel-unconstrained
diff --git a/milena/apps/mesh-segm-skel/Makefile.am b/milena/apps/mesh-segm-skel/Makefile.am
index 4e06baf..861a970 100644
--- a/milena/apps/mesh-segm-skel/Makefile.am
+++ b/milena/apps/mesh-segm-skel/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2008, 2009, 2010 EPITA Research and Development
+# Copyright (C) 2008-2010, 2012 EPITA Research and Development
# Laboratory (LRDE).
#
# This file is part of Olena.
@@ -20,7 +20,7 @@ gluit_builddir = $(top_builddir)/external/trimesh/gluit
include $(top_srcdir)/external/trimesh/gluit/gluit.mk
# Find Milena and trimesh headers.
-AM_CPPFLAGS = -I$(top_srcdir)/milena
+AM_CPPFLAGS = -I$(top_srcdir)/milena -I$(top_builddir)/milena
CPPFLAGS_trimesh = -I$(top_srcdir)/external/trimesh/include
# Produce fast code.
APPS_CXXFLAGS = @APPS_CXXFLAGS@
@@ -285,3 +285,30 @@ MOSTLYCLEANFILES += \
# VTK file.
bin_PROGRAMS += off-to-vtk-bin
off_to_vtk_bin_SOURCES = off-to-vtk-bin.cc
+
+## ------------- ##
+## Mixed tests. ##
+## ------------- ##
+
+# Use Make to generate Doxyfile instead of `configure', as advised by
+# Autoconf's manual (see section ``Installation Directory
+# Variables'').
+# FIXME: Generalize this approach to other tests.
+
+$(generated_tests): Makefile
+ rm -f $@ $@.tmp
+ srcdir=''; \
+ test -f ./$@.in || srcdir=$(srcdir)/; \
+ $(edit) $${srcdir}$@.in >$@.tmp
+ chmod +x $@.tmp
+ chmod a-w $@.tmp
+ mv $@.tmp $@
+
+# Mixed tests corresponding to illustrations of the WADGMM 2010/LNCS
+# submission. Not part of the `check' target; triggered by the
+# `check-mixed' target.
+generated_tests = test-mixed
+test-mixed: $(srcdir)/test-mixed.in
+.PHONY: check-mixed
+check-mixed: test-mixed $(bin_PROGRAMS)
+ ./test-mixed
diff --git a/milena/apps/mesh-segm-skel/mesh-complex-max-curv-1-collapse.cc b/milena/apps/mesh-segm-skel/mesh-complex-max-curv-1-collapse.cc
index 4716a42..47a5a20 100644
--- a/milena/apps/mesh-segm-skel/mesh-complex-max-curv-1-collapse.cc
+++ b/milena/apps/mesh-segm-skel/mesh-complex-max-curv-1-collapse.cc
@@ -1,5 +1,4 @@
-// Copyright (C) 2008, 2009, 2010, 2011 EPITA Research and Development
-// Laboratory (LRDE)
+// Copyright (C) 2008-2012 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Milena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -61,6 +60,8 @@
#include <mln/io/vtk/load.hh>
#include <mln/io/vtk/save.hh>
+#include <mln/util/timer.hh>
+
#include "trimesh/misc.hh"
@@ -91,6 +92,11 @@ main(int argc, char* argv[])
mln::bin_2complex_image3df bin_input;
mln::io::vtk::load(bin_input, input_filename);
+ // FIXME: mln::complex_image should provide shorcuts for this.
+ const mln::topo::complex<D>& cplx = bin_input.domain().cplx();
+ for (unsigned n = 0; n <= D; ++n)
+ std::cout << cplx.nfaces_of_dim(n) << ' ' << n << "-faces" << std::endl;
+
std::pair<float_ima_t, float_ima_t> curv =
mln::geom::mesh_curvature(bin_input.domain());
@@ -353,6 +359,9 @@ main(int argc, char* argv[])
mln_concrete_(bin_ima_t) surface_1_collapse;
mln::initialize(surface_1_collapse, surface_2_collapse);
+
+ mln::util::timer time;
+ time.start();
mln::data::paste
(mln::topo::skeleton::priority_driven_thinning
(mln::mutable_extend((surface_2_collapse | is_an_edge).rw(),
@@ -368,6 +377,8 @@ main(int argc, char* argv[])
undirectly processed). */
| surface_2_collapse.domain(),
surface_1_collapse);
+ time.stop();
+ std::cout << time.read() << " s" << std::endl;
/*---------.
| Output. |
diff --git a/milena/apps/mesh-segm-skel/mesh-complex-max-curv-2-collapse.cc b/milena/apps/mesh-segm-skel/mesh-complex-max-curv-2-collapse.cc
index 7df256e..7c779e3 100644
--- a/milena/apps/mesh-segm-skel/mesh-complex-max-curv-2-collapse.cc
+++ b/milena/apps/mesh-segm-skel/mesh-complex-max-curv-2-collapse.cc
@@ -1,5 +1,4 @@
-// Copyright (C) 2008, 2009, 2010, 2011 EPITA Research and Development
-// Laboratory (LRDE)
+// Copyright (C) 2008-2012 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Milena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -61,6 +60,8 @@
#include <mln/io/vtk/load.hh>
#include <mln/io/vtk/save.hh>
+#include <mln/util/timer.hh>
+
#include "trimesh/misc.hh"
@@ -91,6 +92,11 @@ main(int argc, char* argv[])
mln::bin_2complex_image3df bin_input;
mln::io::vtk::load(bin_input, input_filename);
+ // FIXME: mln::complex_image should provide shorcuts for this.
+ const mln::topo::complex<D>& cplx = bin_input.domain().cplx();
+ for (unsigned n = 0; n <= D; ++n)
+ std::cout << cplx.nfaces_of_dim(n) << ' ' << n << "-faces" << std::endl;
+
std::pair<float_ima_t, float_ima_t> curv =
mln::geom::mesh_curvature(bin_input.domain());
@@ -296,6 +302,9 @@ main(int argc, char* argv[])
mln_concrete_(bin_ima_t) surface_2_collapse;
mln::initialize(surface_2_collapse, surface);
+
+ mln::util::timer time;
+ time.start();
mln::data::paste
(mln::topo::skeleton::priority_driven_thinning
(mln::mutable_extend((surface | is_a_triangle).rw(), surface),
@@ -310,6 +319,8 @@ main(int argc, char* argv[])
undirectly processed). */
| surface.domain(),
surface_2_collapse);
+ time.stop();
+ std::cout << time.read() << " s" << std::endl;
/*---------.
| Output. |
diff --git a/milena/apps/mesh-segm-skel/mesh-complex-pinv-curv-skel.cc b/milena/apps/mesh-segm-skel/mesh-complex-pinv-curv-skel.cc
index bf92305..c4b9bb8 100644
--- a/milena/apps/mesh-segm-skel/mesh-complex-pinv-curv-skel.cc
+++ b/milena/apps/mesh-segm-skel/mesh-complex-pinv-curv-skel.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2008, 2009, 2010 EPITA Research and Development
+// Copyright (C) 2008-2010, 2012 EPITA Research and Development
// Laboratory (LRDE)
//
// This file is part of the Milena Library. This library is free
@@ -54,6 +54,8 @@
#include <mln/topo/detach_cell.hh>
#include <mln/topo/skeleton/breadth_first_thinning.hh>
+#include <mln/util/timer.hh>
+
#include <mln/io/off/load.hh>
/* FIXME: Remove as soon as mln::io::off::save is able to save a
morphed mln::complex_image (i.e., seen through image_if). */
@@ -93,6 +95,11 @@ main(int argc, char* argv[])
mln::bin_2complex_image3df bin_input;
mln::io::off::load(bin_input, input_filename);
+ // FIXME: mln::complex_image should provide shorcuts for this.
+ const mln::topo::complex<D>& cplx = bin_input.domain().cplx();
+ for (unsigned n = 0; n <= D; ++n)
+ std::cout << cplx.nfaces_of_dim(n) << ' ' << n << "-faces" << std::endl;
+
std::pair<float_ima_t, float_ima_t> curv =
mln::geom::mesh_curvature(bin_input.domain());
@@ -307,6 +314,9 @@ main(int argc, char* argv[])
mln_concrete_(bin_ima_t) skel;
mln::initialize(skel, surface);
+
+ mln::util::timer time;
+ time.start();
mln::data::paste
(mln::topo::skeleton::breadth_first_thinning
(mln::mutable_extend((surface | is_a_triangle).rw(), surface),
@@ -314,6 +324,8 @@ main(int argc, char* argv[])
is_simple_triangle,
detach),
skel);
+ time.stop();
+ std::cout << time.read() << " s" << std::endl;
/*---------.
diff --git a/milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-2-collapse.in b/milena/apps/mesh-segm-skel/test-mixed.in
similarity index 62%
copy from milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-2-collapse.in
copy to milena/apps/mesh-segm-skel/test-mixed.in
index 4edf55f..1bc2f0e 100644
--- a/milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-2-collapse.in
+++ b/milena/apps/mesh-segm-skel/test-mixed.in
@@ -1,6 +1,6 @@
#! /bin/sh
-# Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2012 EPITA Research and Development Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -20,5 +20,6 @@ set -ex
mesh_dir=@top_srcdir@/milena/mesh
-time ./mesh-complex-max-curv-2-collapse $mesh_dir/teapot.vtk 20 teapot-max-curv-2-collapse.vtk
-time ./mesh-complex-max-curv-2-collapse $mesh_dir/bunny-holefilled.vtk 50 bunny-holefilled-max-curv-2-collapse.vtk
+./mesh-complex-pinv-curv-skel $mesh_dir/bunny-holefilled.off 50 bunny-holefilled-complex-pinv-curv-skel.off
+./mesh-complex-max-curv-2-collapse $mesh_dir/bunny-holefilled.vtk 50 bunny-holefilled-max-curv-2-collapse.vtk
+./mesh-complex-max-curv-1-collapse $mesh_dir/bunny-holefilled.vtk 50 bunny-holefilled-max-curv-1-collapse.vtk
--
1.7.2.5
1
0
last-svn-commit-560-g5fed9e2 WIP: Start a bench using the watershed transform.
by Roland Levillain 15 Jun '12
by Roland Levillain 15 Jun '12
15 Jun '12
Careful, some implementations may not work (especially
the ones based on complex pointer manipulations).
---
milena/apps/bench/Makefile.am | 30 +-
.../{static_window.hh => static_neighborhood.hh} | 200 +++----
milena/apps/bench/trait.hh | 31 +-
milena/apps/bench/watershed-lena.cc | 116 ++++
milena/apps/bench/watershed.hh | 580 ++++++++++++++++++++
5 files changed, 834 insertions(+), 123 deletions(-)
copy milena/apps/bench/{static_window.hh => static_neighborhood.hh} (58%)
create mode 100644 milena/apps/bench/watershed-lena.cc
create mode 100644 milena/apps/bench/watershed.hh
diff --git a/milena/apps/bench/Makefile.am b/milena/apps/bench/Makefile.am
index d2391c1..c75ea60 100644
--- a/milena/apps/bench/Makefile.am
+++ b/milena/apps/bench/Makefile.am
@@ -1,4 +1,5 @@
-# Copyright (C) 2010, 2011 EPITA Research and Development Laboratory (LRDE).
+# Copyright (C) 2010, 2011, 2012 EPITA Research and Development
+# Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -14,6 +15,8 @@
# You should have received a copy of the GNU General Public License
# along with Olena. If not, see <http://www.gnu.org/licenses/>.
+# Benchmarks for the ICIP 2011 submission and the GRETSI 2011 paper.
+
# Find Milena headers.
AM_CPPFLAGS = -I$(top_srcdir)/milena -I$(top_builddir)/milena
# Produce fast code.
@@ -21,6 +24,10 @@ AM_CXXFLAGS = $(APPS_CXXFLAGS_NODEBUG)
EXTRA_DIST = lena1024.pgm lena2048.pgm
+## ---------- ##
+## Dilation. ##
+## ---------- ##
+
noinst_PROGRAMS = \
dilation-lena \
dilation-lena-bench-nongen \
@@ -124,3 +131,24 @@ test-dilation-lena-bench: test-dilation-lena-bench.in Makefile
CLEANFILES = test-dilation-lena-bench
TESTS = test-dilation-lena-bench
+
+
+## --------------------- ##
+## Watershed transform. ##
+## --------------------- ##
+
+noinst_PROGRAMS += \
+ watershed-lena
+
+watershed_lena_SOURCES = watershed-lena.cc
+
+MOSTLYCLEANFILES += \
+ watershed-lena-out-512-nongen.pgm \
+ watershed-lena-out-512-gen.pgm \
+ watershed-lena-out-512-fast.pgm \
+ watershed-lena-out-1024-nongen.pgm \
+ watershed-lena-out-1024-gen.pgm \
+ watershed-lena-out-1024-fast.pgm \
+ watershed-lena-out-2048-nongen.pgm \
+ watershed-lena-out-2048-gen.pgm \
+ watershed-lena-out-2048-fast.pgm
diff --git a/milena/apps/bench/static_window.hh b/milena/apps/bench/static_neighborhood.hh
similarity index 58%
copy from milena/apps/bench/static_window.hh
copy to milena/apps/bench/static_neighborhood.hh
index 5a8ce21..aa64a98 100644
--- a/milena/apps/bench/static_window.hh
+++ b/milena/apps/bench/static_neighborhood.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008, 2009, 2010, 2011 EPITA Research and Development
-// Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 EPITA Research and
+// Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -24,14 +24,14 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef MLN_CORE_STATIC_WINDOW_HH
-# define MLN_CORE_STATIC_WINDOW_HH
+#ifndef MLN_CORE_STATIC_NEIGHBORHOOD_HH
+# define MLN_CORE_STATIC_NEIGHBORHOOD_HH
// FIXME: Review and update the documentation.
/*! \file
*
- * \brief Definition of the generic window class mln::window.
+ * \brief Definition of the generic neighborhood class mln::neighborhood.
*
* \todo Make naming coherent: we have window (without '_') but
* point_, neighb_, etc.
@@ -43,7 +43,6 @@
* \todo Rename dps_hook_ as util_set_.
*/
-# include <mln/core/internal/window_base.hh>
# include <mln/core/concept/gdpoint.hh>
# include <mln/metal/is_a.hh>
@@ -53,120 +52,91 @@
# include <mln/literal/zero.hh>
# include "apps/bench/static_array.hh"
+# include "apps/bench/static_window.hh"
namespace mln
{
// Forward declarations.
- template <typename D, unsigned n> class static_window;
+ template <typename D, unsigned n> class static_neighborhood;
template <typename V> class dpsites_fwd_piter;
template <typename V> class dpsites_bkd_piter;
- namespace trait
- {
-
- template <typename D, unsigned n>
- struct window_< mln::static_window<D, n> >
- {
- typedef trait::window::size::fixed size;
- typedef trait::window::support::regular support;
- typedef trait::window::definition::unique definition;
- };
-
- } // end of namespace mln::trait
-
-
-
- /*! \brief Generic window class.
+ /*! \brief Generic neighborhood class.
*
- * This type of window is just like a set of delta-points. The
+ * This type of neighborhood is just like a set of delta-points. The
* parameter is \c D, type of delta-point.
*/
template <typename D, unsigned n>
- class static_window : public internal::window_base< D, static_window<D, n> >
+ class static_neighborhood
+ : public Neighborhood< static_neighborhood<D, n> >
{
public:
enum { length = n };
- /// Regular window associated type.
- typedef static_window<D, n> regular;
-
+ /// Window associated type.
+ typedef static_window<D, n> window;
- static_window(const mln::util::static_array<D, n>& dps);
+ /// Get the corresponding window.
+ window win() const;
- /*! \brief Test if the window is centered.
- *
- * \return True if the delta-point 0 belongs to the window.
- */
- bool is_centered() const;
+ static_neighborhood(const mln::util::static_array<D, n>& dps);
- /*! Test if the window is symmetric.
- *
- * \return True if for every dp of this window, -dp is also in
- * this window.
- */
- bool is_symmetric() const;
-
- /// Apply a central symmetry to the target window.
- void sym();
-
-
- /*! \brief Site_Iterator type to browse the points of a basic window
+ /*! \brief Site_Iterator type to browse the points of a basic neighborhood
* w.r.t. the ordering of delta-points.
*/
- typedef dpsites_fwd_piter< static_window<D, n> > fwd_qiter;
+ typedef dpsites_fwd_piter< static_neighborhood<D, n> > fwd_niter;
- /*! \brief Site_Iterator type to browse the points of a basic window
+ /*! \brief Site_Iterator type to browse the points of a basic neighborhood
* w.r.t. the reverse ordering of delta-points.
*/
- typedef dpsites_bkd_piter< static_window<D, n> > bkd_qiter;
+ typedef dpsites_bkd_piter< static_neighborhood<D, n> > bkd_niter;
- /*! \brief Site_Iterator type to browse the points of a basic window
+ /*! \brief Site_Iterator type to browse the points of a basic neighborhood
* whatever the ordering of delta-points.
*/
- typedef fwd_qiter qiter;
-
+ typedef fwd_niter niter;
- /// Give the window size, i.e., the number of delta-sites.
+ /// Give the neighborhood size, i.e., the number of delta-sites.
unsigned size() const;
- /*! \brief Test if the window is empty (null size; no delta-point).
+ /*! \brief Test if the neighborhood is empty (null size; no delta-point).
*/
bool is_empty() const;
- // /// Clear the window.
+ // /// Clear the neighborhood.
// void clear();
- /*! \brief Give the maximum coordinate gap between the window
- center and a window point.
+ /*! \brief Give the maximum coordinate gap between the neighborhood
+ center and a neighborhood point.
*/
unsigned delta() const;
/// Give the \p i-th delta-point.
const D& dp(unsigned i) const;
- /// Test if \p dp is in this window definition.
+ /// Test if \p dp is in this neighborhood definition.
bool has(const D& dp) const;
// /// Insert a delta-point \p dp.
- // static_window<D, n>& insert(const D& dp);
+ // static_neighborhood<D, n>& insert(const D& dp);
- // /// Insert another window \p win.
+ // /// Insert another neighborhood \p nbh.
// template <typename W>
- // static_window<D, n>& insert(const Window<W>& win);
+ // static_neighborhood<D, n>& insert(const Neighborhood<W>& nbh);
// /// \{ Insertion of a delta-point with different numbers of
// /// arguments (coordinates) w.r.t. the dimension.
- // static_window<D, n>& insert(const mln_coord(D)& dind); // For 1D or index access.
+ // static_neighborhood<D, n>& insert(const mln_coord(D)& dind); // For 1D or index access.
- // static_window<D, n>& insert(const mln_coord(D)& drow,
+ // static_neighborhood<D, n>& insert(const mln_coord(D)& drow,
// const mln_coord(D)& dcol); // For 2D.
- // static_window<D, n>& insert(const mln_coord(D)& dsli,
+ // static_neighborhood<D, n>& insert(const mln_coord(D)& dsli,
// const mln_coord(D)& drow,
// const mln_coord(D)& dcol); // For 3D.
/// \}
@@ -175,7 +145,10 @@ namespace mln
/// Hook to the set of D.
const mln::util::static_array<D, n>& dps_hook_() const;
- /// Print the window definition into \p ostr.
+ /// Return true by default.
+ bool is_valid() const;
+
+ /// Print the neighborhood definition into \p ostr.
void print(std::ostream& ostr) const;
private:
@@ -188,22 +161,22 @@ namespace mln
- /*! \brief Equality comparison between windows \p lhs and \p rhs.
+ /*! \brief Equality comparison between neighborhoods \p lhs and \p rhs.
*
- * \relates mln::window
+ * \relates mln::neighborhood
*/
template <typename D, unsigned n>
- bool operator==(const static_window<D, n>& lhs, const static_window<D, n>& rhs);
+ bool operator==(const static_neighborhood<D, n>& lhs, const static_neighborhood<D, n>& rhs);
# ifndef MLN_INCLUDE_ONLY
- // static_window<D, n>
+ // static_neighborhood<D, n>
template <typename D, unsigned n>
inline
- static_window<D, n>::static_window(const mln::util::static_array<D, n>& dps)
+ static_neighborhood<D, n>::static_neighborhood(const mln::util::static_array<D, n>& dps)
: dps_(dps)
{
// FIXME HERE: Was: mln::metal::is_a<D, Dpoint>::check();
@@ -212,39 +185,16 @@ namespace mln
template <typename D, unsigned n>
inline
- bool
- static_window<D, n>::is_symmetric() const
+ static_window<D, n>
+ static_neighborhood<D, n>::win() const
{
- static_window<D, n> cpy = *this;
- cpy.sym();
- return cpy == *this;
+ return static_window<D, n>(dps_);
}
template <typename D, unsigned n>
inline
bool
- static_window<D, n>::is_centered() const
- {
- return this->dps_.has(literal::zero);
- }
-
- template <typename D, unsigned n>
- inline
- void
- static_window<D, n>::sym()
- {
- util::static_array<D, n> rev;
- // FIXME: Can't we use std::copy and reverse_iterators here?
- for (std::size_t i = 0; i < n; ++i)
- rev[i] = dps_[n - 1 - i];
- static_window<D, n> tmp(rev);
- *this = tmp;
- }
-
- template <typename D, unsigned n>
- inline
- bool
- static_window<D, n>::is_empty() const
+ static_neighborhood<D, n>::is_empty() const
{
return n == 0;
}
@@ -252,7 +202,7 @@ namespace mln
// template <typename D, unsigned n>
// inline
// void
- // static_window<D, n>::clear()
+ // static_neighborhood<D, n>::clear()
// {
// dps_.clear();
// }
@@ -260,7 +210,7 @@ namespace mln
template <typename D, unsigned n>
inline
unsigned
- static_window<D, n>::delta() const
+ static_neighborhood<D, n>::delta() const
{
unsigned d = 0;
for (unsigned i = 0; i < n; ++i)
@@ -275,7 +225,7 @@ namespace mln
template <typename D, unsigned n>
inline
unsigned
- static_window<D, n>::delta_(int i) const
+ static_neighborhood<D, n>::delta_(int i) const
{
return i;
}
@@ -283,7 +233,7 @@ namespace mln
template <typename D, unsigned n>
inline
unsigned
- static_window<D, n>::delta_(const Gdpoint<D>& dp) const
+ static_neighborhood<D, n>::delta_(const Gdpoint<D>& dp) const
{
return norm::linfty(exact(dp).to_vec());
}
@@ -291,7 +241,7 @@ namespace mln
template <typename D, unsigned n>
inline
unsigned
- static_window<D, n>::size() const
+ static_neighborhood<D, n>::size() const
{
return n;
}
@@ -299,7 +249,7 @@ namespace mln
template <typename D, unsigned n>
inline
const D&
- static_window<D, n>::dp(unsigned i) const
+ static_neighborhood<D, n>::dp(unsigned i) const
{
mln_precondition(i < n);
return dps_[i];
@@ -308,15 +258,15 @@ namespace mln
template <typename D, unsigned n>
inline
bool
- static_window<D, n>::has(const D& dp) const
+ static_neighborhood<D, n>::has(const D& dp) const
{
return dps_.has(dp);
}
// template <typename D, unsigned n>
// inline
- // static_window<D, n>&
- // static_window<D, n>::insert(const D& dp)
+ // static_neighborhood<D, n>&
+ // static_neighborhood<D, n>::insert(const D& dp)
// {
// dps_.insert(dp);
// return *this;
@@ -325,20 +275,20 @@ namespace mln
// template <typename D, unsigned n>
// template <typename W>
// inline
- // static_window<D, n>&
- // static_window<D, n>::insert(const Window<W>& win_)
+ // static_neighborhood<D, n>&
+ // static_neighborhood<D, n>::insert(const Neighborhood<W>& nbh_)
// {
- // const W& win = exact(win_);
- // const unsigned n = win.size();
+ // const W& nbh = exact(nbh_);
+ // const unsigned n = nbh.size();
// for (unsigned i = 0; i < n; ++i)
- // dps_.insert(win.dp(i));
+ // dps_.insert(nbh.dp(i));
// return *this;
// }
// template <typename D, unsigned n>
// inline
- // static_window<D, n>&
- // static_window<D, n>::insert(const mln_coord(D)& dind)
+ // static_neighborhood<D, n>&
+ // static_neighborhood<D, n>::insert(const mln_coord(D)& dind)
// {
// mlc_bool(D::dim == 1)::check();
// D dp(dind);
@@ -347,8 +297,8 @@ namespace mln
// template <typename D, unsigned n>
// inline
- // static_window<D, n>&
- // static_window<D, n>::insert(const mln_coord(D)& drow,
+ // static_neighborhood<D, n>&
+ // static_neighborhood<D, n>::insert(const mln_coord(D)& drow,
// const mln_coord(D)& dcol)
// {
// mlc_bool(D::dim == 2)::check();
@@ -358,8 +308,8 @@ namespace mln
// template <typename D, unsigned n>
// inline
- // static_window<D, n>&
- // static_window<D, n>::insert(const mln_coord(D)& dsli,
+ // static_neighborhood<D, n>&
+ // static_neighborhood<D, n>::insert(const mln_coord(D)& dsli,
// const mln_coord(D)& drow,
// const mln_coord(D)& dcol)
// {
@@ -371,15 +321,23 @@ namespace mln
template <typename D, unsigned n>
inline
const mln::util::static_array<D, n>&
- static_window<D, n>::dps_hook_() const
+ static_neighborhood<D, n>::dps_hook_() const
{
return dps_;
}
template <typename D, unsigned n>
inline
+ bool
+ static_neighborhood<D, n>::is_valid() const
+ {
+ return true;
+ }
+
+ template <typename D, unsigned n>
+ inline
void
- static_window<D, n>::print(std::ostream& ostr) const
+ static_neighborhood<D, n>::print(std::ostream& ostr) const
{
ostr << dps_;
}
@@ -389,7 +347,7 @@ namespace mln
template <typename D, unsigned n>
bool
- operator==(const static_window<D, n>& lhs, const static_window<D, n>& rhs)
+ operator==(const static_neighborhood<D, n>& lhs, const static_neighborhood<D, n>& rhs)
{
return lhs.dps_hook_() == rhs.dps_hook_();
}
@@ -402,4 +360,4 @@ namespace mln
# include <mln/core/dpsites_piter.hh>
-#endif // ! MLN_CORE_STATIC_WINDOW_HH
+#endif // ! MLN_CORE_STATIC_NEIGHBORHOOD_HH
diff --git a/milena/apps/bench/trait.hh b/milena/apps/bench/trait.hh
index dd2d7e5..c75e842 100644
--- a/milena/apps/bench/trait.hh
+++ b/milena/apps/bench/trait.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2011, 2012 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -30,6 +30,7 @@
# include <mln/metal/none.hh>
# include "apps/bench/static_window.hh"
+# include "apps/bench/static_neighborhood.hh"
# include "apps/bench/static_dpoints_pixter.hh"
@@ -66,6 +67,34 @@ namespace mln
typedef static_dpoints_bkd_pixter< const image2d<T>, static_window<D, n> > ret;
};
+
+ // nixter
+
+ template <typename T, typename D, unsigned n>
+ struct fwd_nixter< image2d<T>, static_neighborhood<D, n> >
+ {
+ typedef static_dpoints_fwd_pixter< image2d<T>, static_neighborhood<D, n> > ret;
+ };
+
+ template <typename T, typename D, unsigned n>
+ struct fwd_nixter< const image2d<T>, static_neighborhood<D, n> >
+ {
+ typedef static_dpoints_fwd_pixter< const image2d<T>, static_neighborhood<D, n> > ret;
+ };
+
+ template <typename T, typename D, unsigned n>
+ struct bkd_nixter< image2d<T>, static_neighborhood<D, n> >
+ {
+ typedef static_dpoints_bkd_pixter< image2d<T>, static_neighborhood<D, n> > ret;
+ };
+
+ template <typename T, typename D, unsigned n>
+ struct bkd_nixter< const image2d<T>, static_neighborhood<D, n> >
+ {
+ typedef static_dpoints_bkd_pixter< const image2d<T>, static_neighborhood<D, n> > ret;
+ };
+
+
// FIXME: Also handle mln::image1d<T> and mln::image3d<T>.
diff --git a/milena/apps/bench/watershed-lena.cc b/milena/apps/bench/watershed-lena.cc
new file mode 100644
index 0000000..2c4710a
--- /dev/null
+++ b/milena/apps/bench/watershed-lena.cc
@@ -0,0 +1,116 @@
+// Copyright (C) 2010, 2011, 2012 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 <mln/core/alias/neighb2d.hh>
+
+#include <mln/morpho/gradient.hh>
+
+#include <mln/value/label.hh>
+#include <mln/data/stretch.hh>
+
+#include "apps/bench/watershed.hh"
+#include "apps/data.hh"
+
+
+// Shortcut macros for run.
+
+#define WATERSHED_WITH_BUILTIN_WINDOW(Namespace, Suffix, Headline) \
+ do \
+ { \
+ t.start(); \
+ w = Namespace::watershed(g, nbasins); \
+ t.stop(); \
+ std::cout << Headline << t.read() << " s" << std::endl; \
+ io::pgm::save(data::stretch(int_u8(), w), \
+ prefix + '-' + length + '-' + Suffix + ".pgm"); \
+ } \
+ while (0)
+
+#define WATERSHED(Namespace, Nbh, Suffix, Headline) \
+ do \
+ { \
+ t.start(); \
+ w = Namespace::watershed(g, Nbh, nbasins); \
+ t.stop(); \
+ std::cout << Headline << t.read() << " s" << std::endl; \
+ io::pgm::save(data::stretch(int_u8(), w), \
+ prefix + '-' + length + '-' + Suffix + ".pgm"); \
+ } \
+ while (0)
+
+
+void
+run(const std::string& filename, const std::string& length)
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::label;
+
+ border::thickness = 1;
+ image2d<int_u8> lena;
+ io::pgm::load(lena, filename);
+ image2d<int_u8> g = morpho::gradient(lena, win_c4p());
+
+ typedef label<24> label_t;
+ label_t nbasins;
+ image2d<label_t> w;
+ util::timer t;
+
+ std::string prefix = "watershed-lena-out";
+ std::cout << "== " << filename << std::endl;
+
+ WATERSHED_WITH_BUILTIN_WINDOW(nongen, "nongen", "nongen\t\t");
+ // FIXME: Does not work yet...
+ // WATERSHED_WITH_BUILTIN_WINDOW(nongen_3ptr, "nongen_3ptr", "nongen_3ptr\t");
+
+ WATERSHED(gen, c4(), "gen", "gen\t\t");
+ // // FIXME: Introduce a new test case, gen_static, using a static window
+ // // and static_qiters.
+ WATERSHED(fast, c4(), "fast", "fast\t\t");
+
+ // Static window, neighborhood and qixters.
+ const unsigned n = 4;
+ mln::dpoint2d dps[n] = { mln::dpoint2d( 0, -1),
+ mln::dpoint2d(-1, 0),
+ mln::dpoint2d(+1, 0),
+ mln::dpoint2d( 0, +1) };
+ mln::util::static_array<mln::dpoint2d, n> sa(dps, dps + n);
+ mln::static_neighborhood<mln::dpoint2d, n> static_nbh_c4 (sa);
+
+ WATERSHED(fast_static, static_nbh_c4, "fast_static", "fast_static\t");
+
+ std::cout << std::endl;
+}
+
+int
+main ()
+{
+ run(MLN_IMG_DIR "/lena.pgm", "512");
+ run(MLN_APPS_DIR "/bench/lena1024.pgm", "1024");
+ run(MLN_APPS_DIR "/bench/lena2048.pgm", "2048");
+}
diff --git a/milena/apps/bench/watershed.hh b/milena/apps/bench/watershed.hh
new file mode 100644
index 0000000..d808647
--- /dev/null
+++ b/milena/apps/bench/watershed.hh
@@ -0,0 +1,580 @@
+// Copyright (C) 2008, 2009, 2012 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_BENCH_WATERSHED_HH
+# define APPS_BENCH_WATERSHED_HH
+
+/// \file
+/// \brief Watershed transform by flooding benchmark cases.
+///
+/// Generic code extracted from mln/morpho/watershed/flooding.hh and
+/// modified.
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/alias/window2d.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/value/label.hh>
+
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/literal/zero.hh>
+# include <mln/labeling/regional_minima.hh>
+
+# include <mln/core/site_set/p_queue_fast.hh>
+# include <mln/core/site_set/p_priority.hh>
+
+# include <mln/extension/adjust_fill.hh>
+
+# include <mln/util/timer.hh>
+
+# include "apps/bench/static_neighborhood.hh"
+# include "apps/bench/static_dpoints_pixter.hh"
+# include "apps/bench/trait.hh"
+
+
+/* FIXME: We should not take into account the time passed into
+ labeling::regional_minima, since this function is the same for in
+ versions of the algorithm. */
+
+/*----------------------.
+| Non-generic version. |
+`----------------------*/
+
+namespace nongen
+{
+ using namespace mln;
+
+ typedef mln::image2d<mln::value::int_u8> image;
+ typedef mln::value::label<24> label;
+ typedef mln::image2d<label> labels;
+
+ labels
+ watershed(const image& input, label& n_basins)
+ {
+ // FIXME: Simplify the body of this routine even more?
+
+ typedef label marker;
+ const marker unmarked = 0;
+
+ typedef mln_value_(image) V;
+ const V max = mln_max(V);
+
+ // Initialize the output with the markers (minima components).
+ typedef labels O;
+ O output = labeling::regional_minima(input, c4(), n_basins);
+
+ // Ordered queue.
+ typedef p_queue_fast<point2d> Q;
+ p_priority<V, Q> queue;
+
+ // In_queue structure to avoid processing sites several times.
+ mln_ch_value_(image, bool) in_queue;
+ initialize(in_queue, input);
+ data::fill(in_queue, false);
+
+
+ // Insert every neighbor (R, C) of every marked area in a
+ // hierarchical queue, with a priority level corresponding to
+ // the grey level input.at_(R, C).
+ for (unsigned int r = 0; r < input.nrows(); ++r) // Iterate on rows.
+ for (unsigned int c = 0; c < input.ncols(); ++c) // Iterate on columns.
+ {
+ if (output.at_(r, c) == unmarked)
+ {
+ if (( r != 0 && output.at_(r-1, c) != unmarked)
+ || (c != 0 && output.at_(r, c-1) != unmarked)
+ || (c != input.ncols() - 1 && output.at_(r, c+1) != unmarked)
+ || (r != input.nrows() - 1 && output.at_(r+1, c) != unmarked))
+ {
+ queue.push(max - input.at_(r, c), point2d(r, c));
+ in_queue.at_(r, c) = true;
+ }
+ }
+ }
+
+ /* Until the queue is empty, extract a point (R, C) from the
+ hierarchical queue, at the highest priority level, that is,
+ the lowest level. */
+ while (! queue.is_empty())
+ {
+ point2d p = queue.front();
+ queue.pop();
+ unsigned int r = p.row();
+ unsigned int c = p.col();
+
+ // Last seen marker adjacent to (R, C).
+ marker adjacent_marker = unmarked;
+ // Has (R, C) a single adjacent marker?
+ bool single_adjacent_marker_p = true;
+
+ const size_t nneighbs = 4;
+ point2d neighb[nneighbs] = { point2d(r-1, c),
+ point2d(r, c-1),
+ point2d(r, c+1),
+ point2d(r+1, c) };
+ for (size_t n = 0; n < nneighbs; ++n)
+ if (output.domain().has(neighb[n]) && output(neighb[n]) != unmarked)
+ {
+ if (adjacent_marker == unmarked)
+ {
+ adjacent_marker = output(neighb[n]);
+ single_adjacent_marker_p = true;
+ }
+ else
+ if (adjacent_marker != output(neighb[n]))
+ {
+ single_adjacent_marker_p = false;
+ break;
+ }
+ }
+ /* If the neighborhood of (R, C) contains only points with the
+ same label, then (R, C) is marked with this label, and its
+ neighbors that are not yet marked are put into the
+ hierarchical queue. */
+ if (single_adjacent_marker_p)
+ {
+ output.at_(r, c) = adjacent_marker;
+ for (size_t n = 0; n < nneighbs; ++n)
+ if (output.domain().has(neighb[n])
+ && output(neighb[n]) == unmarked
+ && ! in_queue(neighb[n]))
+ {
+ queue.push(max - input(neighb[n]), neighb[n]);
+ in_queue(neighb[n]) = true;
+ }
+ }
+ }
+
+ return output;
+ }
+}
+
+/*--------------------------------------------------.
+| Non-generic version, using up to three pointers. |
+`--------------------------------------------------*/
+
+namespace nongen_3ptr
+{
+ using namespace mln;
+
+ typedef mln::image2d<mln::value::int_u8> image;
+ typedef mln::value::label<24> label;
+ typedef mln::image2d<label> labels;
+
+ labels
+ watershed(const image& input, label& n_basins)
+ {
+ // FIXME: Simplify the body of this routine even more?
+
+ typedef label marker;
+ const marker unmarked = 0;
+
+ typedef mln_value_(image) V;
+ const V max = mln_max(V);
+
+
+ // Initialize the output with the markers (minima components).
+ typedef label L;
+ typedef labels O;
+ O output = labeling::regional_minima(input, c4(), n_basins);
+
+ const size_t nneighbs = 4;
+ // Offsets corresponding to a 4-c neighborhood on OUTPUT.
+ ptrdiff_t nbh_offset[nneighbs] =
+ { &output.at_(-1, 0) - &output.at_(0, 0),
+ &output.at_( 0, -1) - &output.at_(0, 0),
+ &output.at_( 0, +1) - &output.at_(0, 0),
+ &output.at_(+1, 0) - &output.at_(0, 0) };
+
+ // Ordered queue.
+ typedef p_queue_fast<L*> Q;
+ p_priority<V, Q> queue;
+
+ // In_queue structure to avoid processing sites several times.
+ mln_ch_value_(image, bool) in_queue;
+ initialize(in_queue, input);
+ data::fill(in_queue, false);
+
+ // Offset between a the pixel located at the same position in
+ // OUTPUT and INPUT.
+ const ptrdiff_t input_offset =
+ (char*)(&input.at_(0, 0)) - (char*)(&output.at_(0, 0));
+ // Offset between a the pixel located at the same position in
+ // OUTPUT and IN_QUEUE.
+ const ptrdiff_t in_queue_offset =
+ (char*)(&in_queue.at_(0, 0)) - (char*)(&output.at_(0, 0));
+
+ // Insert every neighbor of every marked area in a hierarchical
+ // queue, with a priority level corresponding to the grey level of
+ // this area.
+ for (unsigned int r = 0; r < output.nrows(); ++r) // Iterate on rows.
+ {
+ const V* pi = &input.at_(r, 0);
+ L* po = &output.at_(r, 0);
+ bool* pq = &in_queue.at_(r, 0);
+ for (; pi < &input.at_(r, 0) + input.ncols(); ++pi, ++po, ++pq)
+ {
+ if (*po == unmarked)
+ {
+ if (
+ // (-1, 0) neighbor.
+ ( r != 0
+ && *(po + nbh_offset[0]) != unmarked)
+ // (0, -1) neighbor.
+ || (po != &output.at_(r, 0)
+ && *(po + nbh_offset[1]) != unmarked)
+ // (0, +1) neighbor.
+ || (po != &output.at_(r, 0) + output.ncols() - 1
+ && *(po + nbh_offset[2]) != unmarked)
+ // (+1, 0) neighbor.
+ || (r != output.nrows() - 1
+ && *(po + nbh_offset[3]) != unmarked))
+ {
+ queue.push(max - *pi, po);
+ *pq = true;
+ }
+ }
+ }
+ }
+
+ /* Until the queue is empty, extract a point (R, C) from the
+ hierarchical queue, at the highest priority level, that is,
+ the lowest level. */
+ while (! queue.is_empty())
+ {
+ L* po = queue.front();
+ queue.pop();
+
+ // Last seen marker adjacent to the current point.
+ marker adjacent_marker = unmarked;
+ // Has the current point a single adjacent marker?
+ bool single_adjacent_marker_p = true;
+
+ for (size_t n = 0; n < nneighbs; ++n)
+ {
+ L* no = po + nbh_offset[n];
+ // In the border, OUTPUT is unmarked so N is ignored.
+ if (*no != unmarked)
+ {
+ if (adjacent_marker == unmarked)
+ {
+ adjacent_marker = *no;
+ single_adjacent_marker_p = true;
+ }
+ else
+ if (adjacent_marker != *no)
+ {
+ single_adjacent_marker_p = false;
+ break;
+ }
+ }
+ }
+ /* If the neighborhood of the current point contains only
+ points with the same label, then this point is marked with
+ this label, and its neighbors that are not yet marked are
+ put into the hierarchical queue. */
+ if (single_adjacent_marker_p)
+ {
+ *po = adjacent_marker;
+ for (size_t n = 0; n < nneighbs; ++n)
+ {
+ L* no = po + nbh_offset[n];
+ /* Deduce the pointers NI and NQ corresponding to NO
+ in IN_QUEUE and INPUT using the memory offsets
+ bewteen each of these images and OUPUT. This works
+ because the data of qll these images are arranged
+ similarly.
+
+ The ugly casts to and back from char* are required,
+ since the ptrdiff_t values stored in INPUT_OFFSET
+ and IN_QUEUE_OFFSET are expressed as differences
+ between chars. */
+ V* ni = (V*)((char*) no + input_offset);
+ // FIXME: Remove when OK.
+ assert(&input.at_(0, 0) < ni);
+ assert(ni < &input.element(input.nelements() - 1));
+ bool* nq = (bool*)((char*) no + in_queue_offset);
+ // FIXME: Remove when OK.
+ assert(&in_queue.at_(0, 0) < nq);
+ assert(nq < &in_queue.element(in_queue.nelements() - 1));
+ if (*no == unmarked && ! *nq)
+ {
+ queue.push(max - *ni, no);
+ *nq = true;
+ }
+ }
+ }
+ }
+
+ return output;
+ }
+}
+
+
+/*----------------------------------------------.
+| Non-generic version, using a single pointer. |
+`----------------------------------------------*/
+
+namespace nongen_2ptr
+{
+ // FIXME: To do.
+}
+
+
+/*------------------.
+| Generic version. |
+`------------------*/
+
+namespace gen
+{
+ using namespace mln;
+
+ template <typename L, typename I, typename N>
+ mln_ch_value(I, L)
+ watershed(const I& input_, const Neighborhood<N>& nbh_, L& n_basins)
+ {
+ const I input = exact(input_);
+ const N nbh = exact(nbh_);
+
+ typedef L marker;
+ const marker unmarked = literal::zero;
+
+ typedef mln_value(I) V;
+ const V max = mln_max(V);
+
+ // Initialize the output with the markers (minima components).
+ typedef mln_ch_value(I, L) O;
+ O output = labeling::regional_minima(input, nbh, n_basins);
+
+ typedef mln_psite(I) psite;
+
+ // Ordered queue.
+ typedef p_queue_fast<psite> Q;
+ p_priority<V, Q> queue;
+
+ // In_queue structure to avoid processing sites several times.
+ mln_ch_value(I, bool) in_queue;
+ initialize(in_queue, input);
+ data::fill(in_queue, false);
+
+ // Insert every neighbor P of every marked area in a
+ // hierarchical queue, with a priority level corresponding to
+ // the grey level input(P).
+ mln_piter(I) p(output.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if (output(p) == unmarked)
+ for_all(n)
+ if (output.domain().has(n) && output(n) != unmarked)
+ {
+ queue.push(max - input(p), p);
+ in_queue(p) = true;
+ break;
+ }
+
+ /* Until the queue is empty, extract a psite P from the
+ hierarchical queue, at the highest priority level, that is,
+ the lowest level. */
+ while (! queue.is_empty())
+ {
+ psite p = queue.front();
+ queue.pop();
+
+ // Last seen marker adjacent to P.
+ marker adjacent_marker = unmarked;
+ // Has P a single adjacent marker?
+ bool single_adjacent_marker_p = true;
+ mln_niter(N) n(nbh, p);
+ for_all(n)
+ if (output.domain().has(n) && output(n) != unmarked)
+ {
+ if (adjacent_marker == unmarked)
+ {
+ adjacent_marker = output(n);
+ single_adjacent_marker_p = true;
+ }
+ else
+ if (adjacent_marker != output(n))
+ {
+ single_adjacent_marker_p = false;
+ break;
+ }
+ }
+ /* If the neighborhood of P contains only psites with the
+ same label, then P is marked with this label, and its
+ neighbors that are not yet marked are put into the
+ hierarchical queue. */
+ if (single_adjacent_marker_p)
+ {
+ output(p) = adjacent_marker;
+ for_all(n)
+ if (output.domain().has(n) && output(n) == unmarked
+ && ! in_queue(n))
+ {
+ queue.push(max - input(n), n);
+ in_queue(n) = true;
+ }
+ }
+ }
+
+ return output;
+ }
+}
+
+/*-----------------------------------------------.
+| Fast version (with one pixter), less generic. |
+`-----------------------------------------------*/
+
+namespace fast
+{
+ using namespace mln;
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ watershed(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ L& n_basins)
+ {
+ const I input = exact(input_);
+ const N nbh = exact(nbh_);
+
+ typedef L marker;
+ const marker unmarked = literal::zero;
+
+ typedef mln_value(I) V;
+ const V max = mln_max(V);
+
+ extension::adjust_fill(input, nbh, max);
+
+ // Initialize the output with the markers (minima components).
+ typedef mln_ch_value(I, L) O;
+ O output = labeling::regional_minima(input, nbh, n_basins);
+ extension::fill(output, unmarked);
+
+ // Ordered queue.
+ typedef p_queue_fast<unsigned> Q;
+ p_priority<V, Q> queue;
+
+ // In_queue structure to avoid processing sites several times.
+ mln_ch_value(I, bool) in_queue;
+ initialize(in_queue, input);
+ data::fill(in_queue, false);
+ extension::fill(in_queue, true);
+
+ // Insert every neighbor P of every marked area in a
+ // hierarchical queue, with a priority level corresponding to
+ // the grey level input(P).
+ mln_pixter(const O) p_out(output);
+ mln_nixter(const O, N) n_out(p_out, nbh);
+ for_all(p_out)
+ if (p_out.val() == unmarked)
+ for_all(n_out)
+ if (n_out.val() != unmarked)
+ {
+ unsigned po = p_out.offset();
+ queue.push(max - input.element(po), po);
+ in_queue.element(po) = true;
+ break;
+ }
+
+ /* Until the queue is empty, extract a psite P from the
+ hierarchical queue, at the highest priority level, that is,
+ the lowest level. */
+ util::array<int> dp = offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+ while (! queue.is_empty())
+ {
+ unsigned p = queue.front();
+ queue.pop();
+
+ // Last seen marker adjacent to P.
+ marker adjacent_marker = unmarked;
+ // Has P a single adjacent marker?
+ bool single_adjacent_marker_p = true;
+ for (unsigned i = 0; i < n_nbhs; ++i)
+ {
+ unsigned n = p + dp[i];
+ // In the border, OUTPUT is unmarked so N is ignored.
+ if (output.element(n) != unmarked)
+ {
+ if (adjacent_marker == unmarked)
+ {
+ adjacent_marker = output.element(n);
+ single_adjacent_marker_p = true;
+ }
+ else
+ if (adjacent_marker != output.element(n))
+ {
+ single_adjacent_marker_p = false;
+ break;
+ }
+ }
+ }
+ /* If the neighborhood of P contains only psites with the
+ same label, then P is marked with this label, and its
+ neighbors that are not yet marked are put into the
+ hierarchical queue. */
+ if (single_adjacent_marker_p)
+ {
+ output.element(p) = adjacent_marker;
+ for (unsigned i = 0; i < n_nbhs; ++i)
+ {
+ unsigned n = p + dp[i];
+ if (output.element(n) == unmarked
+ // In the border, IN_QUEUE is true so N is ignored.
+ && ! in_queue.element(n))
+ {
+ queue.push(max - input.element(n), n);
+ in_queue.element(n) = true;
+ }
+ }
+ }
+ }
+ return output;
+ }
+}
+
+
+/*------------------------------------------------------------.
+| Fast version (with one pixter) with a static neighborhood. |
+`------------------------------------------------------------*/
+
+namespace fast_static
+{
+ using namespace mln;
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ watershed(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ L& n_basins)
+ {
+ // `fast_static' has the same implementation as `fast'.
+ return ::fast::watershed(input_, nbh_, n_basins);
+ }
+}
+
+#endif // ! APPS_BENCH_WATERSHED_HH
--
1.7.2.5
1
0
last-svn-commit-561-g26a60a9 WIP: Minor changes in apps/bench/dilation-lena.hh.
by Roland Levillain 15 Jun '12
by Roland Levillain 15 Jun '12
15 Jun '12
---
milena/apps/bench/dilation-lena.hh | 35 +++++++++++++++++++----------------
1 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/milena/apps/bench/dilation-lena.hh b/milena/apps/bench/dilation-lena.hh
index 888affd..9eae753 100644
--- a/milena/apps/bench/dilation-lena.hh
+++ b/milena/apps/bench/dilation-lena.hh
@@ -24,26 +24,29 @@
// executable file might be covered by the GNU General Public License.
#ifndef APPS_BENCH_DILATION_LENA_HH
-#define APPS_BENCH_DILATION_LENA_HH
+# define APPS_BENCH_DILATION_LENA_HH
/// \file
/// \brief Dilation benchmark cases.
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/window2d.hh>
+// FIXME: Rename as dilation.hh (there is no specific reference to
+// lena here).
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/alias/window2d.hh>
-#include <mln/value/int_u8.hh>
+# include <mln/value/int_u8.hh>
-#include <mln/accu/stat/max.hh>
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
-#include <mln/util/timer.hh>
+# include <mln/accu/stat/max.hh>
-#include "apps/bench/static_window.hh"
-#include "apps/bench/static_dpoints_pixter.hh"
-#include "apps/bench/trait.hh"
+# include <mln/util/timer.hh>
+
+# include "apps/bench/static_window.hh"
+# include "apps/bench/static_dpoints_pixter.hh"
+# include "apps/bench/trait.hh"
namespace nongen
@@ -119,16 +122,16 @@ namespace nongen_1ptr
{
typedef mln::value::int_u8 val_t;
// Offsets corresponding to a 4-c window on INPUT.
- ptrdiff_t win_offset[4] = { &input.at_(-1, 0) - &input.at_(0, 0),
- &input.at_(+1, 0) - &input.at_(0, 0),
- &input.at_( 0, -1) - &input.at_(0, 0),
- &input.at_( 0, +1) - &input.at_(0, 0) };
+ const ptrdiff_t win_offset[4] = { &input.at_(-1, 0) - &input.at_(0, 0),
+ &input.at_(+1, 0) - &input.at_(0, 0),
+ &input.at_( 0, -1) - &input.at_(0, 0),
+ &input.at_( 0, +1) - &input.at_(0, 0) };
image output;
initialize(output, input);
// Offset between a the pixel located at the same position in
// INPUT and OUTPUT.
- ptrdiff_t output_offset = &output.at_(0, 0) - &input.at_(0, 0);
+ const ptrdiff_t output_offset = &output.at_(0, 0) - &input.at_(0, 0);
for (unsigned int r = 0; r < input.nrows(); ++r) // Iterate on rows.
{
--
1.7.2.5
1
0