
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@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