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
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
De-activate fastest labeling level.
* tests/labeling/level.cc: Update.
* mln/canvas/labeling.hh (todo): New.
(init): Fix warning with g++-4.3.
Some updates.
* mln/labeling/level.hh: Upgrade doc style.
Fix copyright.
* mln/labeling/level.spe.hh: Likewise.
(todo): New.
(level_): De-activate fastest dispatch; the underlying code
cannot work! E.g., p is a pixter on input, yet used in accessing
output.
(level_fastest_functor): Update.
mln/canvas/labeling.hh | 23 +++++++++++++----------
mln/labeling/level.hh | 12 ++++++------
mln/labeling/level.spe.hh | 32 +++++++++++++++++---------------
tests/labeling/level.cc | 13 +++++++------
4 files changed, 43 insertions(+), 37 deletions(-)
Index: tests/labeling/level.cc
--- tests/labeling/level.cc (revision 2834)
+++ tests/labeling/level.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,10 +26,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/labeling/level.cc
- *
- * \brief Test on mln::labeling::level.
- */
+/// \file tests/labeling/level.cc
+///
+/// Test on mln::labeling::level.
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/neighb2d.hh>
@@ -60,7 +60,8 @@
{
image2d<unsigned> labels = labeling::level(lena, l, c4(), n);
unsigned npix =
- accu::compute<accu::count>(labels | (pw::value(labels) != pw::cst(0u)));
+ accu::compute(accu::meta::count(),
+ labels | (pw::value(labels) != pw::cst(0u)));
npixels += npix;
}
mln_assertion(npixels == lena.nsites());
Index: mln/canvas/labeling.hh
--- mln/canvas/labeling.hh (revision 2834)
+++ mln/canvas/labeling.hh (working copy)
@@ -1,4 +1,5 @@
// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -29,8 +30,10 @@
# define MLN_CANVAS_LABELING_HH
/// \file mln/canvas/labeling.hh
-/// \brief Connected component labeling of the object part in a binary
-/// image.
+///
+/// Connected component labeling of the object part in a binary image.
+///
+/// \todo Make the fastest version work.
# include <mln/core/concept/image.hh>
# include <mln/level/fill.hh>
@@ -159,7 +162,7 @@
mln::level::fill(deja_vu, false);
initialize(parent, f.input);
initialize(output, f.input);
- mln::level::fill(output, literal::zero);
+ mln::level::fill(output, L(literal::zero));
nlabels = 0;
}
@@ -271,7 +274,7 @@
{
initialize(parent, f.input);
for (unsigned p = 0; p < parent.nelements(); ++p)
- parent[p] = p; // make_set
+ parent.element(p) = p; // make_set
initialize(output, f.input);
mln::level::fill(output, 0); // FIXME: Use literal::zero.
nlabels = 0;
@@ -315,11 +318,11 @@
status = false;
return;
}
- output[p] = ++nlabels;
+ output(p) = ++nlabels;
}
}
else
- output[p] = output[parent[p]];
+ output(p) = output(parent.element(p));
}
status = true;
}
@@ -328,17 +331,17 @@
bool
labeling_fastest<F>::is_root(unsigned p) const
{
- return parent[p] == p;
+ return parent.element(p) == p;
}
template <typename F>
unsigned
labeling_fastest<F>::find_root(unsigned x)
{
- if (parent[x] == x)
+ if (parent.element(x) == x)
return x;
else
- return parent[x] = find_root(parent[x]);
+ return parent.element(x) = find_root(parent.element(x));
}
template <typename F>
@@ -348,7 +351,7 @@
unsigned r = find_root(n);
if (r != p)
{
- parent[r] = p;
+ parent.element(r) = p;
f.merge_attr(r, p);
}
}
Index: mln/labeling/level.hh
--- mln/labeling/level.hh (revision 2834)
+++ mln/labeling/level.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,11 +29,10 @@
#ifndef MLN_LABELING_LEVEL_HH
# define MLN_LABELING_LEVEL_HH
-/*! \file mln/labeling/level.hh
- *
- * \brief Connected component labeling of the image objects at a given
- * level.
- */
+/// \file mln/labeling/level.hh
+///
+/// Connected component labeling of the image objects at a given
+/// level.
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
Index: mln/labeling/level.spe.hh
--- mln/labeling/level.spe.hh (revision 2834)
+++ mln/labeling/level.spe.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,10 +29,11 @@
#ifndef MLN_LABELING_LEVEL_SPE_HH
# define MLN_LABELING_LEVEL_SPE_HH
-/*! \file mln/labeling/level.spe.hh
- *
- * \brief Specialization for mln::labeling::level.
- */
+/// \file mln/labeling/level.spe.hh
+///
+/// Specialization for mln::labeling::level.
+///
+/// \todo Re-activate the fastest version in dispatch...
# ifndef MLN_LABELING_LEVEL_HH
# error "Forbidden inclusion of *.spe.hh"
@@ -99,8 +101,8 @@
const N& nbh;
const S& s;
- bool handles(unsigned p) const { return input[p] == val; }
- bool equiv(unsigned n, unsigned) const { return input[n] == val; }
+ bool handles(unsigned p) const { return input.element(p) == val; }
+ bool equiv(unsigned n, unsigned) const { return input.element(n) == val; }
void init() {}
bool labels(unsigned) const { return true; }
@@ -157,14 +159,14 @@
return generic::level_(input, val, nbh, nlabels);
}
- template <typename I, typename N, typename L>
- mln_ch_value(I, L)
- level_(trait::image::speed::fastest,
- const I& input, const mln_value(I)& val, const N& nbh,
- L& nlabels)
- {
- return level_fastest_(input, val, nbh, nlabels);
- }
+// template <typename I, typename N, typename L>
+// mln_ch_value(I, L)
+// level_(trait::image::speed::fastest,
+// const I& input, const mln_value(I)& val, const N& nbh,
+// L& nlabels)
+// {
+// return level_fastest_(input, val, nbh, nlabels);
+// }
} // end of namespace mln::labeling::impl
1
0
cleanup-2008 2834: Add accu snake_2d and transform; revamp accu compute.
by Thierry Geraud 10 Nov '08
by Thierry Geraud 10 Nov '08
10 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add accu snake_2d and transform; revamp accu compute.
* tests/accu/snake_2d.cc: New.
* mln/accu/snake_2d.hh: New.
* mln/accu/transform.hh: New.
* mln/core/image/image2d.hh (include): Re-activate make/image2d.
* tests/accu/transform.cc: New.
* tests/accu/compute.cc (FIXME): Fix.
* tests/accu/Makefile.am: Update.
* mln/accu/min.hh: Fix (c) and upgrade doc layout.
* mln/accu/count.hh: Likewise.
(untake): New.
* mln/accu/compute.hh: Revamp w.r.t. convention.
* mln/transform/influence_zone_geodesic.hh: Fix guard.
* mln/transform/distance.hh: Upgrade doc layout.
* mln/transform/distance_geodesic.hh: Fix guard.
* tests/transform/Makefile.am: Update.
* mln/morpho/erosion.hh: Fix layout.
mln/accu/compute.hh | 83 ++++++++++++--
mln/accu/count.hh | 28 ++++
mln/accu/min.hh | 8 -
mln/accu/snake_2d.hh | 130 +++++++++++++++++++----
mln/accu/transform.hh | 175 +++++++++++++++++++++++++++++++
mln/core/image/image2d.hh | 2
mln/morpho/erosion.hh | 10 +
mln/transform/distance.hh | 9 -
mln/transform/distance_geodesic.hh | 2
mln/transform/influence_zone_geodesic.hh | 3
tests/accu/Makefile.am | 4
tests/accu/compute.cc | 26 +---
tests/accu/snake_2d.cc | 52 +++++++++
tests/accu/transform.cc | 62 ++++++++++
tests/transform/Makefile.am | 6 -
15 files changed, 533 insertions(+), 67 deletions(-)
Index: tests/accu/transform.cc
--- tests/accu/transform.cc (revision 0)
+++ tests/accu/transform.cc (revision 0)
@@ -0,0 +1,62 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/accu/transform.cc
+///
+/// Tests on mln::accu::transform.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/accu/transform.hh>
+
+#include <mln/accu/count.hh>
+#include <mln/win/rectangle2d.hh>
+
+#include <mln/pw/all.hh>
+#include <mln/level/compare.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ image2d<int> ima(4, 5);
+ win::rectangle2d rec(3, 3);
+
+ {
+ image2d<unsigned>
+ out = accu::transform(ima, accu::count<int>(), rec),
+ ref(ima.domain());
+ mln_assertion(out == (pw::cst(rec.size()) | ima.domain()));
+ }
+
+ {
+ image2d<unsigned>
+ out = accu::transform(ima, accu::meta::count(), rec),
+ ref(ima.domain());
+ mln_assertion(out == (pw::cst(rec.size()) | ima.domain()));
+ }
+}
Index: tests/accu/compute.cc
--- tests/accu/compute.cc (revision 2833)
+++ tests/accu/compute.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,31 +26,24 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/accu/compute.cc
- *
- * \brief Tests on mln::accu::compute.
- */
+/// \file tests/accu/compute.cc
+///
+/// Tests on mln::accu::compute.
#include <mln/core/image/image2d.hh>
#include <mln/value/int_u8.hh>
+#include <mln/accu/count.hh>
#include <mln/accu/compute.hh>
-#include <mln/level/compute.hh>
-#include <mln/accu/min.hh>
int main()
{
using namespace mln;
using typename value::int_u8;
- // FIXME : make this test compile
-// int_u8 vs[3][3] = { {9,8,7},
-// {6,5,4},
-// {3,2,1} };
-
-// image2d<int_u8> ima = make::image(vs);
-// int a = accu::compute<accu::min>(ima);
-
-// std::cout << a << std::endl;
+ unsigned n = 3;
+ image2d<int_u8> ima(n, n);
+ unsigned c = accu::compute(accu::meta::count(), ima);
+ mln_assertion(c = n * n);
}
Index: tests/accu/Makefile.am
--- tests/accu/Makefile.am (revision 2833)
+++ tests/accu/Makefile.am (working copy)
@@ -19,6 +19,8 @@
nil \
pair \
rank \
+ snake_2d \
+ transform \
tuple
all_accus_SOURCES = all_accus.cc
@@ -37,6 +39,8 @@
nil_SOURCES = nil.cc
pair_SOURCES = pair.cc
rank_SOURCES = rank.cc
+snake_2d_SOURCES = snake_2d.cc
+transform_SOURCES = transform.cc
tuple_SOURCES = tuple.cc
TESTS = $(check_PROGRAMS)
Index: tests/accu/snake_2d.cc
--- tests/accu/snake_2d.cc (revision 0)
+++ tests/accu/snake_2d.cc (revision 0)
@@ -0,0 +1,52 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/accu/snake_2d.cc
+///
+/// Tests on mln::accu::snake_2d.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/accu/snake_2d.hh>
+#include <mln/accu/count.hh>
+#include <mln/win/rectangle2d.hh>
+#include <mln/pw/all.hh>
+#include <mln/level/compare.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ image2d<int> ima(4, 5);
+ win::rectangle2d rec(3, 3);
+
+ image2d<unsigned>
+ out = accu::snake_2d(accu::meta::count(), ima, rec),
+ ref(ima.domain());
+
+ mln_assertion(out == (pw::cst(rec.size()) | ima.domain()));
+}
Index: tests/transform/Makefile.am
--- tests/transform/Makefile.am (revision 2833)
+++ tests/transform/Makefile.am (working copy)
@@ -3,8 +3,12 @@
include $(top_srcdir)/milena/tests/tests.mk
check_PROGRAMS = \
- distance
+ distance \
+ distance_geodesic \
+ influence_zone_geodesic
distance_SOURCES = distance.cc
+distance_geodesic_SOURCES = distance_geodesic.cc
+influence_zone_geodesic_SOURCES = influence_zone_geodesic.cc
TESTS = $(check_PROGRAMS)
Index: mln/core/image/image2d.hh
--- mln/core/image/image2d.hh (revision 2833)
+++ mln/core/image/image2d.hh (working copy)
@@ -691,7 +691,7 @@
# include <mln/make/image.hh>
-// # include <mln/make/image2d.hh>
+# include <mln/make/image2d.hh>
#endif // ! MLN_CORE_IMAGE_IMAGE2D_HH
Index: mln/accu/snake_2d.hh
--- mln/accu/snake_2d.hh (revision 2832)
+++ mln/accu/snake_2d.hh (working copy)
@@ -1,16 +1,90 @@
-#include <mln/core/alias/neighb2d.hh>
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_ACCU_SNAKE_2D_HH
+# define MLN_ACCU_SNAKE_2D_HH
+
+/// \file mln/accu/snake_2d.hh
+///
+/// Run an accumulator in a snake-like browsing.
+
+#include <mln/core/concept/image.hh>
+#include <mln/core/concept/meta_accumulator.hh>
+#include <mln/core/alias/window2d.hh>
#include <mln/win/diff.hh>
#include <mln/win/shift.hh>
-#include <mln/extension/adjust_fill.hh>
+#include <mln/extension/adjust.hh>
#include <mln/canvas/browsing/snake_generic.hh>
+
+
namespace mln
{
+ namespace accu
+ {
+
+
+ template <typename A, typename I, typename W>
+ mln_ch_value(I, mln_result(A))
+ snake_2d(const Accumulator<A>&, const Image<I>& input, const Window<W>& win);
+
+
+ template <typename A, typename I, typename W>
+ mln_ch_value(I, mln_accu_with(A, mln_value(I))::result)
+ snake_2d(const Meta_Accumulator<A>&, const Image<I>& input, const Window<W>& win);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+
+ template <typename I, typename W>
+ void snake_2d_tests(const Image<I>& input_, const Window<W>& win_)
+ {
+ const I& input = exact(input_);
+ const W& win = exact(win_);
+
+ mln_precondition(input.has_data());
+ mln_precondition(! win.is_empty());
+ // mln_precondition(! win.is_valid());
+
+ (void) input;
+ (void) win;
+ }
+
+
template <typename I, typename W, typename A>
- struct snake2d_functor
+ struct snake_2d_functor
{
- typedef snake2d_functor<I,W, A> self;
+ typedef snake_2d_functor<I,W, A> self;
typedef void (self::*move_fun)();
typedef mln_deduce(I, psite, delta) dpsite;
@@ -44,9 +118,9 @@
std::vector<move_fun> moves;
std::vector<dpsite> dps;
- snake2d_functor(const I& input, const W& win)
- : input(input),
- win(win),
+ snake_2d_functor(const Image<I>& input, const Window<W>& win)
+ : input(exact(input)),
+ win(exact(win)),
accu(),
win_left_fwd(win::shift(win, mln::left) - win),
@@ -155,36 +229,54 @@
};
+
+ } // end of namespace mln::accu::internal
+
+
+
template <typename A, typename I, typename W>
inline
mln_ch_value(I, mln_result(A))
- snake2d(const Accumulator<A>&, const Image<I>& input, const Window<W>& win)
+ snake_2d(const Accumulator<A>&, const Image<I>& input, const Window<W>& win)
{
- trace::entering("accu::snake2d");
+ trace::entering("accu::snake_2d");
- typedef snake2d_functor<I, W, A> F;
- F f(exact(input), exact(win));
- canvas::browsing::snake_generic(f);
+ internal::snake_2d_tests(input, win);
- trace::exiting("accu::snake2d");
+ extension::adjust(input, win);
+ internal::snake_2d_functor<I, W, A> f(input, win);
+ canvas::browsing::snake_generic(f);
+ trace::exiting("accu::snake_2d");
return f.output;
}
+
template <typename A, typename I, typename W>
inline
mln_ch_value(I, mln_accu_with(A, mln_value(I))::result)
- snake2d(const Meta_Accumulator<A>&, const Image<I>& input, const Window<W>& win)
+ snake_2d(const Meta_Accumulator<A>&, const Image<I>& input, const Window<W>& win)
{
- trace::entering("accu::snake2d");
+ trace::entering("accu::snake_2d");
+
+ internal::snake_2d_tests(input, win);
typedef mln_accu_with(A, mln_value(I)) A_;
- typedef snake2d_functor<I, W, A_> F;
- F f(exact(input), exact(win));
+
+ extension::adjust(input, win);
+ internal::snake_2d_functor<I, W, A_> f(input, win);
canvas::browsing::snake_generic(f);
- trace::exiting("accu::snake2d");
+ trace::exiting("accu::snake_2d");
return f.output;
}
-} // mln
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_SNAKE_2D_HH
Property changes on: mln/accu/snake_2d.hh
___________________________________________________________________
Added: svn:mergeinfo
Index: mln/accu/transform.hh
--- mln/accu/transform.hh (revision 0)
+++ mln/accu/transform.hh (revision 0)
@@ -0,0 +1,175 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_ACCU_TRANSFORM_HH
+# define MLN_ACCU_TRANSFORM_HH
+
+/// \file mln/accu/transform.hh
+///
+/// Transform an image by applying locally an accumulator on its
+/// values.
+///
+/// \todo Specialize for fastest images.
+
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/window.hh>
+# include <mln/extension/adjust.hh>
+
+
+namespace mln
+{
+
+ namespace accu
+ {
+
+ template <typename I, typename A, typename W>
+ mln_ch_value(I, mln_result(A))
+ transform(const Image<I>& input,
+ const Accumulator<A>& a,
+ const Window<W>& win);
+
+ template <typename I, typename A, typename W>
+ mln_ch_value(I, mln_accu_with(A, mln_value(I))::result)
+ transform(const Image<I>& input,
+ const Meta_Accumulator<A>& a,
+ const Window<W>& win);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I, typename A, typename W>
+ mln_ch_value(I, mln_result(A))
+ transform(const Image<I>& input_,
+ const Accumulator<A>& a_,
+ const Window<W>& win_)
+ {
+ trace::entering("accu::impl::generic::transform");
+
+ const I& input = exact(input_);
+ A a = exact(a_);
+ const W& win = exact(win_);
+
+ mln_precondition(input.has_data());
+ // mln_precondition(win.is_valid());
+
+ extension::adjust(input, win);
+
+ mln_ch_value(I, mln_result(A)) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_qiter(W) q(win, p);
+ for_all(p)
+ {
+ a.init();
+ for_all(q)
+ a.take(input(q));
+ output(p) = a.to_result();
+ }
+
+ trace::exiting("accu::impl::generic::transform");
+ return output;
+ }
+
+ } // end of namespace mln::accu::impl::generic
+
+ } // end of namespace mln::accu::impl
+
+
+ namespace internal
+ {
+
+ template <typename I, typename A, typename W>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform_dispatch(const Image<I>& input,
+ const Accumulator<A>& a,
+ const Window<W>& win)
+ {
+ return impl::generic::transform(input, a, win);
+ }
+
+ } // end of namespace mln::accu::internal
+
+
+
+ template <typename I, typename A, typename W>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform(const Image<I>& input,
+ const Accumulator<A>& a,
+ const Window<W>& win)
+ {
+ trace::entering("accu::transform");
+
+ mln_precondition(exact(input).has_data());
+ // mln_precondition(exact(win).is_valid());
+
+ mln_ch_value(I, mln_result(A)) output;
+ output = internal::transform_dispatch(input, a, win);
+
+ trace::exiting("accu::transform");
+ return output;
+ }
+
+ template <typename I, typename A, typename W>
+ mln_ch_value(I, mln_accu_with(A, mln_value(I))::result)
+ transform(const Image<I>& input,
+ const Meta_Accumulator<A>&,
+ const Window<W>& win)
+ {
+ trace::entering("accu::transform");
+
+ mln_precondition(exact(input).has_data());
+ // mln_precondition(exact(win).is_valid());
+
+ typedef mln_accu_with(A, mln_value(I)) A_;
+ A_ a;
+ mln_ch_value(I, mln_result(A_)) output;
+ output = internal::transform_dispatch(input, a, win);
+
+ trace::exiting("accu::transform");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_TRANSFORM_HH
Index: mln/accu/min.hh
--- mln/accu/min.hh (revision 2833)
+++ mln/accu/min.hh (working copy)
@@ -1,4 +1,5 @@
// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,10 +29,9 @@
#ifndef MLN_ACCU_MIN_HH
# define MLN_ACCU_MIN_HH
-/*! \file mln/accu/min.hh
- *
- * \brief Define an accumulator that computes a min.
- */
+/// \file mln/accu/min.hh
+///
+/// Define an accumulator that computes a min.
# include <mln/accu/internal/base.hh>
# include <mln/core/concept/meta_accumulator.hh>
Index: mln/accu/count.hh
--- mln/accu/count.hh (revision 2833)
+++ mln/accu/count.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -29,11 +30,13 @@
# define MLN_ACCU_COUNT_HH
/// \file mln/accu/count.hh
+///
/// \brief Define an accumulator that counts.
# include <mln/accu/internal/base.hh>
# include <mln/core/concept/meta_accumulator.hh>
+
namespace mln
{
@@ -55,6 +58,9 @@
void take(const argument&);
void take(const count<T>& other);
+ void untake(const argument&);
+ void untake(const count<T>& other);
+
/// Force the value of the counter to \a c.
void set_value(unsigned c);
/// \}
@@ -71,6 +77,7 @@
unsigned count_;
};
+
namespace meta
{
@@ -87,6 +94,7 @@
} // end of namespace mln::accu::meta
+
# ifndef MLN_INCLUDE_ONLY
template <typename T>
@@ -115,6 +123,15 @@
template <typename T>
inline
void
+ count<T>::untake(const argument&)
+ {
+ mln_precondition(count_ > 0);
+ --count_;
+ }
+
+ template <typename T>
+ inline
+ void
count<T>::take(const count<T>& other)
{
count_ += other.count_;
@@ -122,6 +139,15 @@
template <typename T>
inline
+ void
+ count<T>::untake(const count<T>& other)
+ {
+ mln_precondition(other.count_ <= count_);
+ count_ -= other.count_;
+ }
+
+ template <typename T>
+ inline
unsigned
count<T>::to_result() const
{
Index: mln/accu/compute.hh
--- mln/accu/compute.hh (revision 2833)
+++ mln/accu/compute.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,15 +29,15 @@
#ifndef MLN_ACCU_COMPUTE_HH
# define MLN_ACCU_COMPUTE_HH
-/*! \file mln/accu/compute.hh
- *
- * \brief Define an accumulator that computes image pixels.
- */
+/// \file mln/accu/compute.hh
+///
+/// Compute an accumulator on image pixels, i.e., couples (site,
+/// value).
+///
+/// \todo Specialize for fastest images.
# include <mln/core/concept/meta_accumulator.hh>
-# include <mln/core/concept/accumulator.hh>
# include <mln/core/concept/image.hh>
-# include <mln/metal/is_a.hh>
# include <mln/util/pix.hh>
@@ -58,7 +59,7 @@
*/
template <typename A, typename I>
mln_result(A)
- compute(const Image<I>& input);
+ compute(const Accumulator<A>& a, const Image<I>& input);
/*! \brief Make an accumulator compute the pixels of the image \p input.
@@ -73,34 +74,86 @@
*/
template <typename A, typename I>
mln_accu_with(A, util::pix<I>)::result
- compute(const Image<I>& input);
+ compute(const Meta_Accumulator<A>& a, const Image<I>& input);
# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
template <typename A, typename I>
- inline
mln_result(A)
- compute(const Image<I>& input_)
+ compute(const Accumulator<A>&, const Image<I>& input_)
{
- mlc_is_a(A, Accumulator)::check();
+ trace::entering("accu::impl::generic::compute");
+
const I& input = exact(input_);
+ mln_precondition(input.has_data());
+
A a;
mln_piter(I) p(input.domain());
for_all(p)
a.take(make::pix(input, p));
+
+ trace::exiting("accu::impl::generic::compute");
return a.to_result();
}
+ } // end of namespace mln::accu::impl::generic
+
+ } // end of namespace mln::accu::impl
+
+
+ namespace internal
+ {
+
+ template <typename A, typename I>
+ inline
+ mln_result(A)
+ compute_dispatch(const Accumulator<A>& a, const Image<I>& input)
+ {
+ return impl::generic::compute(a, input);
+ }
+
+ } // end of namespace mln::accu::internal
+
+
+
+ template <typename A, typename I>
+ inline
+ mln_result(A)
+ compute(const Accumulator<A>& a, const Image<I>& input)
+ {
+ trace::entering("accu::compute");
+
+ mln_precondition(exact(input).has_data());
+ mln_result(A) output = internal::compute_dispatch(a, input);
+
+ trace::exiting("accu::compute");
+ return output;
+ }
+
template <typename A, typename I>
inline
mln_accu_with(A, util::pix<I>)::result
- compute(const Image<I>& input)
+ compute(const Meta_Accumulator<A>&, const Image<I>& input)
{
- mlc_is_a(A, Meta_Accumulator)::check();
+ trace::entering("accu::compute");
+
+ mln_precondition(exact(input).has_data());
+
typedef mln_accu_with(A, util::pix<I>) A_;
- return compute<A_>(input);
+ A_ a;
+ mln_result(A_) output = internal::compute_dispatch(a, input);
+
+ trace::exiting("accu::compute");
+ return output;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/transform/influence_zone_geodesic.hh
--- mln/transform/influence_zone_geodesic.hh (revision 2833)
+++ mln/transform/influence_zone_geodesic.hh (working copy)
@@ -50,7 +50,6 @@
# ifndef MLN_INCLUDE_ONLY
-
namespace internal
{
@@ -107,4 +106,4 @@
} // end of namespace mln
-#endif // ! MLN_TRANSFORM_DISTANCE_HH
+#endif // ! MLN_TRANSFORM_INFLUENCE_ZONE_GEODESIC_HH
Index: mln/transform/distance.hh
--- mln/transform/distance.hh (revision 2833)
+++ mln/transform/distance.hh (working copy)
@@ -28,10 +28,11 @@
#ifndef MLN_TRANSFORM_DISTANCE_HH
# define MLN_TRANSFORM_DISTANCE_HH
-/*! \file mln/transform/distance.hh
- *
- * \brief Discrete distance transform.
- */
+/// \file mln/transform/distance.hh
+///
+/// Discrete distance transform.
+///
+/// \todo Make a canvas out of it.
# include <vector>
# include <mln/core/concept/image.hh>
Index: mln/transform/distance_geodesic.hh
--- mln/transform/distance_geodesic.hh (revision 2833)
+++ mln/transform/distance_geodesic.hh (working copy)
@@ -104,4 +104,4 @@
} // end of namespace mln
-#endif // ! MLN_TRANSFORM_DISTANCE_HH
+#endif // ! MLN_TRANSFORM_DISTANCE_GEODESIC_HH
Index: mln/morpho/erosion.hh
--- mln/morpho/erosion.hh (revision 2833)
+++ mln/morpho/erosion.hh (working copy)
@@ -1,4 +1,5 @@
// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -29,6 +30,7 @@
# define MLN_MORPHO_EROSION_HH
/// \file mln/morpho/erosion.hh
+///
/// \brief Morphological erosion.
# include <mln/morpho/includes.hh>
@@ -63,11 +65,13 @@
{
const I& input = exact(input_);
const W& win = exact(win_);
+
+ mln_precondition(input.has_data());
+ mln_precondition(! win.is_empty());
+ // mln_precondition(win.is_valid());
+
(void) input;
(void) win;
-
- mln_precondition(exact(input).has_data());
- mln_precondition(! exact(win).is_empty());
}
} // end of mln::morpho::internal
1
0
10 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
INIM: Add the final code for edges dectection.
* ballas/color/min_tree_area_filter.cc: Update
* ballas/color/min_tree_color.cc,
* ballas/color/min_tree_volume_filter.cc: Update output.
* ballas/color/min_tree_height_filter.cc: New min tree filter.
* ballas/color/min_tree_color_v2.cc: New, color filter.
min_tree_area_filter.cc | 8
min_tree_color.cc | 8
min_tree_color_v2.cc | 530 ++++++++++++++++++++++++++++++++++++++++++++
min_tree_height_filter.cc | 550 ++++++++++++++++++++++++++++++++++++++++++++++
min_tree_volume_filter.cc | 74 ++++--
5 files changed, 1151 insertions(+), 19 deletions(-)
Index: ballas/color/min_tree_volume_filter.cc
--- ballas/color/min_tree_volume_filter.cc (revision 2832)
+++ ballas/color/min_tree_volume_filter.cc (working copy)
@@ -10,9 +10,8 @@
# include <mln/make/double_neighb2d.hh>
# include <mln/core/site_set/p_centered.hh>
-# include <mln/literal/origin.hh>
+
# include <mln/literal/black.hh>
-# include <mln/literal/white.hh>
# include <mln/value/int_u8.hh>
# include <mln/value/int_u16.hh>
@@ -23,17 +22,24 @@
# include <mln/io/ppm/load.hh>
# include <mln/io/ppm/save.hh>
-# include <mln/morpho/closing_area.hh>
+# include <mln/accu/min_max.hh>
+
+# include <mln/fun/i2v/array.hh>
+# include <mln/fun/p2v/iota.hh>
# include <mln/level/paste.hh>
# include <mln/level/fill.hh>
# include <mln/level/transform.hh>
# include <mln/extension/fill.hh>
+# include <mln/morpho/closing_area.hh>
+
+
# include <mln/debug/println.hh>
# include "src/distance.hh"
+
namespace mln
{
template <typename I, typename N, typename Ic, typename Nc>
@@ -58,9 +64,8 @@
// attached data:
int lambda;
mln_ch_value(I, int) volume;
- //mln_ch_value(Ic, value::rgb8) values;
- //initialize(values, ref);
- //mln_ch_value(I, int) comp;
+ mln_ch_value(Ic, value::rgb8) color;
+
min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
int lambda)
@@ -82,10 +87,10 @@
initialize(resp, f);
initialize(zpar, f);
initialize(volume, f);
- //initialize(comp, f);
+ initialize(color, f);
mln::level::fill(deja_vu, false);
- //mln::level::fill(resp, false);
+ mln::level::fill(color, value::rgb8(255, 255, 255));
mln::level::fill(volume, 0);
s = level::sort_psites_increasing(f);
@@ -127,7 +132,7 @@
if (resp(p) && (volume(p) < lambda))
{
resp(p) = false;
- update_data(parent(p), volume(p));
+ update_data(parent(p), volume(p), color(p));
}
}
}
@@ -186,6 +191,11 @@
void init_data(const point& p)
{
+ // init volume
+ volume(p) = f(p);
+
+
+ // init color
int red =0, green = 0, blue = 0;
mln_niter(Nc) n(nbhc, p);
@@ -200,8 +210,11 @@
green /= 2;
blue /= 2;
- volume(p) = distance(value::rgb8(red, green, blue),
- value::rgb8(0, 0, 0));
+ color(p).red() = red;
+ color(p).green() = green;
+ color(p).blue() = blue;
+
+
resp(p) = true;
}
@@ -210,15 +223,24 @@
if (f(p) == f(r))
{
resp(p) = false;
+
+ // merge volume
volume(r) += volume(p);
+
+ // merge color
+ color(r) = (color(r) + color(p)) / 2;
}
}
- void update_data(const point& p, int val)
+ void update_data(const point& p, int val, value::rgb8 c)
{
+ // update volume
volume(p) += val;
+ // update color
+ color(p) = (color(p) + c) / 2;
+
if (parent(p) != p && !resp(p))
- update_data(parent(p), val);
+ update_data(parent(p), val, color(p));
}
};
@@ -382,6 +404,8 @@
}
+
+
template <typename I, typename N, typename Ic, typename Nc>
unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
int lambda)
@@ -390,18 +414,19 @@
min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda);
+
mln_piter(I) p(f.domain());
unsigned nnodes = 0;
for_all(p)
{
if (run.is_node(p))
- {
++nnodes;
}
- }
colorize colors(nnodes);
image2d<value::rgb8> tmp(ref.domain());
+ level::fill(tmp, literal::black);
+ image2d<value::rgb8> tmp2(ref.domain());
level::fill(tmp, ref);
mln_piter(I) q(f.domain());
@@ -410,35 +435,46 @@
{
if (run.is_node(q))
{
- tmp(q) = colors(i);
+ tmp(q) = run.color(q);
+ tmp2(q) = colors(i);
i++;
}
}
+
mln_piter(I) r(f.domain());
for_all(r)
{
if (!run.is_node(r))
{
tmp(r) = tmp(run.find_representative(r));
+ tmp2(r) = tmp2(run.find_representative(r));
}
}
image2d<value::rgb8> to_display(tmp.domain());
+ image2d<value::rgb8> to_display2(tmp2.domain());
- level::fill(to_display, value::rgb8(255, 255, 255));
+ level::fill(to_display, literal::black);
level::paste((tmp | is_edge), to_display);
level::paste(morpho::dilation(to_display, c4()), to_display);
- io::ppm::save(display_edge(tmp, literal::black, 3),
- "edge.ppm");
+ level::fill(to_display2, literal::black);
+ level::paste((tmp2 | is_edge), to_display2);
+ level::paste(morpho::dilation(to_display2, c4()), to_display2);
+
+
+ io::ppm::save(display_edge(tmp, literal::black, 3), "edge.ppm");
io::ppm::save(tmp, "full.ppm");
io::ppm::save(cells2image(to_display), "colorize.ppm");
+ io::ppm::save(display_edge(tmp2, literal::black, 3), "edge2.ppm");
+ io::ppm::save(cells2image(to_display2), "colorize2.ppm");
return nnodes;
}
+
template <typename I>
I
do_it(I& input, int lambda, unsigned& nbasins)
Index: ballas/color/min_tree_area_filter.cc
--- ballas/color/min_tree_area_filter.cc (revision 2832)
+++ ballas/color/min_tree_area_filter.cc (working copy)
@@ -38,6 +38,14 @@
# include <mln/debug/println.hh>
+# if 0
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/util/pix.hh>
+# include <mln/morpho/includes.hh>
+# include <mln/level/sort_psites.hh>
+#endif
+
# include "src/distance.hh"
namespace mln
Index: ballas/color/min_tree_height_filter.cc
--- ballas/color/min_tree_height_filter.cc (revision 0)
+++ ballas/color/min_tree_height_filter.cc (revision 0)
@@ -0,0 +1,550 @@
+# include <mln/core/var.hh>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image_if.hh>
+# include <mln/core/image/extended.hh>
+# include <mln/core/routine/extend.hh>
+
+# include <mln/core/alias/window2d.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/make/double_neighb2d.hh>
+# include <mln/core/site_set/p_centered.hh>
+
+
+# include <mln/literal/black.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/value/int_u16.hh>
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/value/rgb8.hh>
+# include <mln/io/ppm/load.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <mln/accu/min_max.hh>
+
+# include <mln/fun/i2v/array.hh>
+# include <mln/fun/p2v/iota.hh>
+
+# include <mln/level/paste.hh>
+# include <mln/level/fill.hh>
+# include <mln/level/transform.hh>
+# include <mln/extension/fill.hh>
+
+# include <mln/morpho/closing_area.hh>
+
+
+# include <mln/debug/println.hh>
+
+# include "src/distance.hh"
+
+
+namespace mln
+{
+ template <typename I, typename N, typename Ic, typename Nc>
+ struct min_tree_
+ {
+ typedef mln_site(I) point;
+ typedef p_array<point> S;
+
+ // in:
+ const I& f;
+ const N& nbh;
+ const Ic& ref;
+ const Nc& nbhc;
+
+ // aux:
+ S s;
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, point) parent;
+ mln_ch_value(I, bool) resp;
+ mln_ch_value(I, point) zpar;
+
+ // attached data:
+ int lambda;
+ mln_ch_value(I, int) height;
+ mln_ch_value(Ic, value::rgb8) color;
+
+
+ min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+ : f(f),
+ nbh(nbh),
+ ref(ref),
+ nbhc(nbhc),
+ lambda(lambda)
+ {
+ run();
+ }
+
+ void run()
+ {
+ // init
+ {
+ initialize(deja_vu, f);
+ initialize(parent, f);
+ initialize(resp, f);
+ initialize(zpar, f);
+ initialize(height, f);
+ initialize(color, f);
+
+ mln::level::fill(deja_vu, false);
+ mln::level::fill(color, value::rgb8(255, 255, 255));
+ mln::level::fill(height, 0);
+
+ s = level::sort_psites_increasing(f);
+ }
+
+ // first pass
+ {
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ make_set(p);
+ for_all(n)
+ if (f.has(n) && deja_vu(n))
+ do_union(n, p);
+ deja_vu(p) = true;
+ }
+ }
+
+ // second pass: canonization
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ {
+ point q = parent(p);
+ if (f(parent(q)) == f(q))
+ {
+ parent(p) = parent(q);
+ resp(q) = false;
+ }
+ }
+ }
+
+ // third pass: Merging region with height < lambda
+ {
+ mln_fwd_piter(S) p(s);
+ for_all(p)
+ {
+ if (resp(p) && (height(p) < lambda))
+ {
+ resp(p) = false;
+ update_data(parent(p), height(p), color(p));
+ }
+ }
+ }
+
+ } // end of run()
+
+ void make_set(const point& p)
+ {
+ parent(p) = p;
+ zpar(p) = p;
+ init_data(p);
+ }
+
+ void set_parent(const point& r, const point& p)
+ {
+ parent(r) = p;
+ merge_data(r, p);
+ }
+
+ bool is_root(const point& p) const
+ {
+ return parent(p) == p;
+ }
+
+ bool is_node(const point& p) const
+ {
+ //return is_root(p) || f(parent(p)) != f(p);
+ return (is_root(p) || resp(p));
+ }
+
+ point find_root(const point& x)
+ {
+ if (zpar(x) == x)
+ return x;
+ else
+ return zpar(x) = find_root(zpar(x));
+ }
+
+ point find_representative(const point& x)
+ {
+ if (parent(x) == x || resp(x))
+ return x;
+ else
+ return find_representative(parent(x));
+ }
+
+ void do_union(const point& n, const point& p)
+ {
+ point r = find_root(n);
+ if (r != p)
+ {
+ set_parent(r, p);
+ zpar(r) = p;
+ }
+ }
+
+ void init_data(const point& p)
+ {
+ // init height
+ height(p) = f(p);
+
+
+ // init color
+ int red =0, green = 0, blue = 0;
+
+ mln_niter(Nc) n(nbhc, p);
+ for_all(n)
+ {
+ red += ref(n).red();
+ green += ref(n).green();
+ blue += ref(n).blue();
+ }
+
+ red /= 2;
+ green /= 2;
+ blue /= 2;
+
+ color(p).red() = red;
+ color(p).green() = green;
+ color(p).blue() = blue;
+
+
+ resp(p) = true;
+ }
+
+ void merge_data(const point& r, const point& p)
+ {
+ if (f(p) == f(r))
+ {
+ resp(p) = false;
+
+ // merge height
+ height(r) += height(r) > height(p) ? height(r) : height(p);
+
+ // merge color
+ color(r) = (color(r) + color(p)) / 2;
+ }
+ }
+
+ void update_data(const point& p, int val, value::rgb8 c)
+ {
+ // update height
+ height(p) = height(p) > val ? height(p) : val;
+ // update color
+ color(p) = (color(p) + c) / 2;
+
+ if (parent(p) != p && !resp(p))
+ update_data(parent(p), val, color(p));
+ }
+
+ };
+}
+
+namespace mln
+{
+ image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data)
+ {
+ image2d<value::int_u16> output(data.domain());
+ mln_piter_(image2d<value::int_u16>) p(output.domain());
+ for_all(p)
+ output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12;
+ return output;
+ }
+} // end of mln
+
+namespace mln
+{
+
+ struct colorize : Function_v2v< colorize >
+ {
+ typedef value::rgb8 result;
+ colorize(unsigned max)
+ : lut(max + 1)
+ {
+ lut[0] = literal::black;
+ for (unsigned i = 1; i <= max; ++i)
+ lut[i] = result(100 + std::rand() % 150,
+ 100 + std::rand() % 150,
+ 100 + std::rand() % 150);
+ }
+ result operator()(unsigned i) const
+ {
+ return lut[i];
+ }
+ std::vector<result> lut;
+ };
+
+ template <typename I>
+ I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+ level::fill(output, bg);
+
+ mln_VAR(edge, ima | is_edge);
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+
+ template <typename I>
+ I display_edge(const I& ima, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+
+ mln_VAR( cell, ima | is_cell );
+ mln_piter(cell_t) q(cell.domain());
+ for_all(q)
+ {
+ unsigned row = (q.row() / 2) * (zoom + 1);
+ unsigned col = (q.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ for (unsigned j = 0; j < zoom; ++j)
+ output.at(row + i, col + j) = ima(q);
+ }
+
+ mln_VAR( edge, ima | is_edge );
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+
+ namespace morpho
+ {
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ dilation(const I& input, const N& nbh)
+ {
+ typedef mln_value(I) V;
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (input.has(n) && input(n) != value::rgb8(0,0,0))
+ output(p) = input(n);
+ }
+ return output;
+ }
+ } // mln::morpho
+
+} // mln
+
+
+
+template <typename T>
+mln::image2d<T>
+image2cells(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output(2 * input.nrows() - 1,
+ 2 * input.ncols() - 1);
+ for (unsigned row = 0; row < input.nrows(); ++row)
+ for (unsigned col = 0; col < input.ncols(); ++col)
+ output.at(2 * row, 2 * col) = input.at(row, col);
+ return output;
+}
+
+
+template <typename T>
+mln::image2d<T>
+cells2image(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output((input.nrows() + 1) / 2,
+ (input.ncols() + 1) / 2);
+ for (unsigned row = 0; row < input.nrows(); row += 2)
+ for (unsigned col = 0; col < input.ncols(); col += 2)
+ output.at(row / 2, col / 2) = input.at(row, col);
+ return output;
+}
+
+
+
+
+template <typename I, typename N, typename Ic, typename Nc>
+unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+{
+ using namespace mln;
+
+ min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda);
+
+
+ mln_piter(I) p(f.domain());
+ unsigned nnodes = 0;
+ for_all(p)
+ {
+ if (run.is_node(p))
+ ++nnodes;
+ }
+
+ colorize colors(nnodes);
+ image2d<value::rgb8> tmp(ref.domain());
+ level::fill(tmp, literal::black);
+ image2d<value::rgb8> tmp2(ref.domain());
+ level::fill(tmp, ref);
+
+ mln_piter(I) q(f.domain());
+ unsigned int i = 0;
+ for_all(q)
+ {
+ if (run.is_node(q))
+ {
+ tmp(q) = run.color(q);
+ tmp2(q) = colors(i);
+ i++;
+ }
+ }
+
+ mln_piter(I) r(f.domain());
+ for_all(r)
+ {
+ if (!run.is_node(r))
+ {
+ tmp(r) = tmp(run.find_representative(r));
+ tmp2(r) = tmp2(run.find_representative(r));
+ }
+ }
+
+ image2d<value::rgb8> to_display(tmp.domain());
+ image2d<value::rgb8> to_display2(tmp2.domain());
+
+ level::fill(to_display, literal::black);
+ level::paste((tmp | is_edge), to_display);
+ level::paste(morpho::dilation(to_display, c4()), to_display);
+
+ level::fill(to_display2, literal::black);
+ level::paste((tmp2 | is_edge), to_display2);
+ level::paste(morpho::dilation(to_display2, c4()), to_display2);
+
+
+ io::ppm::save(display_edge(tmp, literal::black, 3), "edge.ppm");
+ io::ppm::save(tmp, "full.ppm");
+ io::ppm::save(cells2image(to_display), "colorize.ppm");
+
+ io::ppm::save(display_edge(tmp2, literal::black, 3), "edge2.ppm");
+ io::ppm::save(cells2image(to_display2), "colorize2.ppm");
+
+ return nnodes;
+}
+
+
+
+template <typename I>
+I
+do_it(I& input, int lambda, unsigned& nbasins)
+{
+ using namespace mln;
+
+ /// Graph creation
+ I graph;
+ create_graph(input, graph, value::rgb8(0, 0, 0));
+
+ // Initialization
+ image2d<value::int_u16> ima = convert_to_grey(graph);
+
+ // Neigbhorhood
+ // e2c
+ bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+
+ mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v));
+
+ bool e2e_h[] = { 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0 };
+
+ bool e2e_v[] = { 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0 };
+ mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v));
+
+ // Algorithm
+ distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima);
+
+ io::pgm::save(ima, "edge.pgm");
+
+ nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda);
+
+ return graph;
+}
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl;
+ std::cerr << " lambda >= 0" << std::endl;
+ abort();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+
+ if (argc != 3)
+ usage(argv);
+
+ int lambda = atoi(argv[2]);
+ if (lambda < 0)
+ usage(argv);
+
+ image2d<value::rgb8> ima;
+ io::ppm::load(ima, argv[1]);
+
+ unsigned nbasins;
+ image2d<value::rgb8> output = do_it(ima, lambda, nbasins);
+
+ //io::ppm::save(output, argv[3]);
+}
Index: ballas/color/min_tree_color.cc
--- ballas/color/min_tree_color.cc (revision 2832)
+++ ballas/color/min_tree_color.cc (working copy)
@@ -38,6 +38,14 @@
# include <mln/debug/println.hh>
+# if 0
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/util/pix.hh>
+# include <mln/morpho/includes.hh>
+# include <mln/level/sort_psites.hh>
+#endif
+
# include "src/distance.hh"
namespace mln
Index: ballas/color/min_tree_color_v2.cc
--- ballas/color/min_tree_color_v2.cc (revision 0)
+++ ballas/color/min_tree_color_v2.cc (revision 0)
@@ -0,0 +1,530 @@
+# include <mln/core/var.hh>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image_if.hh>
+# include <mln/core/image/extended.hh>
+# include <mln/core/routine/extend.hh>
+
+# include <mln/core/alias/window2d.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/make/double_neighb2d.hh>
+# include <mln/core/site_set/p_centered.hh>
+
+
+# include <mln/literal/black.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/value/int_u16.hh>
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/value/rgb8.hh>
+# include <mln/io/ppm/load.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <mln/accu/min_max.hh>
+
+# include <mln/fun/i2v/array.hh>
+# include <mln/fun/p2v/iota.hh>
+
+# include <mln/level/paste.hh>
+# include <mln/level/fill.hh>
+# include <mln/level/transform.hh>
+# include <mln/extension/fill.hh>
+
+# include <mln/morpho/closing_area.hh>
+
+
+# include <mln/debug/println.hh>
+
+# include "src/distance.hh"
+
+namespace mln
+{
+ template <typename I, typename N, typename Ic, typename Nc>
+ struct min_tree_
+ {
+ typedef mln_site(I) point;
+ typedef p_array<point> S;
+
+ // in:
+ const I& f;
+ const N& nbh;
+ const Ic& ref;
+ const Nc& nbhc;
+
+ // aux:
+ S s;
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, point) parent;
+ mln_ch_value(I, bool) resp;
+ mln_ch_value(I, point) zpar;
+
+ // attached data:
+ unsigned lambda;
+ mln_ch_value(I, value::rgb8) color;
+ //mln_ch_value(Ic, value::rgb8) values;
+ //initialize(values, ref);
+ //mln_ch_value(I, int) comp;
+
+ min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+ : f(f),
+ nbh(nbh),
+ ref(ref),
+ nbhc(nbhc),
+ lambda(lambda)
+ {
+ run();
+ }
+
+ void run()
+ {
+ // init
+ {
+ initialize(deja_vu, f);
+ initialize(parent, f);
+ initialize(resp, f);
+ initialize(zpar, f);
+ initialize(color, f);
+
+ mln::level::fill(deja_vu, false);
+ mln::level::fill(color, value::rgb8(255, 255, 255));
+
+ s = level::sort_psites_increasing(f);
+ }
+
+ // first pass
+ {
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ make_set(p);
+ for_all(n)
+ if (f.has(n) && deja_vu(n))
+ do_union(n, p);
+ deja_vu(p) = true;
+ }
+ }
+
+ // second pass: canonization
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ {
+ point q = parent(p);
+ if (f(parent(q)) == f(q))
+ {
+ parent(p) = parent(q);
+ resp(q) = false;
+ }
+ }
+ }
+
+ // third pass: Merging region with distance(color) < lambda
+ {
+ mln_fwd_piter(S) p(s);
+ for_all(p)
+ {
+ point q = parent(p);
+ if (resp(p) && distance(color(p), color(q)) < lambda)
+ {
+ resp(p) = false;
+ update_data(q, color(p));
+ }
+ }
+ }
+
+ } // end of run()
+
+ void make_set(const point& p)
+ {
+ parent(p) = p;
+ zpar(p) = p;
+ init_data(p);
+ }
+
+ void set_parent(const point& r, const point& p)
+ {
+ parent(r) = p;
+ merge_data(r, p);
+ }
+
+ bool is_root(const point& p) const
+ {
+ return parent(p) == p;
+ }
+
+ bool is_node(const point& p) const
+ {
+ //return is_root(p) || f(parent(p)) != f(p);
+ return (is_root(p) || resp(p));
+ }
+
+ point find_root(const point& x)
+ {
+ if (zpar(x) == x)
+ return x;
+ else
+ return zpar(x) = find_root(zpar(x));
+ }
+
+ point find_representative(const point& x)
+ {
+ if (parent(x) == x || resp(x))
+ return x;
+ else
+ return find_representative(parent(x));
+ }
+
+ void do_union(const point& n, const point& p)
+ {
+ point r = find_root(n);
+ if (r != p)
+ {
+ set_parent(r, p);
+ zpar(r) = p;
+ }
+ }
+
+ void init_data(const point& p)
+ {
+ int red =0, green = 0, blue = 0;
+
+ mln_niter(Nc) n(nbhc, p);
+ for_all(n)
+ {
+ red += ref(n).red();
+ green += ref(n).green();
+ blue += ref(n).blue();
+ }
+
+ red /= 2;
+ green /= 2;
+ blue /= 2;
+
+ color(p).red() = red;
+ color(p).green() = green;
+ color(p).blue() = blue;
+
+ resp(p) = true;
+ }
+
+ void merge_data(const point& r, const point& p)
+ {
+ if (f(p) == f(r))
+ {
+ resp(p) = false;
+ color(r) = (color(r) + color(p)) / 2;
+ }
+ }
+
+ void update_data(const point& p, value::rgb8 val)
+ {
+ color(p) = (color(p) + val) / 2;
+ if (parent(p) != p && !resp(p))
+ update_data(parent(p), color(p));
+ }
+
+ };
+}
+
+namespace mln
+{
+ image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data)
+ {
+ image2d<value::int_u16> output(data.domain());
+ mln_piter_(image2d<value::int_u16>) p(output.domain());
+ for_all(p)
+ output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12;
+ return output;
+ }
+} // end of mln
+
+namespace mln
+{
+
+ struct colorize : Function_v2v< colorize >
+ {
+ typedef value::rgb8 result;
+ colorize(unsigned max)
+ : lut(max + 1)
+ {
+ lut[0] = literal::black;
+ for (unsigned i = 1; i <= max; ++i)
+ lut[i] = result(100 + std::rand() % 150,
+ 100 + std::rand() % 150,
+ 100 + std::rand() % 150);
+ }
+ result operator()(unsigned i) const
+ {
+ return lut[i];
+ }
+ std::vector<result> lut;
+ };
+
+ template <typename I>
+ I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+ level::fill(output, bg);
+
+ mln_VAR(edge, ima | is_edge);
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+ template <typename I>
+ I display_edge(const I& ima, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+
+ mln_VAR( cell, ima | is_cell );
+ mln_piter(cell_t) q(cell.domain());
+ for_all(q)
+ {
+ unsigned row = (q.row() / 2) * (zoom + 1);
+ unsigned col = (q.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ for (unsigned j = 0; j < zoom; ++j)
+ output.at(row + i, col + j) = ima(q);
+ }
+
+ mln_VAR( edge, ima | is_edge );
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+
+ namespace morpho
+ {
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ dilation(const I& input, const N& nbh)
+ {
+ typedef mln_value(I) V;
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (input.has(n) && input(n) != value::rgb8(0,0,0))
+ output(p) = input(n);
+ }
+ return output;
+ }
+ } // mln::morpho
+
+} // mln
+
+
+
+template <typename T>
+mln::image2d<T>
+image2cells(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output(2 * input.nrows() - 1,
+ 2 * input.ncols() - 1);
+ for (unsigned row = 0; row < input.nrows(); ++row)
+ for (unsigned col = 0; col < input.ncols(); ++col)
+ output.at(2 * row, 2 * col) = input.at(row, col);
+ return output;
+}
+
+
+template <typename T>
+mln::image2d<T>
+cells2image(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output((input.nrows() + 1) / 2,
+ (input.ncols() + 1) / 2);
+ for (unsigned row = 0; row < input.nrows(); row += 2)
+ for (unsigned col = 0; col < input.ncols(); col += 2)
+ output.at(row / 2, col / 2) = input.at(row, col);
+ return output;
+}
+
+
+template <typename I, typename N, typename Ic, typename Nc>
+unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+{
+ using namespace mln;
+
+ min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda);
+
+
+ mln_piter(I) p(f.domain());
+ unsigned nnodes = 0;
+ for_all(p)
+ {
+ if (run.is_node(p))
+ ++nnodes;
+ }
+
+ colorize colors(nnodes);
+ image2d<value::rgb8> tmp(ref.domain());
+ level::fill(tmp, literal::black);
+ image2d<value::rgb8> tmp2(ref.domain());
+ level::fill(tmp, ref);
+
+ mln_piter(I) q(f.domain());
+ unsigned int i = 0;
+ for_all(q)
+ {
+ if (run.is_node(q))
+ {
+ tmp(q) = run.color(q);
+ tmp2(q) = colors(i);
+ i++;
+ }
+ }
+
+ mln_piter(I) r(f.domain());
+ for_all(r)
+ {
+ if (!run.is_node(r))
+ {
+ tmp(r) = tmp(run.find_representative(r));
+ tmp2(r) = tmp2(run.find_representative(r));
+ }
+ }
+
+ image2d<value::rgb8> to_display(tmp.domain());
+ image2d<value::rgb8> to_display2(tmp2.domain());
+
+ level::fill(to_display, literal::black);
+ level::paste((tmp | is_edge), to_display);
+ level::paste(morpho::dilation(to_display, c4()), to_display);
+
+ level::fill(to_display2, literal::black);
+ level::paste((tmp2 | is_edge), to_display2);
+ level::paste(morpho::dilation(to_display2, c4()), to_display2);
+
+
+ io::ppm::save(display_edge(tmp, literal::black, 3), "edge.ppm");
+ io::ppm::save(tmp, "full.ppm");
+ io::ppm::save(cells2image(to_display), "colorize.ppm");
+
+ io::ppm::save(display_edge(tmp2, literal::black, 3), "edge2.ppm");
+ io::ppm::save(cells2image(to_display2), "colorize2.ppm");
+
+ return nnodes;
+}
+
+
+template <typename I>
+I
+do_it(I& input, int lambda, unsigned& nbasins)
+{
+ using namespace mln;
+
+ /// Graph creation
+ I graph;
+ create_graph(input, graph, value::rgb8(0, 0, 0));
+
+ // Initialization
+ image2d<value::int_u16> ima = convert_to_grey(graph);
+
+ // Neigbhorhood
+ // e2c
+ bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+
+ mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v));
+
+ bool e2e_h[] = { 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0 };
+
+ bool e2e_v[] = { 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0 };
+ mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v));
+
+ // Algorithm
+ distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima);
+
+ io::pgm::save(ima, "edge.pgm");
+
+ nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda);
+
+ return graph;
+}
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl;
+ std::cerr << " lambda >= 0" << std::endl;
+ abort();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+
+ if (argc != 3)
+ usage(argv);
+
+ int lambda = atoi(argv[2]);
+ if (lambda < 0)
+ usage(argv);
+
+ image2d<value::rgb8> ima;
+ io::ppm::load(ima, argv[1]);
+
+ unsigned nbasins;
+ image2d<value::rgb8> output = do_it(ima, lambda, nbasins);
+
+ //io::ppm::save(output, argv[3]);
+}
1
0
cleanup-2008 2832: Rely on a canvas to compute iz and distance transforms.
by Thierry Geraud 10 Nov '08
by Thierry Geraud 10 Nov '08
10 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Rely on a canvas to compute iz and distance transforms.
* tests/transform/influence_zone_geodesic.cc: Slight change.
* mln/debug/println.hh: New overload to display a message.
* mln/canvas/distance_geodesic.hh: New.
* mln/transform/influence_zone_geodesic.hh: Update.
* mln/transform/distance_geodesic.hh: Update.
mln/canvas/distance_geodesic.hh | 81 ++++++++----------------
mln/debug/println.hh | 28 ++++++--
mln/transform/distance_geodesic.hh | 84 +++++--------------------
mln/transform/influence_zone_geodesic.hh | 96 ++++++-----------------------
tests/transform/influence_zone_geodesic.cc | 2
5 files changed, 91 insertions(+), 200 deletions(-)
Index: tests/transform/influence_zone_geodesic.cc
--- tests/transform/influence_zone_geodesic.cc (revision 2831)
+++ tests/transform/influence_zone_geodesic.cc (working copy)
@@ -53,6 +53,6 @@
0, 0, 0, 0, 0, 0, 0 };
image2d<int_u8> input = make::image2d(vals);
- image2d<int_u8> output = transform::influence_zone_geodesic(input, c4(), int_u8(1));
+ image2d<int_u8> output = transform::influence_zone_geodesic(input, c4(), int_u8(2));
debug::println(output);
}
Index: mln/debug/println.hh
--- mln/debug/println.hh (revision 2831)
+++ mln/debug/println.hh (working copy)
@@ -1,4 +1,5 @@
// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,12 +29,11 @@
#ifndef MLN_DEBUG_PRINTLN_HH
# define MLN_DEBUG_PRINTLN_HH
-/*! \file mln/debug/println.hh
- *
- * \brief Print an image on the standard output.
- *
- * \todo Revamp.
- */
+/// \file mln/debug/println.hh
+///
+/// Print an image on the standard output.
+///
+/// \todo Revamp.
# include <mln/core/concept/image.hh>
# include <mln/core/concept/window.hh>
@@ -43,6 +43,7 @@
// Specializations are in:
# include <mln/debug/println.spe.hh>
+
namespace mln
{
@@ -53,6 +54,11 @@
template <typename I>
void println(const Image<I>& input);
+ /// Print the message \p msg and the image \p input on the
+ /// standard output.
+ template <typename I>
+ void println(const std::string& msg, const Image<I>& input);
+
# ifndef MLN_INCLUDE_ONLY
@@ -75,7 +81,8 @@
} // end of namespace mln::debug::impl
- // Facade.
+ // Facades.
+
template <typename I>
inline
void
@@ -87,6 +94,13 @@
trace::exiting("debug::println");
}
+ template <typename I>
+ void println(const std::string& msg, const Image<I>& input)
+ {
+ std::cout << msg << std::endl;
+ println(input);
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::debug
Index: mln/transform/influence_zone_geodesic.hh
--- mln/transform/influence_zone_geodesic.hh (revision 2831)
+++ mln/transform/influence_zone_geodesic.hh (working copy)
@@ -32,13 +32,8 @@
///
/// Discrete geodesic distance transform.
-# include <mln/core/concept/image.hh>
-# include <mln/core/concept/neighborhood.hh>
-# include <mln/core/site_set/p_queue_fast.hh>
-# include <mln/core/routine/clone.hh>
-# include <mln/level/fill.hh>
-
-# include <mln/debug/println.hh>
+# include <mln/canvas/distance_geodesic.hh>
+# include <mln/literal/zero.hh>
namespace mln
@@ -55,99 +50,54 @@
# ifndef MLN_INCLUDE_ONLY
- namespace impl
- {
- namespace generic
+ namespace internal
{
- template <typename I, typename N, typename D>
- mln_concrete(I)
- influence_zone_geodesic(const Image<I>& input_, const Neighborhood<N>& nbh_,
- D max)
+ template <typename I>
+ struct iz_functor
{
- trace::entering("transform::impl::generic::influence_zone_geodesic");
-
- const I& input = exact(input_);
- const N& nbh = exact(nbh_);
-
- mln_precondition(input.has_data());
-
- mln_ch_value(I, D) dmap; // Distance map is aux data.
- initialize(dmap, input);
-
+ typedef mln_value(I) V;
typedef mln_site(I) P;
- p_queue_fast<P> q;
- mln_concrete(I) output = clone(input);
+ mln_concrete(I) output;
- // Initialization.
- {
- level::fill(dmap, max);
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- if (input(p) != 0) // p in a component
- {
- dmap(p) = 0;
- for_all(n)
- if (input.domain().has(n) && input(n) == 0) // n in background
+ void init(const I& input)
{
- q.push(p);
- break;
- }
+ output = clone(input);
}
+ bool inqueue_p_wrt_input_p(const V& input_p)
+ {
+ return input_p != 0u;
}
-
- // Propagation.
+ bool inqueue_p_wrt_input_n(const V& input_n)
{
- P p;
- mln_niter(N) n(nbh, p);
- while (! q.is_empty())
- {
- p = q.pop_front();
- if (dmap(p) == max)
- {
- // Saturation so stop.
- q.clear();
- break;
+ return input_n == 0u;
}
- for_all(n)
- if (input.domain().has(n) && dmap(n) == max)
+ void process(const P& p, const P& n)
{
- dmap(n) = dmap(p) + 1;
output(n) = output(p);
- q.push(n);
- }
- }
}
+ };
- trace::exiting("transform::impl::generic::influence_zone_geodesic");
- return output;
- }
+ } // end of namespace mln::transform::internal
- } // end of namespace mln::transform::impl::generic
-
- } // end of namespace mln::transform::impl
-
-
- // Facade.
template <typename I, typename N, typename D>
- inline
mln_concrete(I)
influence_zone_geodesic(const Image<I>& input, const Neighborhood<N>& nbh,
- D distance_max)
+ D max)
{
trace::entering("transform::influence_zone_geodesic");
- // FIXME: tests.
+ mln_precondition(exact(input).has_data());
+ // mln_precondition(exact(nbh).is_valid());
- mln_concrete(I) output;
- output = impl::generic::influence_zone_geodesic(input, nbh, distance_max);
+ internal::iz_functor<I> f;
+ (void) mln::canvas::distance_geodesic(input, nbh, max, f);
trace::exiting("transform::influence_zone_geodesic");
- return output;
+ return f.output;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/transform/distance_geodesic.hh
--- mln/transform/distance_geodesic.hh (revision 2831)
+++ mln/transform/distance_geodesic.hh (working copy)
@@ -32,10 +32,7 @@
///
/// Discrete geodesic distance transform.
-# include <mln/core/concept/image.hh>
-# include <mln/core/concept/neighborhood.hh>
-# include <mln/core/site_set/p_queue_fast.hh>
-# include <mln/level/fill.hh>
+# include <mln/canvas/distance_geodesic.hh>
@@ -53,79 +50,34 @@
# ifndef MLN_INCLUDE_ONLY
- namespace impl
- {
- namespace generic
+ namespace internal
{
- template <typename I, typename N, typename D>
- mln_ch_value(I, D)
- distance_geodesic(const Image<I>& input_, const Neighborhood<N>& nbh_, D max)
+ template <typename I>
+ struct distance_functor
{
- trace::entering("transform::impl::generic::distance_geodesic");
-
- const I& input = exact(input_);
- const N& nbh = exact(nbh_);
-
- mln_precondition(input.has_data());
-
- mln_ch_value(I, D) output;
- initialize(output, input);
-
+ typedef mln_value(I) V;
typedef mln_site(I) P;
- p_queue_fast<P> q;
- // Initialization.
+ void init(const I&)
{
- level::fill(output, max);
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- if (input(p) == true) // p in object
- {
- output(p) = 0;
- for_all(n)
- if (input.domain().has(n) && input(n) == false) // n in background
- {
- q.push(p);
- break;
- }
}
- }
-
- // Propagation.
+ bool inqueue_p_wrt_input_p(const V& input_p)
{
- P p;
- mln_niter(N) n(nbh, p);
- while (! q.is_empty())
- {
- p = q.pop_front();
- for_all(n)
- if (input.domain().has(n) && output(n) == max)
- {
- output(n) = output(p) + 1;
- if (output(n) == max)
- {
- // Saturation so stop.
- q.clear();
- break;
- }
- q.push(n);
- }
+ return input_p == true;
}
+ bool inqueue_p_wrt_input_n(const V& input_n)
+ {
+ return input_n == false;
}
-
- trace::exiting("transform::impl::generic::distance_geodesic");
- return output;
+ void process(const P&, const P&)
+ {
}
+ };
- } // end of namespace mln::transform::impl::generic
-
- } // end of namespace mln::transform::impl
-
+ } // end of namespace mln::transform::internal
- // Facade.
template <typename I, typename N, typename D>
inline
@@ -134,10 +86,12 @@
{
trace::entering("transform::distance_geodesic");
- // FIXME: tests.
+ mln_precondition(exact(input).has_data());
+ // mln_precondition(exact(nbh).is_valid());
mln_ch_value(I, D) output;
- output = impl::generic::distance_geodesic(input, nbh, max);
+ internal::distance_functor<I> f;
+ output = mln::canvas::distance_geodesic(input, nbh, max, f);
trace::exiting("transform::distance_geodesic");
return output;
Index: mln/canvas/distance_geodesic.hh
--- mln/canvas/distance_geodesic.hh (revision 2830)
+++ mln/canvas/distance_geodesic.hh (working copy)
@@ -25,12 +25,12 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_TRANSFORM_INFLUENCE_ZONE_GEODESIC_HH
-# define MLN_TRANSFORM_INFLUENCE_ZONE_GEODESIC_HH
+#ifndef MLN_CANVAS_DISTANCE_GEODESIC_HH
+# define MLN_CANVAS_DISTANCE_GEODESIC_HH
-/// \file mln/transform/influence_zone_geodesic.hh
+/// \file mln/canvas/distance_geodesic.hh
///
-/// Discrete geodesic distance transform.
+/// Discrete geodesic distance canvas.
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
@@ -38,40 +38,37 @@
# include <mln/core/routine/clone.hh>
# include <mln/level/fill.hh>
-# include <mln/debug/println.hh>
-
namespace mln
{
- namespace transform
+ namespace canvas
{
- /// Discrete geodesic distance transform.
- template <typename I, typename N, typename D>
- mln_concrete(I)
- influence_zone_geodesic(const Image<I>& input, const Neighborhood<N>& nbh, D max);
+ /// Discrete geodesic distance canvas.
+ template <typename I, typename N, typename D,
+ typename F>
+ mln_ch_value(I, D)
+ distance_geodesic(const Image<I>& input, const Neighborhood<N>& nbh, D max,
+ F& functor);
# ifndef MLN_INCLUDE_ONLY
- namespace impl
- {
-
- namespace generic
- {
- template <typename I, typename N, typename D>
- mln_concrete(I)
- influence_zone_geodesic(const Image<I>& input_, const Neighborhood<N>& nbh_,
- D max)
+ template <typename I, typename N, typename D,
+ typename F>
+ mln_ch_value(I, D)
+ distance_geodesic(const Image<I>& input_, const Neighborhood<N>& nbh_, D max,
+ F& functor)
{
- trace::entering("transform::impl::generic::influence_zone_geodesic");
+ trace::entering("canvas::distance_geodesic");
const I& input = exact(input_);
const N& nbh = exact(nbh_);
mln_precondition(input.has_data());
+ // mln_precondition(nbh.is_valid());
mln_ch_value(I, D) dmap; // Distance map is aux data.
initialize(dmap, input);
@@ -79,19 +76,19 @@
typedef mln_site(I) P;
p_queue_fast<P> q;
- mln_concrete(I) output = clone(input);
-
// Initialization.
{
+ functor.init(input); // <-- init
level::fill(dmap, max);
mln_piter(I) p(input.domain());
mln_niter(N) n(nbh, p);
for_all(p)
- if (input(p) != 0) // p in a component
+ if (functor.inqueue_p_wrt_input_p(input(p))) // <-- inqueue_p_wrt_input_p
{
dmap(p) = 0;
for_all(n)
- if (input.domain().has(n) && input(n) == 0) // n in background
+ if (input.domain().has(n) &&
+ functor.inqueue_p_wrt_input_n(input(n))) // <-- inqueue_p_wrt_input_n
{
q.push(p);
break;
@@ -116,45 +113,21 @@
if (input.domain().has(n) && dmap(n) == max)
{
dmap(n) = dmap(p) + 1;
- output(n) = output(p);
+ functor.process(p, n); // <- process
q.push(n);
}
}
}
- trace::exiting("transform::impl::generic::influence_zone_geodesic");
- return output;
- }
-
- } // end of namespace mln::transform::impl::generic
-
- } // end of namespace mln::transform::impl
-
-
- // Facade.
-
- template <typename I, typename N, typename D>
- inline
- mln_concrete(I)
- influence_zone_geodesic(const Image<I>& input, const Neighborhood<N>& nbh,
- D distance_max)
- {
- trace::entering("transform::influence_zone_geodesic");
-
- // FIXME: tests.
-
- mln_concrete(I) output;
- output = impl::generic::influence_zone_geodesic(input, nbh, distance_max);
-
- trace::exiting("transform::influence_zone_geodesic");
- return output;
+ trace::exiting("canvas::distance_geodesic");
+ return dmap;
}
# endif // ! MLN_INCLUDE_ONLY
- } // end of namespace mln::transform
+ } // end of namespace mln::canvas
} // end of namespace mln
-#endif // ! MLN_TRANSFORM_DISTANCE_HH
+#endif // ! MLN_CANVAS_DISTANCE_GEODESIC_HH
Property changes on: mln/canvas/distance_geodesic.hh
___________________________________________________________________
Added: svn:mergeinfo
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Fix in mln_value_quant_from_ macro.
* mln/trait/value_.hh: Fix a bug.
* mln/core/image/flat_image.hh: Fix warning.
* mln/level/fill_with_value.spe.hh: Update.
* mln/level/paste.hh,
* mln/level/fill_with_value.hh: Update documentations.
core/image/flat_image.hh | 3 +++
level/fill_with_value.hh | 7 +++----
level/fill_with_value.spe.hh | 2 +-
level/paste.hh | 1 +
trait/value_.hh | 5 +++--
5 files changed, 11 insertions(+), 7 deletions(-)
Index: mln/trait/value_.hh
--- mln/trait/value_.hh (revision 2830)
+++ mln/trait/value_.hh (working copy)
@@ -49,7 +49,7 @@
# define mln_trait_value_kind(V) typename mln::trait::value_< V >::kind
# define mln_trait_value_kind_(V) mln::trait::value_< V >::kind
# define mln_trait_value_quant(V) typename mln::trait::value_< V >::quant
-# define mln_trait_value_quant_(V) mln::trait::value_< V >::quant
+# define mln_trait_value_quant_(V) mln::trait::bvalue_< V >::quant
# define mln_nbits(V) mln::trait::value_< V >::nbits
@@ -67,8 +67,9 @@
+/// FIXME: check that the -1 is correct
# define mln_value_quant_from_(C) \
- mlc_if(mln::metal::bool_<( C > 65536 || C == 0 )>, \
+ mlc_if(mln::metal::bool_<( C > 65536 || C == 0 || C == -1)>, \
mln::trait::value::quant::high, \
mln::trait::value::quant::low)
Index: mln/core/image/flat_image.hh
--- mln/core/image/flat_image.hh (revision 2830)
+++ mln/core/image/flat_image.hh (working copy)
@@ -252,6 +252,9 @@
mln_precondition(this->has_data());
mln_precondition(old_val == this->data_->val_);
this->data_->val_ = new_val;
+
+ /// Avoid warning when NDEBUG is set
+ (void) old_val;
}
template <typename T, typename S>
Index: mln/level/fill_with_value.spe.hh
--- mln/level/fill_with_value.spe.hh (revision 2830)
+++ mln/level/fill_with_value.spe.hh (working copy)
@@ -77,8 +77,8 @@
{
trace::entering("level::impl::fill_with_value_one_block");
-
I& ima = exact(ima_);
+
internal::fill_with_value_tests(ima, val);
mln_precondition(((mlc_is(mln_trait_image_pw_io(I),
trait::image::pw_io::read_write)::value ||
Index: mln/level/paste.hh
--- mln/level/paste.hh (revision 2830)
+++ mln/level/paste.hh (working copy)
@@ -88,6 +88,7 @@
mln_precondition(exact(input).has_data());
mln_precondition(exact(input).domain() <= exact(output).domain());
+ // Avoid warning when compiling with NDEBUG
(void)input;
(void)output;
}
Index: mln/level/fill_with_value.hh
--- mln/level/fill_with_value.hh (revision 2830)
+++ mln/level/fill_with_value.hh (working copy)
@@ -77,12 +77,11 @@
inline
void fill_with_value_tests(Image<I>& ima, const V&)
{
- // Avoid a warning about an undefined variable when NDEBUG
- // is not defined.
- (void) ima;
-
mlc_converts_to(mln_exact(V), mln_value(I))::check();
mln_precondition(exact(ima).has_data());
+
+ // Avoid a warning about an undefined variable when NDEBUG
+ (void) ima;
}
} // end of namespace mln::level::internal
1
0
URL: https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
ChangeLog:
2008-11-10 Dalila Benboudjema <dalila(a)lrde.epita.fr>
Add a new sandbox for Dalila.
* dalila/Makefile: New.
* dalila/demat.hh: New.
* dalila/images/factures/facture.pbm: New.
* dalila/images/factures/facture2.pbm: New.
* dalila/images/factures/facture3.pbm: New.
* dalila/images/factures: New.
* dalila/images/photos/chavez.pbm: New.
* dalila/images/photos/family.pbm: New.
* dalila/images/photos/garden.pbm: New.
* dalila/images/photos/garden_crop.pbm: New.
* dalila/images/photos/revolution.pbm: New.
* dalila/images/photos/revolution2.pbm: New.
* dalila/images/photos: New.
* dalila/images: New.
* dalila/photo.cc: New.
* dalila/start.sh: New.
* dalila/table.cc: New.
* dalila: New.
---
Makefile | 18 ++
demat.hh | 564 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
photo.cc | 64 +++++++
start.sh | 44 ++++
table.cc | 66 +++++++
5 files changed, 756 insertions(+)
Index: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture2.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture2.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture3.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/factures/facture3.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/garden_crop.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/garden_crop.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/revolution.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/revolution.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/revolution2.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/revolution2.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/chavez.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/chavez.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/garden.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/garden.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/images/photos/family.pbm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/images/photos/family.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: branches/cleanup-2008/milena/sandbox/dalila/start.sh
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/start.sh (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/start.sh (revision 2830)
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+out_location="./images-out"
+
+treat_file()
+{
+ file=$1
+ shift
+ echo "-------------------------"
+ echo " * Processing $file..."
+ echo " => Running: $1 $file"
+ echo "-------------------------"
+ d1=`date +%s`
+ time $1 $file
+ d2=`date +%s`
+ echo ""
+ dstdir="$out_location/`basename $file .pbm`"
+ echo "Moving output files to $dstdir..."
+ mkdir -p $dstdir
+ mv -f *.pbm $dstdir 2>/dev/null
+ mv -f *.ppm $dstdir 2>/dev/null
+ mv -f *.pgm $dstdir 2>/dev/null
+ echo ""
+}
+
+treat_dir()
+{
+ for file in $2/*; do
+ treat_file $file $1
+ done
+}
+
+rm -f *.pbm *.ppm *.pgm
+make
+
+# Traite une seule image
+# Usage: ./starh.sh <file.pbm> <table | photo>
+if [ $# -eq 2 ]; then
+ treat_file $1 ./$2
+else
+# Traite toutes les images
+ treat_dir ./table ./images/factures
+ treat_dir ./photo ./images/photos
+fi
Property changes on: branches/cleanup-2008/milena/sandbox/dalila/start.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: branches/cleanup-2008/milena/sandbox/dalila/demat.hh
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/demat.hh (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/demat.hh (revision 2830)
@@ -0,0 +1,564 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+# ifndef DEMAT_HH_
+# define DEMAT_HH_
+
+# include <libgen.h>
+# include <sstream>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image1d.hh>
+
+# include <mln/core/concept/function.hh>
+# include <mln/core/image/image_if.hh>
+# include <mln/core/image/sub_image.hh>
+# include <mln/core/image/cast_image.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/core/var.hh>
+# include <mln/core/routine/clone.hh>
+# include <mln/core/routine/ops.hh>
+# include <mln/core/site_set/p_vaccess.hh>
+# include <mln/core/site_set/p_set.hh>
+
+# include <mln/accu/bbox.hh>
+# include <mln/accu/count.hh>
+
+# include <mln/border/fill.hh>
+
+# include <mln/convert/to.hh>
+# include <mln/convert/to_fun.hh>
+
+# include <mln/debug/println.hh>
+# include <mln/debug/colorize.hh>
+
+# include <mln/draw/box.hh>
+
+# include <mln/fun/i2v/array.hh>
+
+# include <mln/io/pbm/load.hh>
+# include <mln/io/pbm/save.hh>
+# include <mln/io/ppm/save.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/labeling/blobs.hh>
+# include <mln/labeling/compute.hh>
+
+# include <mln/level/convert.hh>
+# include <mln/level/compute.hh>
+# include <mln/level/fill.hh>
+# include <mln/level/paste.hh>
+# include <mln/level/apply.hh>
+# include <mln/level/transform.hh>
+
+# include <mln/literal/all.hh>
+
+# include <mln/logical/not.hh>
+
+# include <mln/morpho/hit_or_miss.hh>
+# include <mln/morpho/erosion.hh>
+# include <mln/morpho/top_hat.hh>
+# include <mln/morpho/opening.hh>
+
+# include <mln/pw/all.hh>
+
+# include <mln/util/array.hh>
+
+# include <mln/value/int_u16.hh>
+# include <mln/value/rgb8.hh>
+
+# include <mln/win/hline2d.hh>
+# include <mln/win/vline2d.hh>
+
+namespace scribo
+{
+
+ namespace internal
+ {
+
+ using namespace mln;
+ using value::int_u16;
+ using value::rgb8;
+
+ char *input_file = 0;
+ int dbg_file_id = 0;
+
+ std::string output_file(const char *name, unsigned file_id)
+ {
+ std::ostringstream os;
+ os << "./"
+ << file_id
+ << "_"
+ << input_file
+ << "_"
+ << name;
+ return os.str();
+ }
+
+ void draw_component_boxes(image2d<rgb8>& output, const util::array<box2d>& boxes)
+ {
+ for (unsigned i = 1; i < boxes.nelements(); ++i)
+ if (boxes[i].is_valid())
+ {
+ output(boxes[i].center()) = literal::red;
+ draw::box(output, boxes[i], literal::red);
+ }
+ }
+
+ template <typename V>
+ void save_lbl_image(const image2d<V>& lbl, unsigned nlabels,
+ const char *filename, unsigned file_id)
+ {
+ image2d<rgb8> output = debug::colorize<image2d<rgb8>, image2d<V> >(lbl, nlabels);
+ io::ppm::save(output, output_file(filename, file_id));
+ }
+
+
+ /// Functions related to the matrix extraction
+ /// \{
+
+ void draw_hline(image2d<rgb8>& ima,
+ const box2d& box,
+ const rgb8& v)
+ {
+ unsigned ncols = box.pmax().col() - box.pmin().col();
+ point2d p1 = box.center();
+ p1.col() -= ncols / 2;
+ point2d p2 = box.center();
+ p2.col() += ncols / 2;
+
+ draw::line(ima, p1, p2, v);
+ }
+
+ void draw_vline(image2d<rgb8>& ima,
+ const box2d& box,
+ const rgb8& v)
+ {
+ unsigned nrows = box.pmax().row() - box.pmin().row();
+ point2d p1 = box.center();
+ p1.row() -= nrows / 2;
+ point2d p2 = box.center();
+ p2.row() += nrows / 2;
+
+ draw::line(ima, p1, p2, v);
+ }
+
+ void draw_row(image2d<rgb8>& ima,
+ unsigned line,
+ const rgb8& v)
+ {
+ draw::line(ima, point2d(line, 0), point2d(line, ima.ncols()), v);
+ }
+
+ void draw_col(image2d<rgb8>& ima,
+ unsigned line,
+ const rgb8& v)
+ {
+ draw::line(ima, point2d(0, line), point2d(ima.nrows(), line), v);
+ }
+
+ void
+ extract_matrix(const image2d<bool>& in,
+ std::pair<util::array<box2d>, util::array<box2d> > tboxes)
+ {
+ std::cout << "Extracting matrix..." << std::endl;
+
+ image1d<unsigned> hend(in.ncols()),
+ hrow(in.nrows()),
+ vend(in.nrows()),
+ vcol(in.ncols());
+
+ level::fill(hend, 0);
+ level::fill(hrow, 0);
+ level::fill(vend, 0);
+ level::fill(vcol, 0);
+
+ for (unsigned i = 1; i < tboxes.first.nelements(); ++i)
+ {
+ ++vend.at(tboxes.first[i].pmin().row());
+ ++vend.at(tboxes.first[i].pmax().row());
+ ++vcol.at(tboxes.first[i].center().col());
+ }
+
+ for (unsigned i = 1; i < tboxes.second.nelements(); ++i)
+ {
+ ++hend.at(tboxes.second[i].pmin().col());
+ ++hend.at(tboxes.second[i].pmax().col());
+ ++hrow.at(tboxes.second[i].center().row());
+ }
+
+#ifndef NOUT
+ image2d<rgb8> tmp(in.domain());
+ level::fill(tmp, literal::black);
+
+ for (unsigned i = 1; i < in.ncols(); ++i)
+ {
+ if (hend.at(i) > 0)
+ draw_col(tmp, i, literal::orange);
+ if (vcol.at(i) > 0)
+ draw_col(tmp, i, literal::orange);
+ }
+
+ for (unsigned i = 1; i < in.nrows(); ++i)
+ {
+ if (hrow.at(i) > 0)
+ draw_row(tmp, i, literal::magenta);
+ if (vend.at(i) > 0)
+ draw_row(tmp, i, literal::magenta);
+ }
+
+ for (unsigned i = 1; i < tboxes.first.nelements(); ++i)
+ draw_vline(tmp, tboxes.first[i], literal::green);
+
+ for (unsigned i = 1; i < tboxes.second.nelements(); ++i)
+ draw_hline(tmp, tboxes.second[i], literal::red);
+
+ io::ppm::save(tmp, output_file("matrix.ppm", 4));
+#endif
+
+ }
+
+ /// \}
+
+
+
+ /// Functions related to the table removal
+ /// \{
+
+
+ /// Extract the components bboxes.
+ util::array<box2d>
+ component_boxes(const image2d<bool>& filter)
+ {
+ std::cout << "component boxes" << std::endl;
+ int_u16 nlabels = 0;
+ image2d<int_u16> lbl = labeling::blobs(filter, c8(), nlabels);
+
+ return labeling::compute(accu::meta::bbox(), lbl, nlabels);
+ }
+
+ /// Remove table bboxes from an image.
+ void erase_table_boxes(image2d<bool>& output,
+ util::array<box2d>& boxes,
+ unsigned bbox_enlarge, unsigned dim)
+ {
+ for (unsigned i = 1; i < boxes.nelements(); ++i)
+ {
+ boxes[i].enlarge(dim, bbox_enlarge + 1);
+ boxes[i].crop_wrt(output.domain());
+ level::paste((pw::cst(false) | boxes[i] |
+ (pw::value(output) == pw::cst(true))), output);
+ }
+ }
+
+
+ /// Find table bboxes and remove them from the image.
+ std::pair<util::array<box2d>,
+ util::array<box2d> >
+ extract_tables(image2d<bool>& in,
+ image2d<rgb8>& output,
+ unsigned l)
+ {
+ typedef image2d<int_u16> I;
+ typedef accu::bbox<mln_psite_(I)> A;
+ typedef util::array<mln_result_(A)> boxes_t;
+
+
+ // Lignes verticales
+ std::cout << "Removing vertical lines" << std::endl;
+ win::vline2d vline(l);
+ image2d<bool> vfilter = morpho::erosion(in, vline);
+
+#ifndef NOUT
+ io::pbm::save(vfilter, output_file("table-vfilter.pbm", 1));
+#endif
+
+ boxes_t vboxes = component_boxes(vfilter);
+ erase_table_boxes(in, vboxes, (l / 2), 0);
+
+
+ // Lignes horizontales
+ std::cout << "Removing horizontal lines" << std::endl;
+ win::hline2d hline(l);
+ image2d<bool> hfilter = morpho::erosion(in, hline);
+
+#ifndef NOUT
+ io::pbm::save(hfilter, output_file("table-hfilter.pbm", 2));
+#endif
+
+ boxes_t hboxes = component_boxes(hfilter);
+ erase_table_boxes(in, hboxes, (l / 2), 1);
+
+
+#ifndef NOUT
+ image2d<rgb8> tmp = clone(output);
+ draw_component_boxes(tmp, vboxes);
+ draw_component_boxes(tmp, hboxes);
+ io::ppm::save(tmp, output_file("table-filtered.ppm", 3));
+#endif
+
+ return std::make_pair(vboxes, hboxes);
+ }
+
+ /// \}
+ /// End of functions related to the table removal.
+
+
+ /// Function related to text extraction
+ /// \{
+
+ inline
+ int_u16
+ most_left(const fun::i2v::array<int_u16>& left_link, unsigned i)
+ {
+ while (left_link(i) != i)
+ i = left_link(i);
+ return i;
+ }
+
+ inline
+ int_u16
+ uncurri_left_link(fun::i2v::array<int_u16>& left_link, unsigned i)
+ {
+ if (left_link(i) != i)
+ left_link(i) = uncurri_left_link(left_link, left_link(i));
+ return left_link(i);
+ }
+
+ template <typename V>
+ void
+ remove_small_comps_i2v(image2d<V>& lbl,
+ V& nlabels,
+ unsigned min_comp_size)
+ {
+ std::cout << "Removing small components smaller than "
+ << min_comp_size << " sites among " << nlabels
+ << "components" << std::endl;
+
+ typedef accu::count<mln_psite(image2d<V>)> accu_count_t;
+
+ util::array<mln_result(accu_count_t)> nsitecomp
+ = labeling::compute(accu_count_t(), lbl, nlabels);
+
+ V ncomp = 0;
+
+ fun::i2v::array<V> f(nsitecomp.nelements());
+ f(0) = 0;
+
+ for (unsigned i = 1; i <= nlabels; ++i)
+ {
+ if (nsitecomp[i] < min_comp_size)
+ f(i) = 0;
+ else
+ f(i) = ++ncomp;
+ }
+
+ lbl = level::transform(lbl, f);
+ nlabels = ncomp;
+
+#ifndef NOUT
+ save_lbl_image(lbl, nlabels, "lbl-small-comps-removed.pgm", 6);
+#endif
+ }
+
+
+ /// Merge bboxes according to their left box neighbor.
+ util::array< box2d >
+ group_bboxes(fun::i2v::array<int_u16>& left_link, image2d<int_u16>& lbl,
+ util::array<box2d>& cboxes, unsigned ncomp)
+ {
+ // Currify left_link lookup table and compute text area bboxes.
+ util::array< accu::bbox<point2d> > tboxes;
+ tboxes.resize(ncomp + 1);
+ for (unsigned i = 1; i <= ncomp; ++i)
+ tboxes[uncurri_left_link(left_link, i)].take(cboxes[i]);
+
+ //Update labels
+ lbl = level::transform(lbl, left_link);
+
+#ifndef NOUT
+ save_lbl_image(lbl, ncomp, "lbl-grouped-boxes.pgm", 7);
+#endif
+
+ util::array<box2d> result;
+ for (unsigned i = 1; i <= ncomp; ++i)
+ if (tboxes[i].is_valid())
+ result.append(tboxes[i].to_result());
+
+ return result;
+ }
+
+
+ /// Update the lookup table \p left if a neighbor is found on the right of
+ /// the current bbox.
+ void update_link(fun::i2v::array<int_u16>& left_link, image2d<int_u16>& lbl,
+ const point2d& p, const point2d& c,
+ unsigned i, int dmax)
+ {
+ if (lbl.domain().has(p) && lbl(p) != 0u && lbl(p) != i
+ && (math::abs(p.col() - c.col())) < dmax)
+ {
+ if (left_link(lbl(p)) == lbl(p) && most_left(left_link, i) != lbl(p))
+ left_link(lbl(p)) = i;
+// else
+// left_link(lbl(p)) = 0;//FIXME: should be uncommented?
+ }
+ }
+
+
+
+ /// Map each character bbox to its left bbox neighbor if possible.
+ /// Iterate to the right but link boxes to the left.
+ fun::i2v::array<int_u16>
+ link_character_bboxes(image2d<int_u16>& lbl,
+ const util::array<box2d>& cboxes,
+ unsigned ncomp,
+ unsigned bbox_distance)
+ {
+ fun::i2v::array<int_u16> left_link;
+ left_link.resize(ncomp + 1);
+
+ for (unsigned i = 0; i <= ncomp; ++i)
+ left_link(i) = i;
+
+ for (unsigned i = 1; i <= ncomp; ++i)
+ {
+ unsigned midcol = (cboxes[i].pmax().col() - cboxes[i].pmin().col()) / 2;
+ int dmax = midcol + bbox_distance;
+ point2d c = cboxes[i].center();
+ /// First site on the right of the central site
+ point2d p(c.row(), c.col() + 1);
+
+ // FIXME: Lemmings with a condition on the distance => write a special version?
+ while (lbl.domain().has(p) && (lbl(p) == 0u || lbl(p) == i)
+ && math::abs(p.col() - c.col()) < dmax)
+ ++p.col();
+
+ update_link(left_link, lbl, p, c, i, dmax);
+ }
+
+ return left_link;
+ }
+
+ util::array<box2d>
+ extract_text(image2d<bool>& in_,
+ image2d<rgb8>& output,
+ unsigned bbox_distance,
+ unsigned min_comp_size)
+ {
+ std::cout << "extracting text..." << std::endl;
+
+ typedef int_u16 V;
+ typedef image2d<V> I;
+ typedef util::array<box2d> boxes_t;
+
+ // Extract edges.
+ //win::rectangle2d l(5, 5);
+ unsigned l = 11;
+ //win::hline2d hline(l);
+ win::vline2d vline(l);
+ //image2d<bool> in = morpho::top_hat_white(in_, l);
+ image2d<bool> in = morpho::opening(in_, vline);
+ io::pbm::save(in, output_file("OuvertureSizevLine11.ppm", 9));
+
+ // Find character bboxes.
+ V nlabels;
+ image2d<V> lbl = labeling::blobs(in, c8(), nlabels);
+
+ //Remove small components.
+ remove_small_comps_i2v(lbl, nlabels, min_comp_size);
+
+ boxes_t cboxes = labeling::compute(accu::meta::bbox(), lbl, nlabels);
+
+#ifndef NOUT
+ image2d<rgb8> tmp = clone(output);
+ draw_component_boxes(tmp, cboxes);
+ io::ppm::save(tmp, output_file("character-bboxes.ppm", 5));
+#endif
+
+ //merge_bboxes(cboxes, lbl, nlabels);
+
+ //Link character bboxes to their left neighboor if possible.
+ fun::i2v::array<int_u16> left =
+ link_character_bboxes(lbl, cboxes, nlabels, bbox_distance);
+
+ //Merge character bboxes according to their left neighbor.
+ util::array<box2d> tboxes = group_bboxes(left, lbl, cboxes, nlabels);
+
+ return tboxes;
+ }
+
+ /// \}
+ /// End of functions related to text extraction
+
+ } // end of namespace scribo::internal
+
+
+ // Facade
+ void demat(char *argv[], bool treat_tables)
+ {
+ using namespace mln;
+ using value::rgb8;
+
+ border::thickness = 21;
+ trace::quiet = true;
+
+ //Useful debug variables
+ internal::input_file = basename(argv[1]);
+ unsigned l = 101;
+ unsigned bbox_distance = 25;
+ unsigned min_comp_size = 5;
+
+ //Load image
+ image2d<bool> in;
+ io::pbm::load(in, argv[1]);
+ in = logical::not_(in);
+
+ image2d<rgb8> output = level::convert(rgb8(), in);
+
+ std::pair<util::array<box2d>,
+ util::array<box2d> > tblboxes;
+ if (treat_tables)
+ {
+ tblboxes = internal::extract_tables(in, output, l);
+ internal::extract_matrix(in, tblboxes);
+ }
+
+ util::array<box2d> tboxes =
+ internal::extract_text(in, output, bbox_distance, min_comp_size);
+
+ internal::draw_component_boxes(output, tboxes);
+ io::ppm::save(output, internal::output_file("out.ppm", 8));
+
+ /// Use txt bboxes here with Tesseract
+ /// for (i = 1; i < tboxes.nelements(); ++i)
+ /// tesseract(in | tboxes[i])
+ }
+
+} // end of namespace scribo
+
+# endif // ! DEMAT_HH
Index: branches/cleanup-2008/milena/sandbox/dalila/table.cc
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/table.cc (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/table.cc (revision 2830)
@@ -0,0 +1,66 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+
+#include "demat.hh"
+
+int main(int argc, char*argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc < 2)
+ {
+ std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
+ << std::endl << std::endl
+ << std::endl
+ << "=========="
+ << std::endl << std::endl
+ << "<in.pbm> B/W inverted input image."
+ << std::endl << std::endl
+/* << "<out.ppm> RGB8 output image."
+ << std::endl << std::endl
+ << "<l> Line length"
+ << std::endl << std::endl
+ << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
+ << std::endl << std::endl
+ << "<min_comp_nsites> Minimum site count of a character/text component."
+ << std::endl
+ << " If a component have a site count lesser than this value, it is erased."
+ << std::endl << std::endl
+ << std::endl*/
+ << "=========="
+ << std::endl << std::endl
+ << "HINT: compile with -DNOUT to avoid debug images."
+ << std::endl << std::endl;
+ return 1;
+ }
+
+ scribo::demat(argv, true);
+
+ return 0;
+}
Index: branches/cleanup-2008/milena/sandbox/dalila/Makefile
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/Makefile (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/Makefile (revision 2830)
@@ -0,0 +1,18 @@
+OLENA_INCLUDE_PATH=../../../
+CXXFLAGS=-I$(OLENA_INCLUDE_PATH) -ggdb3 -Wall -O1 -DNDEBUG
+
+all: photo table
+
+photo: demat.hh photo.cc
+ g++ $(CXXFLAGS) photo.cc -o photo
+
+table: demat.hh table.cc
+ g++ $(CXXFLAGS) table.cc -o table
+
+dclean: clean
+ rm -f photo
+ rm -f table
+
+clean:
+ rm -f *.pbm *.pgm *.ppm
+
Index: branches/cleanup-2008/milena/sandbox/dalila/photo.cc
===================================================================
--- branches/cleanup-2008/milena/sandbox/dalila/photo.cc (revision 0)
+++ branches/cleanup-2008/milena/sandbox/dalila/photo.cc (revision 2830)
@@ -0,0 +1,64 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+
+#include "demat.hh"
+
+int main(int argc, char*argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc < 2)
+ {
+ std::cout << argv[0] << " <in.pbm> <out.pgm> <l> <bbox_larger> <bbox_distance> <min_comp_nsites>" << std::endl
+ << std::endl << std::endl
+ << std::endl
+ << "=========="
+ << std::endl << std::endl
+ << "<in.pbm> B/W inverted input image."
+ << std::endl << std::endl
+/* << "<out.ppm> RGB8 output image."
+ << std::endl << std::endl
+ << "<bbox_distance> Maximum distance between character bounding boxes. Used for bbox grouping."
+ << std::endl << std::endl
+ << "<min_comp_nsites> Minimum site count of a character/text component."
+ << std::endl
+ << " If a component have a site count lesser than this value, it is erased."
+ << std::endl << std::endl
+ << std::endl*/
+ << "=========="
+ << std::endl << std::endl
+ << "HINT: compile with -DNOUT to avoid debug images."
+ << std::endl << std::endl;
+ return 1;
+ }
+
+ scribo::demat(argv, false);
+
+ return 0;
+}
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
INIM: Classif: Update palette proj.
* inim/classif/src/iccvg04.cc: Fix warning.
* inim/classif/src/proj.hh: Update palette prj.
* inim/classif/Makefile: Add warning flag.
Makefile | 8 ++++----
src/iccvg04.cc | 2 --
src/proj.hh | 10 +++++++---
3 files changed, 11 insertions(+), 9 deletions(-)
Index: inim/classif/src/iccvg04.cc
--- inim/classif/src/iccvg04.cc (revision 2828)
+++ inim/classif/src/iccvg04.cc (working copy)
@@ -53,7 +53,6 @@
const value::int_u8 v = 255 / f; // FIXME
image3d<unsigned> histo(v,v,v);
level::fill(histo, 0);
- unsigned i = 0;
mln_piter(I) p(ima.domain());
for_all(p)
@@ -163,7 +162,6 @@
image3d<unsigned> histo_filtered(histo.domain());
morpho::opening_volume(histo, c6(), lambda, histo_filtered);
-
//watershed over histo_closure
unsigned nbasins = 0;
image3d<unsigned> ws = morpho::meyer_wst(arith::revert(histo_filtered),
Index: inim/classif/src/proj.hh
--- inim/classif/src/proj.hh (revision 2828)
+++ inim/classif/src/proj.hh (working copy)
@@ -40,7 +40,7 @@
template <typename T, typename A>
image2d<mln_result(A)>
- proj(const image3d<T>& input, A a)
+ proj(const image3d<T>& input, A)
{
image2d<A> acc(geom::nslis(input), geom::nrows(input));
mln_piter(image3d<T>) p(input.domain());
@@ -69,11 +69,15 @@
image2d<value::rgb8> out(proj_class.domain());
level::fill(out, literal::white);
- mln_piter(image2d<value::int_u8>) p(hproj.domain());
+ mln_piter(image2d<value::int_u8>) p(proj_class.domain());
for_all(p)
if (hproj(p) > 0)
+ {
+ if (proj_class(p) > 0)
out(p) = convert::to<value::rgb8>(mean[proj_class(p)]);
-
+ else
+ out(p) = literal::red;
+ }
io::ppm::save(out, fn);
}
Index: inim/classif/Makefile
--- inim/classif/Makefile (revision 2828)
+++ inim/classif/Makefile (working copy)
@@ -21,18 +21,18 @@
$(ICCVG): $(ICCVG_SRC)
- g++ $(ICCVG_INCLUDES) -O1 -DNDEBUG $(ICCVG_SRC) -o $(ICCVG)
+ g++ $(ICCVG_INCLUDES) -Wall -W -O1 -DNDEBUG $(ICCVG_SRC) -o $(ICCVG)
$(ICCVG_DBG): $(ICCVG_SRC)
- g++ $(ICCVG_INCLUDES) -O0 -g3 -ggdb3 $(ICCVG_SRC) -o $(ICCVG_DBG)
+ g++ $(ICCVG_INCLUDES) -Wall -W -O0 -g3 -ggdb3 $(ICCVG_SRC) -o $(ICCVG_DBG)
$(V2): $(V2_SRC)
- g++ $(V2_INCLUDES) -O1 -DNDEBUG $(V2_SRC) -o $(V2)
+ g++ $(V2_INCLUDES) -Wall -W -O1 -DNDEBUG $(V2_SRC) -o $(V2)
$(V2_DBG): $(V2_SRC) .dep_v2
- g++ $(V2_INCLUDES) -O0 -g3 -ggdb3 $(V2_SRC) -o $(V2_DBG)
+ g++ $(V2_INCLUDES) -Wall -W -O0 -g3 -ggdb3 $(V2_SRC) -o $(V2_DBG)
.PHONY:clean check check-debug valgrind .dep_iccvg .dep_v2
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add a couple of geodesic transforms.
* mln/transform/influence_zone_geodesic.hh: New.
* mln/transform/all.hh: Update.
* tests/transform/influence_zone_geodesic.cc: New.
* mln/transform/distance_geodesic.hh: New.
* tests/transform/distance_geodesic.cc: New.
mln/transform/all.hh | 13 +-
mln/transform/distance_geodesic.hh | 153 +++++++++++++++++++++++++++
mln/transform/influence_zone_geodesic.hh | 160 +++++++++++++++++++++++++++++
tests/transform/distance_geodesic.cc | 52 +++++++++
tests/transform/influence_zone_geodesic.cc | 58 ++++++++++
5 files changed, 430 insertions(+), 6 deletions(-)
Index: tests/transform/distance_geodesic.cc
--- tests/transform/distance_geodesic.cc (revision 0)
+++ tests/transform/distance_geodesic.cc (revision 0)
@@ -0,0 +1,52 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/transform/distance_geodesic.cc
+///
+/// Test on mln::transform::distance_geodesic.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/level/fill.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/transform/distance_geodesic.hh>
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ image2d<bool> input(9, 9);
+ level::fill(input, false);
+ input.at(4, 4) = true;
+
+ image2d<int_u8> output = transform::distance_geodesic(input, c4(), int_u8(4));
+ debug::println(output);
+}
Index: tests/transform/influence_zone_geodesic.cc
--- tests/transform/influence_zone_geodesic.cc (revision 0)
+++ tests/transform/influence_zone_geodesic.cc (revision 0)
@@ -0,0 +1,58 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/transform/influence_zone_geodesic.cc
+///
+/// Test on mln::transform::influence_zone_geodesic.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/make/image2d.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/transform/influence_zone_geodesic.hh>
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ int_u8 vals[] =
+ { 1, 1, 0, 0, 0, 0, 3,
+ 1, 1, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0 };
+ image2d<int_u8> input = make::image2d(vals);
+
+ image2d<int_u8> output = transform::influence_zone_geodesic(input, c4(), int_u8(1));
+ debug::println(output);
+}
Index: mln/transform/influence_zone_geodesic.hh
--- mln/transform/influence_zone_geodesic.hh (revision 0)
+++ mln/transform/influence_zone_geodesic.hh (revision 0)
@@ -0,0 +1,160 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_TRANSFORM_INFLUENCE_ZONE_GEODESIC_HH
+# define MLN_TRANSFORM_INFLUENCE_ZONE_GEODESIC_HH
+
+/// \file mln/transform/influence_zone_geodesic.hh
+///
+/// Discrete geodesic distance transform.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/site_set/p_queue_fast.hh>
+# include <mln/core/routine/clone.hh>
+# include <mln/level/fill.hh>
+
+# include <mln/debug/println.hh>
+
+
+namespace mln
+{
+
+ namespace transform
+ {
+
+ /// Discrete geodesic distance transform.
+ template <typename I, typename N, typename D>
+ mln_concrete(I)
+ influence_zone_geodesic(const Image<I>& input, const Neighborhood<N>& nbh, D max);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I, typename N, typename D>
+ mln_concrete(I)
+ influence_zone_geodesic(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ D max)
+ {
+ trace::entering("transform::impl::generic::influence_zone_geodesic");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(input.has_data());
+
+ mln_ch_value(I, D) dmap; // Distance map is aux data.
+ initialize(dmap, input);
+
+ typedef mln_site(I) P;
+ p_queue_fast<P> q;
+
+ mln_concrete(I) output = clone(input);
+
+ // Initialization.
+ {
+ level::fill(dmap, max);
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if (input(p) != 0) // p in a component
+ {
+ dmap(p) = 0;
+ for_all(n)
+ if (input.domain().has(n) && input(n) == 0) // n in background
+ {
+ q.push(p);
+ break;
+ }
+ }
+ }
+
+ // Propagation.
+ {
+ P p;
+ mln_niter(N) n(nbh, p);
+ while (! q.is_empty())
+ {
+ p = q.pop_front();
+ if (dmap(p) == max)
+ {
+ // Saturation so stop.
+ q.clear();
+ break;
+ }
+ for_all(n)
+ if (input.domain().has(n) && dmap(n) == max)
+ {
+ dmap(n) = dmap(p) + 1;
+ output(n) = output(p);
+ q.push(n);
+ }
+ }
+ }
+
+ trace::exiting("transform::impl::generic::influence_zone_geodesic");
+ return output;
+ }
+
+ } // end of namespace mln::transform::impl::generic
+
+ } // end of namespace mln::transform::impl
+
+
+ // Facade.
+
+ template <typename I, typename N, typename D>
+ inline
+ mln_concrete(I)
+ influence_zone_geodesic(const Image<I>& input, const Neighborhood<N>& nbh,
+ D distance_max)
+ {
+ trace::entering("transform::influence_zone_geodesic");
+
+ // FIXME: tests.
+
+ mln_concrete(I) output;
+ output = impl::generic::influence_zone_geodesic(input, nbh, distance_max);
+
+ trace::exiting("transform::influence_zone_geodesic");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::transform
+
+} // end of namespace mln
+
+
+#endif // ! MLN_TRANSFORM_DISTANCE_HH
Index: mln/transform/all.hh
--- mln/transform/all.hh (revision 2827)
+++ mln/transform/all.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,22 +28,23 @@
#ifndef MLN_TRANSFORM_ALL_HH
# define MLN_TRANSFORM_ALL_HH
-/*! \file mln/transform/all.hh
- *
- * \brief File that includes all "point-wise" expression tools.
- */
+/// \file mln/transform/all.hh
+///
+/// File that includes all transforms.
namespace mln
{
- /// Namespace of "point-wise" expression tools.
+ /// Namespace of transforms.
namespace transform {}
} // end of namespace mln
# include <mln/transform/distance.hh>
+# include <mln/transform/distance_geodesic.hh>
+# include <mln/transform/influence_zone_geodesic.hh>
#endif // ! MLN_TRANSFORM_ALL_HH
Index: mln/transform/distance_geodesic.hh
--- mln/transform/distance_geodesic.hh (revision 0)
+++ mln/transform/distance_geodesic.hh (revision 0)
@@ -0,0 +1,153 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_TRANSFORM_DISTANCE_GEODESIC_HH
+# define MLN_TRANSFORM_DISTANCE_GEODESIC_HH
+
+/// \file mln/transform/distance_geodesic.hh
+///
+/// Discrete geodesic distance transform.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/site_set/p_queue_fast.hh>
+# include <mln/level/fill.hh>
+
+
+
+namespace mln
+{
+
+ namespace transform
+ {
+
+ /// Discrete geodesic distance transform.
+ template <typename I, typename N, typename D>
+ mln_ch_value(I, D)
+ distance_geodesic(const Image<I>& input, const Neighborhood<N>& nbh, D max);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I, typename N, typename D>
+ mln_ch_value(I, D)
+ distance_geodesic(const Image<I>& input_, const Neighborhood<N>& nbh_, D max)
+ {
+ trace::entering("transform::impl::generic::distance_geodesic");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(input.has_data());
+
+ mln_ch_value(I, D) output;
+ initialize(output, input);
+
+ typedef mln_site(I) P;
+ p_queue_fast<P> q;
+
+ // Initialization.
+ {
+ level::fill(output, max);
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if (input(p) == true) // p in object
+ {
+ output(p) = 0;
+ for_all(n)
+ if (input.domain().has(n) && input(n) == false) // n in background
+ {
+ q.push(p);
+ break;
+ }
+ }
+ }
+
+ // Propagation.
+ {
+ P p;
+ mln_niter(N) n(nbh, p);
+ while (! q.is_empty())
+ {
+ p = q.pop_front();
+ for_all(n)
+ if (input.domain().has(n) && output(n) == max)
+ {
+ output(n) = output(p) + 1;
+ if (output(n) == max)
+ {
+ // Saturation so stop.
+ q.clear();
+ break;
+ }
+ q.push(n);
+ }
+ }
+ }
+
+ trace::exiting("transform::impl::generic::distance_geodesic");
+ return output;
+ }
+
+ } // end of namespace mln::transform::impl::generic
+
+ } // end of namespace mln::transform::impl
+
+
+ // Facade.
+
+ template <typename I, typename N, typename D>
+ inline
+ mln_ch_value(I, D)
+ distance_geodesic(const Image<I>& input, const Neighborhood<N>& nbh, D max)
+ {
+ trace::entering("transform::distance_geodesic");
+
+ // FIXME: tests.
+
+ mln_ch_value(I, D) output;
+ output = impl::generic::distance_geodesic(input, nbh, max);
+
+ trace::exiting("transform::distance_geodesic");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::transform
+
+} // end of namespace mln
+
+
+#endif // ! MLN_TRANSFORM_DISTANCE_HH
1
0
cleanup-2008 2827: Add directional filters for the gaussian and its derivatives.
by Nicolas Ballas 07 Nov '08
by Nicolas Ballas 07 Nov '08
07 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Add directional filters for the gaussian and its derivatives.
* tests/linear/gaussian.cc: Update tests.
* mln/linear/gaussian.hh: Add directional filters.
mln/linear/gaussian.hh | 293 ++++++++++++++++++++++++++++++++++++++++++++---
tests/linear/gaussian.cc | 3
2 files changed, 281 insertions(+), 15 deletions(-)
Index: tests/linear/gaussian.cc
--- tests/linear/gaussian.cc (revision 2826)
+++ tests/linear/gaussian.cc (working copy)
@@ -44,6 +44,8 @@
#include "tests/data.hh"
+#include <mln/trace/all.hh>
+
int main()
@@ -54,6 +56,5 @@
io::pgm::load(lena, MLN_IMG_DIR "/lena.pgm");
image2d<value::int_u8> out = linear::gaussian(lena, 5.1f);
-
io::pgm::save(out, "out.pgm");
}
Index: mln/linear/gaussian.hh
--- mln/linear/gaussian.hh (revision 2826)
+++ mln/linear/gaussian.hh (working copy)
@@ -43,6 +43,8 @@
# include <mln/geom/ncols.hh>
# include <mln/geom/nrows.hh>
+# include <mln/trait/image/props.hh>
+
# include <mln/extension/adjust_fill.hh>
# include <mln/level/stretch.hh>
@@ -51,6 +53,8 @@
# include <vector>
# include <cmath>
+# include <mln/debug/println.hh>
+
namespace mln
{
@@ -247,7 +251,6 @@
}
// Combine results from causal and non-causal parts.
-
current = start;
for (int i = 0; i < len; ++i)
{
@@ -331,8 +334,10 @@
float scale0 = 1 + exp2b0 - 2 * cos0 * expb0;
scale0 *= scale0 * scale0;
- float scaleA = a1 * sin0 * expb0 * (1 + expb0 * (2 * cos0 * (1 + exp2b0) + exp2b0 - 6)) +
- a0 * expb0 * (2 * expb0 * (2 - cos0 * cos0) * (1 - exp2b0) - cos0 * (1 - exp2b0 * exp2b0));
+ float scaleA = a1 * sin0 * expb0 *
+ (1 + expb0 * (2 * cos0 * (1 + exp2b0) + exp2b0 - 6)) +
+ a0 * expb0 * (2 * expb0 * (2 - cos0 * cos0) *
+ (1 - exp2b0) - cos0 * (1 - exp2b0 * exp2b0));
float expb1 = exp(b1);
float exp2b1 = exp(2.0 * b1);
@@ -340,8 +345,10 @@
float scale1 = 1 + exp2b1 - 2 * cos1 * expb1;
scale1 *= scale1 * scale1;
- float scaleC = c1 * sin1 * expb1 * (1 + expb1 * (2 * cos1 * (1 + exp2b1) + exp2b1 - 6)) +
- c0 * expb1 * (2 * expb1 * (2 - cos1 * cos1) * (1 - exp2b1) - cos1 * (1 - exp2b1 * exp2b1));
+ float scaleC = c1 * sin1 * expb1 *
+ (1 + expb1 * (2 * cos1 * (1 + exp2b1) + exp2b1 - 6)) +
+ c0 * expb1 * (2 * expb1 * (2 - cos1 * cos1) *
+ (1 - exp2b1) - cos1 * (1 - exp2b1 * exp2b1));
float sumA = scaleA / scale0;
float sumC = scaleC / scale1;
@@ -350,29 +357,114 @@
return (sumA + sumC);
}
+
+ template <class I, class F>
+ inline
+ void
+ generic_filter_(trait::image::dimension::one_d,
+ Image<I>& img_, const F& coef, int dir)
+ {
+ I& img = exact(img_);
+ mln_precondition(dir < I::site::dim);
+
+
+ recursivefilter_<mln_value(I)>(img, coef,
+ point1d(-img.border()),
+ point1d(geom::ninds(img) - 1 +
+ img.border()),
+ geom::ninds(img) + 2 * img.border(),
+ dpoint1d(1));
+ }
+
template <class I, class F>
inline
void
- generic_filter_(Image<I>& img_, const F& coef)
+ generic_filter_(trait::image::dimension::two_d,
+ Image<I>& img_, const F& coef, int dir)
{
I& img = exact(img_);
+ mln_precondition(dir < I::site::dim);
+
+
+ if (dir == 0)
+ {
// Apply on rows.
for (unsigned j = 0; j < geom::ncols(img); ++j)
recursivefilter_< mln_value(I) >(img, coef,
point2d(-img.border(), j),
- point2d(geom::nrows(img) - 1 + img.border(), j),
+ point2d(geom::nrows(img) - 1 +
+ img.border(), j),
geom::nrows(img) + 2 * img.border(),
dpoint2d(1, 0));
+ }
+ if (dir == 1)
+ {
// Apply on columns.
for (unsigned i = 0; i < geom::nrows(img); ++i)
recursivefilter_< mln_value(I) >(img, coef,
point2d(i, -img.border()),
- point2d(i, geom::ncols(img) - 1 + img.border()),
+ point2d(i, geom::ncols(img) - 1 +
+ img.border()),
geom::ncols(img) + 2 * img.border(),
dpoint2d(0, 1));
}
+ }
+
+ template <class I, class F>
+ inline
+ void
+ generic_filter_(trait::image::dimension::three_d,
+ Image<I>& img_, const F& coef, int dir)
+ {
+ I& img = exact(img_);
+ mln_precondition(dir < I::site::dim);
+
+ if (dir == 0)
+ {
+ // Apply on slices.
+ for (unsigned j = 0; j < geom::nrows(img); ++j)
+ for (unsigned k = 0; k < geom::ncols(img); ++k)
+ recursivefilter_<mln_value(I)>(img, coef,
+ point3d(-img.border(), j , k),
+ point3d(geom::nslis(img) - 1 +
+ img.border(), j, k),
+ geom::nslis(img) + 2 *
+ img.border(),
+ dpoint3d(1, 0, 0));
+ }
+
+
+ if (dir == 1)
+ {
+ // Apply on rows.
+ for (unsigned i = 0; i < geom::nslis(img); ++i)
+ for (unsigned k = 0; k < geom::ncols(img); ++k)
+ recursivefilter_<mln_value(I)>(img, coef,
+ point3d(i, -img.border(), k),
+ point3d(i, geom::nrows(img) - 1 +
+ img.border(), k),
+ geom::nrows(img) + 2 *
+ img.border(),
+ dpoint3d(0, 1, 0));
+ }
+
+ if (dir == 2)
+ {
+ // Apply on columns.
+ for (unsigned i = 0; i < geom::nslis(img); ++i)
+ for (unsigned j = 0; j < geom::nrows(img); ++i)
+ recursivefilter_<mln_value(I)>(img, coef,
+ point3d(i, j, -img.border()),
+ point3d(i, j, geom::ncols(img) -
+ 1 + img.border()),
+ geom::ncols(img) + 2 *
+ img.border(),
+ dpoint3d(0, 0, 1));
+ }
+ }
+
template <class I, class F, class O>
@@ -391,15 +483,42 @@
// On tiny sigma, Derich algorithm doesn't work.
// It is the same thing that to convolve with a Dirac.
if (sigma > 0.006)
- generic_filter_(work_img, coef);
- /* Convert the result image to the user-requested datatype.
- FIXME: We are making an unnecessary copy in case the
- user expects a ntg::float_s image. */
- //level::stretch(work_img, out);
+ for (int i = 0; i < I::site::dim; ++i)
+ generic_filter_(mln_trait_image_dimension(I)(),
+ work_img, coef, i);
+
+ // FIXME deal with overflow problem
+ // for instance, when we paste a float image into a int_u8 images.
+ level::paste(work_img, out);
+ }
+
+ template <class I, class F, class O>
+ inline
+ void
+ generic_filter_common_(trait::value::nature::scalar,
+ const Image<I>& in,
+ const F& coef,
+ float sigma,
+ Image<O>& out,
+ int dir)
+ {
+ mln_ch_value(O, float) work_img(exact(in).domain());
+ level::paste(in, work_img);
+ extension::adjust_fill(work_img, 4, 0);
+
+ // On tiny sigma, Derich algorithm doesn't work.
+ // It is the same thing that to convolve with a Dirac.
+ if (sigma > 0.006)
+ generic_filter_(mln_trait_image_dimension(I)(),
+ work_img, coef, dir);
+
+ // FIXME deal with overflow problem
+ // for instance, when we paste a float image into a int_u8 images.
level::paste(work_img, out);
}
+
template <class I, class F, class O>
inline
void
@@ -417,13 +536,145 @@
// On tiny sigma, Derich algorithm doesn't work.
// It is the same thing that to convolve with a Dirac.
if (sigma > 0.006)
- generic_filter_(out, coef);
+ for (int i = 0; i < I::site::dim; ++i)
+ generic_filter_(mln_trait_image_dimension(I)(),
+ out, coef, i);
+ }
+
+ template <class I, class F, class O>
+ inline
+ void
+ generic_filter_common_(trait::value::nature::vectorial,
+ const Image<I>& in,
+ const F& coef,
+ float sigma,
+ Image<O>& out,
+ int dir)
+ {
+ // typedef algebra::vec<3, float> vec3f;
+ // mln_ch_value(O, vec3f) work_img(exact(in).domain());
+ // FIXME : paste does not work (rgb8 -> vec3f).
+ level::paste(in, out);
+
+ // On tiny sigma, Derich algorithm doesn't work.
+ // It is the same thing that to convolve with a Dirac.
+ if (sigma > 0.006)
+ generic_filter_(mln_trait_image_dimension(I)(),
+ out, coef, dir);
}
} // end of namespace mln::linear::impl
+
// Facade.
+
+ /*! Apply an approximated gaussian filter of \p sigma on \p input.
+ * on a specific direction \p dir
+ * if \p dir = 0, the filter is applied on the first image dimension.
+ * if \p dir = 1, the filter is applied on the second image dimension.
+ * And so on...
+ *
+ * \pre input.has_data
+ * \pre dir < dimension(input)
+ */
+ template <class I>
+ inline
+ mln_concrete(I)
+ gaussian(const Image<I>& input, float sigma, int dir)
+ {
+ mln_precondition(exact(input).has_data());
+ mln_precondition(dir < I::site::dim);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+ impl::recursivefilter_coef_ coef(1.68f, 3.735f,
+ 1.783f, 1.723f,
+ -0.6803f, -0.2598f,
+ 0.6318f, 1.997f,
+ sigma, impl::gaussian_norm_coef_);
+
+ impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
+ input, coef, sigma, output, dir);
+ return output;
+ }
+
+
+ /*! Apply an approximated first derivative gaussian filter of \p sigma on
+ * \p input.
+ * on a specific direction \p dir
+ * if \p dir = 0, the filter is applied on the first image dimension.
+ * if \p dir = 1, the filter is applied on the second image dimension.
+ * And so on...
+ *
+ * \pre input.has_data
+ * \pre dir < dimension(input)
+ */
+ template <class I>
+ inline
+ mln_concrete(I)
+ gaussian_1st_derivative(const Image<I>& input, float sigma, int dir)
+ {
+ mln_precondition(exact(input).has_data());
+ mln_precondition(dir < I::site::dim);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ impl::recursivefilter_coef_
+ coef(-0.6472f, -4.531f,
+ 1.527f, 1.516f,
+ 0.6494f, 0.9557f,
+ 0.6719f, 2.072f,
+ sigma, impl::gaussian_1st_deriv_coef_norm_);
+
+ impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
+ input, coef, sigma, output, dir);
+ return output;
+ }
+
+ /*! Apply an approximated second derivative gaussian filter of \p sigma on
+ * \p input.
+ * on a specific direction \p dir
+ * if \p dir = 0, the filter is applied on the first image dimension.
+ * if \p dir = 1, the filter is applied on the second image dimension.
+ * And so on...
+ *
+ * \pre input.has_data
+ * \pre dir < dimension(input)
+ */
+ template <class I>
+ inline
+ mln_concrete(I)
+ gaussian_2nd_derivative(const Image<I>& input, float sigma, int dir)
+ {
+ mln_precondition(exact(input).has_data());
+ mln_precondition(dir < I::site::dim);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ impl::recursivefilter_coef_
+ coef(-1.331f, 3.661f,
+ 1.24f, 1.314f,
+ 0.3225f, -1.738f,
+ 0.748f, 2.166f,
+ sigma, impl::gaussian_2nd_deriv_coef_norm_);
+
+ impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
+ input, coef, sigma, output, dir);
+ return output;
+ }
+
+
+
+
+
+ /*! Apply an approximated gaussian filter of \p sigma on \p input.
+ * This filter is applied in all the input image direction.
+ *
+ * \pre input.has_data
+ */
template <class I>
inline
mln_concrete(I)
@@ -446,6 +697,13 @@
return output;
}
+
+ /*! Apply an approximated first derivative gaussian filter of \p sigma on
+ * \p input
+ * This filter is applied in all the input image direction.
+ *
+ * \pre input.has_data
+ */
template <class I>
inline
mln_concrete(I)
@@ -467,6 +725,13 @@
return output;
}
+
+ /*! Apply an approximated second derivative gaussian filter of \p sigma on
+ * \p input
+ * This filter is applied in all the input image direction.
+ *
+ * \pre input.has_data
+ */
template <class I>
inline
mln_concrete(I)
1
0
07 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Revamp linear sobel and cleanup level transform.
* mln/linear/ch_convolve.hh (mln_ch_convolve_grad): New.
* mln/linear/sobel_2d.hh: New.
* mln/linear/sobel.hh: Remove; obsolete.
* tests/linear/sobel.cc: Remove; obsolete.
* tests/linear/sobel_2d.cc: New.
* tests/linear/Makefile.am: Update.
* mln/fun/x2v/l1_norm.hh: New.
* mln/fun/vv2v/vec.hh: New.
* mln/fun/vv2v/all.hh: Update.
* mln/level/transform.spe.hh: Cleanup.
* mln/level/transform.hh: Cleanup.
* mln/level/transform_inplace.hh: New.
* tests/level/transform_inplace.cc: New.
* tests/level/Makefile.am: Update.
* mln/make/image2d.hh: Relax check; it was too strong.
* mln/core/concept/image.hh: Likewise.
* tests/make/image2d.cc: Augment.
mln/core/concept/image.hh | 6 -
mln/fun/vv2v/all.hh | 13 +-
mln/fun/vv2v/vec.hh | 80 +++++++++++++
mln/fun/x2v/l1_norm.hh | 81 +++++++++++++
mln/level/transform.hh | 139 +++++++++--------------
mln/level/transform.spe.hh | 94 +++++++---------
mln/level/transform_inplace.hh | 226 ++++++++++++++++++++++++++++++++++++++
mln/linear/ch_convolve.hh | 6 +
mln/linear/sobel_2d.hh | 229 +++++++++++----------------------------
mln/make/image2d.hh | 4
tests/level/Makefile.am | 2
tests/level/transform_inplace.cc | 56 +++++++++
tests/linear/Makefile.am | 4
tests/linear/sobel_2d.cc | 34 +----
tests/make/image2d.cc | 15 +-
15 files changed, 653 insertions(+), 336 deletions(-)
Index: tests/level/transform_inplace.cc
--- tests/level/transform_inplace.cc (revision 0)
+++ tests/level/transform_inplace.cc (revision 0)
@@ -0,0 +1,56 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/level/transform_inplace.cc
+///
+/// Tests on mln::level::transform_inplace
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/routine/clone.hh>
+#include <mln/fun/v2v/inc.hh>
+#include <mln/fun/v2v/dec.hh>
+#include <mln/debug/iota.hh>
+
+#include <mln/level/transform_inplace.hh>
+#include <mln/level/compare.hh>
+
+
+
+int main()
+{
+ using namespace mln;
+ const unsigned size = 50;
+
+ image2d<int> ref(3, 3);
+ debug::iota(ref);
+
+ image2d<int> ima = clone(ref);
+ level::transform_inplace(ima, fun::v2v::inc<int>());
+ level::transform_inplace(ima, fun::v2v::dec<int>());
+
+ mln_assertion(ima == ref);
+}
Index: tests/level/Makefile.am
--- tests/level/Makefile.am (revision 2825)
+++ tests/level/Makefile.am (working copy)
@@ -28,6 +28,7 @@
sort_psites_full \
stretch \
transform \
+ transform_inplace \
update
abs_SOURCES = abs.cc
@@ -52,6 +53,7 @@
sort_psites_SOURCES = sort_psites.cc
stretch_SOURCES = stretch.cc
transform_SOURCES = transform.cc
+transform_inplace_SOURCES = transform_inplace.cc
update_SOURCES = update.cc
# Lengthy tests.
Index: tests/linear/Makefile.am
--- tests/linear/Makefile.am (revision 2825)
+++ tests/linear/Makefile.am (working copy)
@@ -11,7 +11,7 @@
gaussian \
lap \
log \
- sobel
+ sobel_2d
convolve_SOURCES = convolve.cc
gaussian_SOURCES = gaussian.cc
@@ -19,6 +19,6 @@
convolve_directional_SOURCES = convolve_directional.cc
convolve_2x1d_SOURCES = convolve_2x1d.cc
log_SOURCES = log.cc
-sobel_SOURCES = sobel.cc
+sobel_2d_SOURCES = sobel_2d.cc
TESTS = $(check_PROGRAMS)
Index: tests/linear/sobel_2d.cc
--- tests/linear/sobel_2d.cc (revision 2821)
+++ tests/linear/sobel_2d.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,22 +26,20 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/linear/sobel.cc
- *
- * \brief Tests on mln::linear::sobel.
- */
+/// \file tests/linear/sobel_2d.cc
+///
+/// Tests on mln::linear::sobel_2d.
+
#include <mln/core/image/image2d.hh>
+#include <mln/core/var.hh>
#include <mln/value/int_u8.hh>
-#include <mln/level/saturate.hh>
#include <mln/level/stretch.hh>
#include <mln/io/pgm/load.hh>
#include <mln/io/pgm/save.hh>
-#include <mln/border/thickness.hh>
-#include <mln/linear/sobel.hh>
-
+#include <mln/linear/sobel_2d.hh>
#include <mln/debug/println.hh>
#include "tests/data.hh"
@@ -56,19 +55,6 @@
image2d<int_u8> input;
io::pgm::load(input, MLN_IMG_DIR "/tiny.pgm");
- // Create unused objects, for test purpose.
- linear::sobel_h(input);
- linear::sobel_v(input);
- linear::sobel(input);
-
- linear::sobel_norm(input);
-
- image2d<float> result = linear::sobel_norm(input);
- image2d<int_u8> output (result.domain());
- level::stretch (result, output);
- debug::println (output);
-
- image2d<int_u8> output_sat (output.domain());
- level::saturate(output, output_sat);
- io::pgm::save(output_sat, "out.pgm");
+ image2d<float> output = linear::sobel_2d_l1_norm(input);
+ io::pgm::save(level::stretch(int_u8(), output), "out.pgm");
}
Property changes on: tests/linear/sobel_2d.cc
___________________________________________________________________
Added: svn:mergeinfo
Index: tests/make/image2d.cc
--- tests/make/image2d.cc (revision 2825)
+++ tests/make/image2d.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -25,10 +25,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/make/image2d.cc
- *
- * \brief Tests on mln::make::image2d.
- */
+/// \file tests/make/image2d.cc
+///
+/// Tests on mln::make::image2d.
#include <mln/make/image2d.hh>
@@ -44,4 +43,10 @@
0, 1, 0, 0, 0 };
image2d<bool> ima = make::image2d(vals);
mln_assertion(ima.domain() == box2d(5,5));
+
+ bool vs[] = { 1, 0,
+ 1, 1 };
+ image2d<bool> tiny = make::image2d(vs);
+ mln_assertion(tiny.domain() == box2d(2,2));
+
}
Index: mln/core/concept/image.hh
--- mln/core/concept/image.hh (revision 2825)
+++ mln/core/concept/image.hh (working copy)
@@ -251,13 +251,13 @@
mlc_converts_to(V, mln_value(I))::check();
typedef mln_site(I) P;
enum { d = P::dim,
- s = mlc_root(d,S)::value / 2 };
- metal::bool_<(mlc_pow_int(2 * s + 1, d) == S)>::check();
+ s = mlc_root(d, S)::value };
+ metal::bool_<(mlc_pow_int(s, d) == S)>::check();
I& to = exact(to_);
mln_precondition(! to.has_data());
- box<P> b(all_to(0), all_to(2 * s));
+ box<P> b(all_to(0), all_to(s - 1));
to.init_(b);
mln_fwd_piter(box<P>) p(b);
unsigned i = 0;
Index: mln/level/transform.spe.hh
--- mln/level/transform.spe.hh (revision 2825)
+++ mln/level/transform.spe.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,11 +29,9 @@
#ifndef MLN_LEVEL_TRANSFORM_SPE_HH
# define MLN_LEVEL_TRANSFORM_SPE_HH
-/*! \file mln/level/transform.spe.hh
- *
- * \brief Specializations for mln::level::transform.
- *
- */
+/// \file mln/level/transform.spe.hh
+///
+/// Specializations for mln::level::transform.
# ifndef MLN_LEVEL_TRANSFORM_HH
# error "Forbidden inclusion of *.spe.hh"
@@ -58,11 +57,17 @@
namespace internal
{
- template <typename I, typename F, typename O>
+
+ template <typename I, typename F>
inline
void transform_tests(const Image<I>& input,
- const Function_v2v<F>& f,
- Image<O>& output);
+ const Function_v2v<F>& f);
+
+ template <typename I1, typename I2, typename F>
+ inline
+ void transform_tests(const Image<I1>& input1, const Image<I2>& input2,
+ const Function_v2v<F>& f);
+
}
@@ -88,17 +93,16 @@
{
trace::entering("level::impl::transform_lowq");
+ mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
+ trait::image::pw_io::read_write)::check();
+
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
mln_ch_value(I, mln_result(F)) output;
initialize(output, input);
- level::internal::transform_tests(input, f, output);
- mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
- trait::image::pw_io::read_write)::check();
-
value::lut_vec<mln_vset(I), mln_result(F)>
lut(input.values_eligible(), f);
@@ -118,17 +122,16 @@
{
trace::entering("level::impl::transform_taken");
+ mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
+ trait::image::pw_io::read_write)::check();
+
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
mln_ch_value(I, mln_result(F)) output;
initialize(output, input);
- level::internal::transform_tests(input, f, output);
- mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
- trait::image::pw_io::read_write)::check();
-
value::lut_vec<mln_vset(I), mln_result(F)>
lut(input.taken_values(), f);
@@ -151,13 +154,11 @@
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
mln_ch_value(I, mln_result(F)) output;
initialize(output, input);
- level::internal::transform_tests(input_, f_, output);
-
mln_result(F) val = f(input.val());
fill_with_value(output, val);
@@ -173,18 +174,15 @@
{
trace::entering("level::impl::transform_fast");
- typedef mln_ch_value(I, mln_result(F)) O;
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
- mln_ch_value(I, mln_result(F)) output;
+ typedef mln_ch_value(I, mln_result(F)) O;
+ O output;
initialize(output, input);
-
- level::internal::transform_tests(input, f, output);
-
mln_pixter(const I) pi(input);
mln_pixter(O) po(output);
po.start();
@@ -207,17 +205,15 @@
const Function_v2v<F>& f_)
{
trace::entering("level::impl::transform_fast_lowq");
- typedef mln_ch_value(I, mln_result(F)) O;
const I& input = exact(input_);
const F& f = exact(f_);
+ level::internal::transform_tests(input, f);
- mln_precondition(exact(input).has_data());
- mln_ch_value(I, mln_result(F)) output;
+ typedef mln_ch_value(I, mln_result(F)) O;
+ O output;
initialize(output, input);
- level::internal::transform_tests(input, f, output);
-
value::lut_vec<mln_vset(I), mln_result(F)>
lut(input.values_eligible(), f);
@@ -247,7 +243,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::undef,
+ transform_dispatch(mln::trait::undef,
mln::trait::image::quant::any,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -258,7 +254,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::vw_set::any,
+ transform_dispatch(mln::trait::image::vw_set::any,
mln::trait::image::quant::any,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -269,7 +265,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::vw_set::uni,
+ transform_dispatch(mln::trait::image::vw_set::uni,
mln::trait::image::quant::any,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -281,7 +277,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::vw_set::any,
+ transform_dispatch(mln::trait::image::vw_set::any,
mln::trait::image::quant::low,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -294,7 +290,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::quant::any,
+ transform_dispatch(mln::trait::image::quant::any,
mln::trait::image::value_access::direct,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -306,7 +302,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::quant::low,
+ transform_dispatch(mln::trait::image::quant::low,
mln::trait::image::value_access::direct,
const Image<I>& input,
const Function_v2v<F>& f)
@@ -319,12 +315,12 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::quant::any,
+ transform_dispatch(mln::trait::image::quant::any,
mln::trait::image::value_access::any,
const Image<I>& input,
const Function_v2v<F>& f)
{
- return transform_dispatch_(mln_trait_image_vw_set(I)(),
+ return transform_dispatch(mln_trait_image_vw_set(I)(),
mln_trait_image_quant(I)(),
input, f);
}
@@ -333,11 +329,11 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::value_storage::any,
+ transform_dispatch(mln::trait::image::value_storage::any,
const Image<I>& input,
const Function_v2v<F>& f)
{
- return transform_dispatch_(mln_trait_image_vw_set(I)(),
+ return transform_dispatch(mln_trait_image_vw_set(I)(),
mln_trait_image_quant(I)(),
input, f);
}
@@ -345,7 +341,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::value_storage::singleton,
+ transform_dispatch(mln::trait::image::value_storage::singleton,
const Image<I>& input,
const Function_v2v<F>& f)
{
@@ -355,7 +351,7 @@
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
- transform_dispatch_(mln::trait::image::value_storage::one_block,
+ transform_dispatch(mln::trait::image::value_storage::one_block,
const Image<I>& input_,
const Function_v2v<F>& f_)
{
@@ -364,11 +360,11 @@
/// Check alignement property
if (mlc_is(mln_trait_image_value_alignement(I),
trait::image::value_alignement::with_grid)::value)
- return transform_dispatch_(mln_trait_image_quant(I)(),
+ return transform_dispatch(mln_trait_image_quant(I)(),
mln_trait_image_value_access(I)(),
input, f_);
else
- return transform_dispatch_(mln_trait_image_vw_set(I)(),
+ return transform_dispatch(mln_trait_image_vw_set(I)(),
mln_trait_image_quant(I)(),
input, f_);
}
@@ -377,10 +373,10 @@
template <typename I, typename F>
mln_ch_value(I, mln_result(F))
- transform_dispatch_(const Image<I>& input,
+ transform_dispatch(const Image<I>& input,
const Function_v2v<F>& f)
{
- return transform_dispatch_(mln_trait_image_value_storage(I)(),
+ return transform_dispatch(mln_trait_image_value_storage(I)(),
input, f);
}
Index: mln/level/transform.hh
--- mln/level/transform.hh (revision 2825)
+++ mln/level/transform.hh (working copy)
@@ -1,4 +1,5 @@
// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -39,10 +40,8 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/function.hh>
-
# include <mln/value/set.hh>
-
// Specializations are in:
# include <mln/level/transform.spe.hh>
@@ -53,7 +52,7 @@
namespace level
{
- /*! Transform the image \p input through a function \p f
+ /*! Transform the image \p input through a function \p f.
*
* \param[in] input The input image.
* \param[in] f The function.
@@ -67,95 +66,74 @@
transform(const Image<I>& input, const Function_v2v<F>& f);
- /*! Transform two images \p ima1 \p ima2 through a function \p f
+ /*! Transform two images \p input1 \p input2 through a function \p f.
*
- * \param[in] input The input image.
+ * \param[in] input1 The 1st input image.
+ * \param[in] input2 The 2nd input image.
* \param[in] f The function.
*
* This routine runs: \n
- * for all p of \p input, \p output(p) = \p f( \p input(p) ).
- *
+ * for all p of \p input, \p output(p) = \p f( \p input1(p), \p input2(p) ).
*/
- template <typename I, typename J, typename F>
- mln_ch_value(I, mln_result(F))
- transform(const Image<I>& ima1,
- const Image<J>& ima2,
+ template <typename I1, typename I2, typename F>
+ mln_ch_value(I1, mln_result(F))
+ transform(const Image<I1>& input1,
+ const Image<I2>& input2,
const Function_vv2v<F>& f);
+
# ifndef MLN_INCLUDE_ONLY
namespace internal
{
- template <typename I, typename F, typename O>
+
+ template <typename I, typename F>
inline
void transform_tests(const Image<I>& input,
- const Function_v2v<F>& f,
- Image<O>& output)
+ const Function_v2v<F>& f)
{
+ // Dynamic test.
+ mln_precondition(exact(input).has_data());
+
// Avoid a warning about an undefined variable when NDEBUG
// is not defined.
(void) input;
(void) f;
- (void) output;
-
- // Properties check
- mln_precondition((mlc_is(mln_trait_image_pw_io(O),
- trait::image::pw_io::read_write)::value ||
- mlc_is(mln_trait_image_vw_io(O),
- trait::image::vw_io::read_write)::value));
-
- // FIXME Convert test
- mlc_converts_to(mln_result(F), mln_value(O))::check();
-
-
- // Dynamic tests
- mln_precondition(exact(input).has_data());
- mln_precondition(exact(output).domain() >= exact(input).domain());
}
- template <typename I, typename J, typename F, typename O>
+ template <typename I1, typename I2, typename F>
inline
- void transform_tests(const Image<I>& ima1,
- const Image<J>& ima2,
- const Function_v2v<F>& f,
- Image<O>& output)
+ void transform_tests(const Image<I1>& input1,
+ const Image<I2>& input2,
+ const Function_vv2v<F>& f)
{
+ // Dynamic tests.
+ mln_precondition(exact(input1).has_data());
+ mln_precondition(exact(input2).has_data());
+ mln_precondition(exact(input2).domain() == exact(input1).domain());
+
// Avoid a warning about an undefined variable when NDEBUG
// is not defined.
- (void) ima1;
- (void) ima2;
+ (void) input1;
+ (void) input2;
(void) f;
- (void) output;
-
- // Properties check
- mln_precondition((mlc_is(mln_trait_image_pw_io(O),
- trait::image::pw_io::read_write)::value ||
- mlc_is(mln_trait_image_vw_io(O),
- trait::image::vw_io::read_write)::value));
-
- // FIXME Convert test
- mlc_converts_to(mln_result(F), mln_value(O))::check();
-
-
- // Dynamic tests
- mln_precondition(exact(ima1).has_data());
- mln_precondition(exact(ima2).has_data());
- mln_precondition(exact(ima1).domain() == exact(ima2).domain());
- mln_precondition(exact(output).domain() >= exact(ima1).domain());
}
} // end of namespace mln::level::internal
+
namespace impl
{
+ // Generic implementations.
+
+
namespace generic
{
- // Generic implementation.
template <typename I, typename F>
inline
mln_ch_value(I, mln_result(F))
@@ -166,11 +144,11 @@
const I& input = exact(input_);
const F& f = exact(f_);
- mln_precondition(exact(input).has_data());
+ level::internal::transform_tests(input, f);
+
mln_ch_value(I, mln_result(F)) output;
initialize(output, input);
- level::internal::transform_tests(input, f, output);
mlc_is(mln_trait_image_pw_io(mln_ch_value(I, mln_result(F))),
trait::image::pw_io::read_write)::check();
@@ -179,36 +157,33 @@
output(p) = f(input(p));
trace::exiting("level::impl::generic::transform");
-
return output;
}
- // Generic implementation.
- template <typename I, typename J, typename F>
+ template <typename I1, typename I2, typename F>
inline
- mln_ch_value(I, mln_result(F))
- transform(const Image<I>& ima1_,
- const Image<J>& ima2_,
+ mln_ch_value(I1, mln_result(F))
+ transform(const Image<I1>& input1_,
+ const Image<I2>& input2_,
const Function_vv2v<F>& f_)
{
trace::entering("level::impl::generic::transform");
- const I& ima1 = exact(ima1_);
- const I& ima2 = exact(ima2_);
+ const I1& input1 = exact(input1_);
+ const I2& input2 = exact(input2_);
const F& f = exact(f_);
- mln_ch_value(I, mln_result(F)) output;
- initialize(output, ima1);
+ level::internal::transform_tests(input1, input2, f);
-// level::internal::transform_tests(ima1, ima2, f, output);
+ mln_ch_value(I1, mln_result(F)) output;
+ initialize(output, input1);
- mln_piter(I) p(ima1.domain());
+ mln_piter(I1) p(input1.domain());
for_all(p)
- output(p) = f(ima1(p), ima2(p));
+ output(p) = f(input1(p), input2(p));
trace::exiting("level::impl::generic::transform");
-
return output;
}
@@ -217,7 +192,8 @@
} // end of namespace mln::level::impl
- // Facade.
+
+ // Facades.
template <typename I, typename F>
inline
@@ -226,30 +202,31 @@
{
trace::entering("level::transform");
+ internal::transform_tests(input, f);
+
mln_ch_value(I, mln_result(F)) output;
- output = impl::internal::transform_dispatch_(exact(input), exact(f));
+ output = impl::internal::transform_dispatch(exact(input), exact(f));
trace::exiting("level::transform");
-
return output;
}
- template <typename I, typename J, typename F>
+ template <typename I1, typename I2, typename F>
inline
- mln_ch_value(I, mln_result(F))
- transform(const Image<I>& ima1,
- const Image<J>& ima2,
+ mln_ch_value(I1, mln_result(F))
+ transform(const Image<I1>& input1,
+ const Image<I2>& input2,
const Function_vv2v<F>& f)
{
trace::entering("level::transform");
- mln_ch_value(I, mln_result(F)) output;
- output = impl::generic::transform(exact(ima1), exact(ima2), exact(f));
+ internal::transform_tests(input1, input2, f);
- trace::exiting("level::transform");
+ mln_ch_value(I1, mln_result(F)) output;
+ output = impl::generic::transform(input1, input2, f);
+ trace::exiting("level::transform");
return output;
-
}
Index: mln/level/transform_inplace.hh
--- mln/level/transform_inplace.hh (revision 0)
+++ mln/level/transform_inplace.hh (revision 0)
@@ -0,0 +1,226 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ // General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_LEVEL_TRANSFORM_INPLACE_HH
+# define MLN_LEVEL_TRANSFORM_INPLACE_HH
+
+/// \file mln/level/transform_inplace.hh
+///
+/// Transform inplace the contents of an image through a function.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/function.hh>
+
+
+namespace mln
+{
+
+ namespace level
+ {
+
+ /*! Transform inplace the image \p ima through a function \p f.
+ *
+ * \param[in,out] ima The image to be transformed.
+ * \param[in] f The function.
+ *
+ * This routine runs: \n
+ * for all p of \p ima, \p ima(p) = \p f( \p ima(p) ).
+ *
+ */
+ template <typename I, typename F>
+ void
+ transform_inplace(Image<I>& ima, const Function_v2v<F>& f);
+
+
+ /*! Transform inplace the image \p ima with the image \p aux
+ through a function \p f.
+ *
+ * \param[in] ima1 The image to be transformed.
+ * \param[in] aux The auxiliary image.
+ * \param[in] f The function.
+ *
+ * This routine runs: \n
+ * for all p of \p ima, \p ima(p) = \p f( \p ima(p), \p aux(p) ).
+ */
+ template <typename I1, typename I2, typename F>
+ void
+ transform_inplace(Image<I1>& ima, const Image<I2>& aux,
+ const Function_vv2v<F>& f);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename I, typename F>
+ inline
+ void transform_inplace_tests(const Image<I>& ima,
+ const Function_v2v<F>& f)
+ {
+ // Properties checks.
+ mlc_or(mlc_is(mln_trait_image_pw_io(I),
+ trait::image::pw_io::read_write),
+ mlc_is(mln_trait_image_vw_io(I),
+ trait::image::vw_io::read_write))::check();
+ mlc_converts_to(mln_result(F), mln_value(I))::check();
+
+ // Dynamic test.
+ mln_precondition(exact(ima).has_data());
+
+ // Avoid a warning.
+ (void) ima;
+ (void) f;
+ }
+
+ template <typename I1, typename I2, typename F>
+ inline
+ void transform_tests(const Image<I1>& ima,
+ const Image<I2>& aux,
+ const Function_v2v<F>& f)
+ {
+ // Properties checks.
+ mlc_or(mlc_is(mln_trait_image_pw_io(I1),
+ trait::image::pw_io::read_write),
+ mlc_is(mln_trait_image_vw_io(I1),
+ trait::image::vw_io::read_write))::check();
+ mlc_converts_to(mln_result(F), mln_value(I1))::check();
+
+ // Dynamic test.
+ mln_precondition(exact(ima).has_data());
+ mln_precondition(exact(aux).has_data());
+ mln_precondition(exact(aux).domain() == exact(ima).domain());
+
+ // Avoid a warning.
+ (void) ima;
+ (void) aux;
+ (void) f;
+ }
+
+ } // end of namespace mln::level::internal
+
+
+ namespace impl
+ {
+
+
+ namespace generic
+ {
+
+ // Generic implementation.
+ template <typename I, typename F>
+ inline
+ void
+ transform_inplace(Image<I>& ima_, const Function_v2v<F>& f_)
+ {
+ trace::entering("level::impl::generic::transform_inplace");
+
+ mlc_is(mln_trait_image_pw_io(I),
+ trait::image::pw_io::read_write)::check();
+
+ I& ima = exact(ima_);
+ const F& f = exact(f_);
+
+ level::internal::transform_inplace_tests(ima, f);
+
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ ima(p) = f(ima(p));
+
+ trace::exiting("level::impl::generic::transform_inplace");
+ }
+
+
+ // Generic implementation.
+ template <typename I1, typename I2, typename F>
+ inline
+ void
+ transform_inplace(Image<I1>& ima_, const Image<I2>& aux_,
+ const Function_vv2v<F>& f_)
+ {
+ trace::entering("level::impl::generic::transform_inplace");
+
+ mlc_is(mln_trait_image_pw_io(I1),
+ trait::image::pw_io::read_write)::check();
+
+ I1& ima = exact(ima_);
+ const I2& aux = exact(aux_);
+ const F& f = exact(f_);
+
+ level::internal::transform_inplace_tests(ima, aux, f);
+
+ mln_piter(I1) p(ima.domain());
+ for_all(p)
+ ima(p) = f(ima(p), aux(p));
+
+ trace::exiting("level::impl::generic::transform_inplace");
+ }
+
+ } // end of namespace mln::level::impl::generic
+
+
+ } // end of namespace mln::level::impl
+
+
+ // Facades.
+
+ template <typename I, typename F>
+ inline
+ void
+ transform_inplace(Image<I>& ima, const Function_v2v<F>& f)
+ {
+ trace::entering("level::transform_inplace");
+
+ level::internal::transform_inplace_tests(ima, f);
+ impl::generic::transform_inplace(ima, f);
+
+ trace::exiting("level::transform_inplace");
+ }
+
+ template <typename I1, typename I2, typename F>
+ void
+ transform_inplace(Image<I1>& ima, const Image<I2>& aux,
+ const Function_vv2v<F>& f)
+ {
+ trace::entering("level::transform_inplace");
+
+ level::internal::transform_inplace_tests(ima, aux, f);
+ impl::generic::transform_inplace(ima, aux, f);
+
+ trace::exiting("level::transform_inplace");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::level
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LEVEL_TRANSFORM_INPLACE_HH
Index: mln/linear/ch_convolve.hh
--- mln/linear/ch_convolve.hh (revision 2825)
+++ mln/linear/ch_convolve.hh (working copy)
@@ -38,12 +38,18 @@
# include <mln/trait/ch_value.hh>
# include <mln/value/ops.hh>
+# include <mln/algebra/vec.hh>
+
/// Define the result of the convolution of an image with type \p I
/// with a weighted window of type \p W or weights of type \p W.
# define mln_ch_convolve(I, W) \
typename mln::linear::ch_convolve<I, W>::ret
+# define mln_ch_convolve_grad(I, W) \
+ typename mln::trait::ch_value< I, algebra::vec< I::site::dim, typename mln::linear::ch_convolve<I,W>::ret::value > >::ret
+
+
namespace mln
{
Index: mln/linear/sobel_2d.hh
--- mln/linear/sobel_2d.hh (revision 2821)
+++ mln/linear/sobel_2d.hh (working copy)
@@ -26,12 +26,12 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_LINEAR_SOBEL_HH
-# define MLN_LINEAR_SOBEL_HH
+#ifndef MLN_LINEAR_SOBEL_2D_HH
+# define MLN_LINEAR_SOBEL_2D_HH
-/// \file mln/linear/sobel.hh
+/// \file mln/linear/sobel_2d.hh
///
-/// Sobel filter.
+/// Sobel_2d filter.
/// \todo Extends to the case of other dimensions (only the 2-d case
/// is handled here).
@@ -42,24 +42,10 @@
# include <mln/arith/plus.hh>
# include <mln/level/abs.hh>
-# include <mln/fun/v2v/norm.hh>
-# include <mln/level/transform.hh>
-# include <mln/linear/line_x2_convolve.hh>
+# include <mln/fun/x2v/l1_norm.hh>
+# include <mln/fun/vv2v/vec.hh>
+# include <mln/linear/convolve_2x1d.hh>
-# include <mln/value/stack.hh>
-
-// FIXME: We might want to move these macros to another file, like
-// mln/core/gradient.hh.
-
-
-/// \brief Get the gradient component image type associated to image \a I.
-#define mln_gradient_component(I) \
- /* FIXME: Use mln_sum_x (or mln_sum_product) instead of mln_sum. */ \
- mln_ch_value(I, mln_sum(mln_value(I)))
-
-/// \brief Get the gradient image type associated to image \a I.
-#define mln_gradient(I) \
- mln::value::stack_image<I::point::dim, mln_gradient_component(I)>
namespace mln
@@ -68,194 +54,109 @@
namespace linear
{
- /// Sobel gradient components.
+ /// Sobel_2d gradient components.
/// \{
- /// Compute the vertical component of the Sobel gradient.
+ /// Compute the horizontal component of the 2D Sobel gradient.
template <typename I>
- mln_gradient_component(I) sobel_h(const Image<I>& input);
+ mln_ch_convolve(I, int)
+ sobel_2d_h(const Image<I>& input);
- /// Compute the horizontal component of the Sobel gradient.
+ /// Compute the vertical component of the 2D Sobel gradient.
template <typename I>
- mln_gradient_component(I) sobel_v(const Image<I>& input);
+ mln_ch_convolve(I, int)
+ sobel_2d_v(const Image<I>& input);
/// \}
- /// Compute the Sobel gradient of an image.
- ///
- /// \param[in] input A vectorial output image.
- /// \{
+ /// Compute the vertical component of the 2D Sobel gradient.
template <typename I>
- mln_gradient(I) sobel(const Image<I>& input);
- /// \}
-
- /// Compute the norm of the Sobel gradient of an image.
- ///
- /// \param input a vectorial input image
- /// \param norm a norm functor (\see mln/fun/v2v/norm.hh),
- /// defaulting to the L1-norm (mln::fun::v2v::l1_norm).
- /// \return the norm-image of the Sobel gradient of the input image
- /// FIXME: Add constraints on N (mln::Function_v2v<N>).
- /// \{
- template <typename I, typename N>
- mln_ch_value(I, mln_result(N)) sobel_norm(const Image<I>& input, N norm);
+ mln_ch_convolve_grad(I, int)
+ sobel_2d(const Image<I>& input);
/// \}
-
- /// \brief Compute the L-1 norm of the Sobel gradient of an image.
- ///
- /// This function is a shortcut for the general
- /// mln::linear::sobel_norm function.
- /// \{
+ /// Compute the L1 norm of the 2D Sobel gradient.
template <typename I>
- mln_ch_value(I, mln_sum(mln_value(I))) sobel_norm(const Image<I>& input);
+ mln_ch_convolve(I, int)
+ sobel_2d_l1_norm(const Image<I>& input);
/// \}
# ifndef MLN_INCLUDE_ONLY
-/// \brief Ensure type \p V is a scalar value.
-///
-/// For internal use only (#undef'd before the end of this file). (We
-/// might want to export this macro to the user interface; if so,
-/// rename it and move it elsewhere.)
-///
-/// FIXME: At the moment (rev. 1645), we cannot use mlc_is_a to check
-/// whether V derives from trait::value::nature::scalar like this
-///
-/// mlc_is_a(trait::value_<V>::nature, trait::value::nature::scalar)::check()
-///
-/// since `mlc_is_a' doesn't work on non template classes (yet). Hence
-/// the ugly workaround based on comprehensive checks.
-/// \{
-# define mlc_internal_ensure_is_scalar(V) \
- mlc_or(mlc_equal(typename mln::trait::value_<V>::nature, \
- mln::trait::value::nature::scalar), \
- mlc_or(mlc_equal(typename mln::trait::value_<V>::nature, \
- mln::trait::value::nature::integer), \
- mlc_equal(typename mln::trait::value_<V>::nature, \
- mln::trait::value::nature::floating)))::check()
-/// \}
- namespace impl
- {
+ // Facades.
template <typename I>
inline
- mln_gradient_component(I)
- sobel_h_(const Image<I>& input)
+ mln_ch_convolve(I, int)
+ sobel_2d_h(const Image<I>& input)
{
- // We don't use const ints here, since it would confuse the
- // STL allocators used within the windows used in the
- // convolutions.
- int wrow[] = { -1, 0, 1 };
- int wcol[] = { 1,
+ trace::entering("linear::sobel_2d_h");
+ mln_precondition(exact(input).has_data());
+
+ int wh[] = { -1, 0, 1 };
+ int wv[] = { 1,
2,
1 };
- // FIXME: It'd probably be nicer to have a "functional" version
- // of linear::line_x2_convolve.
- mln_gradient_component(I) output(exact(input).domain());
- linear::line_x2_convolve(input, wrow, wcol, output);
+ mln_ch_convolve(I, int) output = convolve_2x1d(input, wh, wv);
+
+ trace::exiting("linear::sobel_2d_h");
return output;
}
+
template <typename I>
inline
- mln_gradient_component(I)
- sobel_v_(const Image<I>& input)
+ mln_ch_convolve(I, int)
+ sobel_2d_v(const Image<I>& input)
{
- // We don't use const ints here, since it would confuse the
- // STL allocators used within the windows used in the
- // convolutions.
- int wrow[] = { 1, 2, 1 };
- int wcol[] = { -1,
+ trace::entering("linear::sobel_2d_v");
+ mln_precondition(exact(input).has_data());
+
+ int wh[] = { 1, 2, 1 };
+ int wv[] = { -1,
0,
+1 };
- // FIXME: It'd probably be nicer to have a "functional" version
- // of linear::line_x2_convolve.
- mln_gradient_component(I) output(exact(input).domain());
- linear::line_x2_convolve(input, wrow, wcol, output);
+ mln_ch_convolve(I, int) output = convolve_2x1d(input, wh, wv);
+
+ trace::exiting("linear::sobel_2d_v");
return output;
}
- template <typename I>
- inline
- mln_gradient(I)
- sobel_(const Image<I>& input)
- {
- /* FIXME: Not generic w.r.t. the dimension (only works on 2-D
- images here). Anyway, we'd need a n-dimensional definition
- of the Sobel gradient to.
-
- Stick with a very simple static assertion for the momemt,
- and improve later. */
- mlc_equal(metal::int_<I::point::dim>, metal::int_<2>)::check();
-
- mln_gradient_component(I) component_h = linear::sobel_h(input);
- mln_gradient_component(I) component_v = linear::sobel_v(input);
- return value::stack(component_h, component_v);
- }
- /* FIXME: Add constraints on N (mln::Function_v2v<N>). */
- template <typename I, typename N>
- mln_ch_value(I, mln_result(N))
- sobel_norm_(const Image<I>& input, N norm)
+ template <typename I>
+ mln_ch_convolve_grad(I, int)
+ sobel_2d(const Image<I>& input)
{
- mln_gradient(I) gradient = mln::linear::sobel (input);
- return level::transform (gradient, norm);
- }
-
- } // end of namespace mln::linear::impl
+ trace::entering("linear::sobel_2d");
+ mln_precondition(exact(input).has_data());
+ typedef mln_ch_convolve(I, int) J;
+ J h = sobel_2d_h(input),
+ v = sobel_2d_v(input);
+ fun::vv2v::vec<mln_value(J)> f;
+ mln_ch_convolve_grad(I, int) output = level::transform(h, v, f);
- // Facades.
-
- template <typename I>
- inline
- mln_gradient_component(I) sobel_h(const Image<I>& input)
- {
- mlc_internal_ensure_is_scalar(mln_value(I));
- return impl::sobel_h_(exact(input));
+ trace::exiting("linear::sobel_2d");
+ return output;
}
- template <typename I>
- inline
- mln_gradient_component(I) sobel_v(const Image<I>& input)
- {
- mlc_internal_ensure_is_scalar(mln_value(I));
- return impl::sobel_v_(exact(input));
- }
template <typename I>
- inline
- mln_gradient(I) sobel(const Image<I>& input)
+ mln_ch_convolve(I, int)
+ sobel_2d_l1_norm(const Image<I>& input)
{
- mlc_internal_ensure_is_scalar(mln_value(I));
- return impl::sobel_(exact(input));
- }
+ trace::entering("linear::sobel_2d_norm_l1");
+ mln_precondition(exact(input).has_data());
- template <typename I, typename N>
- inline
- mln_ch_value(I, mln_result(N))
- sobel_norm(const Image<I>& input, N norm)
- {
- mlc_internal_ensure_is_scalar(mln_value(I));
- return impl::sobel_norm_(exact(input), norm);
- }
+ typedef mln_ch_convolve_grad(I, int) G;
+ G grad = sobel_2d(input);
+ fun::x2v::l1_norm<mln_value(G)> f;
+ mln_ch_convolve(I, int) output = level::transform(grad, f);
- template <typename I>
- inline
- mln_ch_value(I, mln_sum(mln_value(I)))
- sobel_norm(const Image<I>& input)
- {
- // The type of a component of a vector from the gradient.
- typedef mln_sum(mln_value(I)) gradient_val_t;
- // The type of a vector from the gradient.
- typedef mln::algebra::vec<I::point::dim, gradient_val_t> gradient_vec_t;
- return sobel_norm(input,
- fun::v2v::l1_norm<gradient_vec_t, gradient_val_t>());
+ trace::exiting("linear::sobel_2d");
+ return output;
}
-# undef mlc_internal_ensure_is_scalar
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::linear
@@ -263,4 +164,4 @@
} // end of namespace mln
-#endif // ! MLN_LINEAR_SOBEL_HH
+#endif // ! MLN_LINEAR_SOBEL_2D_HH
Property changes on: mln/linear/sobel_2d.hh
___________________________________________________________________
Added: svn:mergeinfo
Index: mln/make/image2d.hh
--- mln/make/image2d.hh (revision 2825)
+++ mln/make/image2d.hh (working copy)
@@ -60,8 +60,8 @@
image2d(V (&values)[S])
{
mlc_bool(S != 0)::check();
- enum { s = mlc_sqrt_int(S) / 2 };
- metal::bool_<((2 * s + 1) * (2 * s + 1) == S)>::check();
+ enum { s = mlc_sqrt_int(S) };
+ metal::bool_<(s * s == S)>::check();
mln::image2d<V> tmp;
convert::from_to(values, tmp);
return tmp;
Index: mln/fun/x2v/l1_norm.hh
--- mln/fun/x2v/l1_norm.hh (revision 0)
+++ mln/fun/x2v/l1_norm.hh (revision 0)
@@ -0,0 +1,81 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_FUN_X2V_L1_NORM_HH
+# define MLN_FUN_X2V_L1_NORM_HH
+
+/// \file mln/fun/x2v/l1_norm.hh
+///
+/// Define the L1-norm of an algebraic vector.
+
+# include <mln/core/concept/function.hh>
+# include <mln/algebra/vec.hh>
+# include <mln/math/abs.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace x2v
+ {
+
+ template <typename V>
+ struct l1_norm : public Function_v2v< l1_norm<V> >
+ {
+ typedef mln_coord(V) C;
+ typedef mln_sum(C) result;
+
+ result operator()(const V& v) const;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ inline
+ typename l1_norm<V>::result
+ l1_norm<V>::operator()(const V& v) const
+ {
+ result res = 0;
+ for (unsigned i = 0; i < V::dim; ++i)
+ res += mln::math::abs(v[i]);
+ return res;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::x2v
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_X2V_L1_NORM_HH
Index: mln/fun/vv2v/all.hh
--- mln/fun/vv2v/all.hh (revision 2825)
+++ mln/fun/vv2v/all.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,10 +28,9 @@
#ifndef MLN_FUN_VV2V_ALL_HH
# define MLN_FUN_VV2V_ALL_HH
-/*! \file mln/fun/vv2v/all.hh
- *
- * \brief File that includes all functions from point to value.
- */
+/// \file mln/fun/vv2v/all.hh
+///
+/// File that includes all functions from point to value.
namespace mln
@@ -40,7 +39,7 @@
namespace fun
{
- /// Namespace of functions from point to value.
+ /// Namespace of functions from a couple of values to a value.
namespace vv2v
{
}
@@ -51,5 +50,7 @@
# include <mln/fun/vv2v/max.hh>
# include <mln/fun/vv2v/min.hh>
+# include <mln/fun/vv2v/vec.hh>
+
#endif // ! MLN_FUN_VV2V_ALL_HH
Index: mln/fun/vv2v/vec.hh
--- mln/fun/vv2v/vec.hh (revision 0)
+++ mln/fun/vv2v/vec.hh (revision 0)
@@ -0,0 +1,80 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_FUN_VV2V_VEC_HH
+# define MLN_FUN_VV2V_VEC_HH
+
+/// \file mln/fun/vv2v/vec.hh
+///
+/// computing the vecimum of two values using a functor.
+
+# include <mln/core/concept/function.hh>
+# include <mln/algebra/vec.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace vv2v
+ {
+
+ // FIXME: Doc.
+
+ /// \brief A functor computing the vecimum of two values.
+ template <typename V>
+ struct vec : public Function_vv2v< vec<V> >
+ {
+ typedef algebra::vec<2,V> result;
+ algebra::vec<2,V> operator()(const V& v1, const V& v2) const;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ inline
+ algebra::vec<2,V>
+ vec<V>::operator()(const V& v1, const V& v2) const
+ {
+ algebra::vec<2,V> tmp;
+ tmp.set(v1, v2);
+ return tmp;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::vv2v
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_VV2V_VEC_HH
1
0