3904: Add world::binary_2d::enlarge.

* mln/world/binary_2d/enlarge.hh: new routine. * tests/world/Makefile.am, * tests/world/binary_2d/Makefile.am: new makefiles. * tests/world/binary_2d/enlarge.cc: new associated test. --- milena/ChangeLog | 11 + milena/mln/world/binary_2d/enlarge.hh | 380 ++++++++++++++++++++++++++++++ milena/tests/world/Makefile.am | 1 + milena/tests/world/binary_2d/Makefile.am | 12 + milena/tests/world/binary_2d/enlarge.cc | 47 ++++ 5 files changed, 451 insertions(+), 0 deletions(-) create mode 100644 milena/mln/world/binary_2d/enlarge.hh create mode 100644 milena/tests/world/binary_2d/Makefile.am create mode 100644 milena/tests/world/binary_2d/enlarge.cc diff --git a/milena/ChangeLog b/milena/ChangeLog index 87735dc..c68baff 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,5 +1,16 @@ 2009-05-28 Guillaume Lazzara <lazzara@lrde.epita.fr> + Add world::binary_2d::enlarge. + + * mln/world/binary_2d/enlarge.hh: new routine. + + * tests/world/Makefile.am, + * tests/world/binary_2d/Makefile.am: new makefiles. + + * tests/world/binary_2d/enlarge.cc: new associated test. + +2009-05-28 Guillaume Lazzara <lazzara@lrde.epita.fr> + Add debug::superpose. * mln/debug/all.hh: update includes. diff --git a/milena/mln/world/binary_2d/enlarge.hh b/milena/mln/world/binary_2d/enlarge.hh new file mode 100644 index 0000000..6094a51 --- /dev/null +++ b/milena/mln/world/binary_2d/enlarge.hh @@ -0,0 +1,380 @@ +// Copyright (C) 2009 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_WORLD_BINARY_2D_ENLARGE_HH +# define MLN_WORLD_BINARY_2D_ENLARGE_HH + +/// \file mln/world/binary_2d/enlarge.hh +/// +/// Enlarge 2^n times a binary image. +/// +/// \todo Make it much more generic. + + +# include <iostream> + +# include <mln/core/image/image2d.hh> +# include <mln/core/routine/initialize.hh> + +# include <mln/value/int_u8.hh> +# include <mln/fun/p2v/ternary.hh> +# include <mln/fun/v2b/threshold.hh> + +# include <mln/level/transform.hh> + +# include <mln/pw/image.hh> +# include <mln/pw/cst.hh> +# include <mln/pw/value.hh> +# include <mln/opt/at.hh> + +# include <mln/geom/min_row.hh> +# include <mln/geom/min_col.hh> + +# include <mln/core/routine/duplicate.hh> + + +namespace mln +{ + + namespace world + { + + namespace binary_2d + { + + /// Enlarge a binary image 2^n times + /// + /// \param[in] input A binary image. + /// \param[in] n The power of 2 setting up the enlargement. + /// + /// \return A binary image with a domain 2^\p n times larger. + // + template <typename I> + mln_concrete(I) + enlarge(const Image<I>& input, unsigned n); + + +# ifndef MLN_INCLUDE_ONLY + + + // Internal routines. + + namespace internal + { + + inline + float + val(bool b) + { + return b ? 1 : 0; + } + + inline + int + do_threshold(float value) + { + return 255.f * value; + } + + } // end of namespace mln::world::binary_2d + + + + + // Implementation. + + namespace impl + { + + ///FIXME: works only on 2d images. + inline + image2d<value::int_u8> + enlargex2(const image2d<bool>& input) + { + using value::int_u8; + + mln_precondition(input.is_valid()); + + unsigned + mrow = geom::min_row(input), + mcol = geom::min_col(input); + + image2d<int_u8> output(make::box2d(mrow, mcol, + mrow + 2 * input.nrows() - 1, + mcol + 2 * input.ncols() - 1)); + float value; + + // row 0 + opt::at(output, mrow, mcol) = internal::do_threshold(opt::at(input, mrow, mcol)); + + for (unsigned col = 2; col < output.ncols(); col += 2) + { + value = internal::val(opt::at(input, mrow, mcol + col / 2)); + value += internal::val(opt::at(input, mrow, mcol + col / 2 - 1)); + opt::at(output, mrow, mcol + col) = internal::do_threshold(value / 2); + } + + for (unsigned col = 1; col < output.ncols(); col += 2) + opt::at(output, mrow, mcol + col) + = internal::do_threshold(opt::at(input, mrow, mcol + col / 2)); + + // col 0 + + for (unsigned row = 2; row < output.nrows(); row += 2) + { + value = internal::val(opt::at(input, mrow + row / 2, mcol)); + value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol)); + opt::at(output, mrow + row, mcol) = internal::do_threshold(value / 2); + } + + for (unsigned row = 1; row < output.nrows(); row += 2) + opt::at(output, mrow + row, mcol) + = internal::do_threshold(opt::at(input, mrow + row / 2, mcol)); + + // others + + for (unsigned row = 2; row < output.nrows(); row += 2) + { + for (unsigned col = 2; col < output.ncols(); col += 2) + { + value = internal::val(opt::at(input, mrow + row / 2, mcol + col / 2)); + value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol + col / 2)); + value += internal::val(opt::at(input, mrow + row / 2, mcol + col / 2 - 1)); + value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol + col / 2 - 1)); + opt::at(output, mrow + row, mcol + col) + = internal::do_threshold(value / 4); + } + for (unsigned col = 1; col < output.ncols(); col += 2) + { + value = internal::val(opt::at(input, mrow + row / 2, mcol + col / 2)); + value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol + col / 2)); + opt::at(output, mrow + row, mcol + col) = internal::do_threshold(value / 2); + } + } + + for (unsigned row = 1; row < output.nrows(); row += 2) + { + for (unsigned col = 2; col < output.ncols(); col += 2) + { + value = internal::val(opt::at(input, mrow + row / 2, mcol + col / 2)); + value += internal::val(opt::at(input, mrow + row / 2, mcol + col / 2 - 1)); + opt::at(output, mrow + row, mcol + col) = internal::do_threshold(value / 2); + } + for (unsigned col = 1; col < output.ncols(); col += 2) + opt::at(output, mrow + row, mcol + col) + = internal::do_threshold(opt::at(input, mrow + row / 2, mcol + col / 2)); + } + + return output; + } + + + + inline + image2d<value::int_u8> + enlargex2(const image2d<value::int_u8>& input) + { + using value::int_u8; + + unsigned + mrow = geom::min_row(input), + mcol = geom::min_col(input); + + image2d<int_u8> output(make::box2d(mrow, mcol, + mrow + 2 * input.nrows() - 1, + mcol + 2 * input.ncols() - 1)); + unsigned value; + + // row 0 + opt::at(output, mrow, mcol) = (opt::at(input, mrow, mcol)); + + for (unsigned col = 2; col < output.ncols(); col += 2) + { + value = (opt::at(input, mrow, mcol + col / 2)); + value += (opt::at(input, mrow, mcol + col / 2 - 1)); + opt::at(output, mrow, mcol + col) = (value / 2); + } + + for (unsigned col = 1; col < output.ncols(); col += 2) + opt::at(output, mrow, mcol + col) = (opt::at(input, mrow, mcol + col / 2)); + + // col 0 + + for (unsigned row = 2; row < output.nrows(); row += 2) + { + value = (opt::at(input, mrow + row / 2, mcol)); + value += (opt::at(input, mrow + row / 2 - 1, mcol)); + opt::at(output, mrow + row, mcol) = (value / 2); + } + + for (unsigned row = 1; row < output.nrows(); row += 2) + opt::at(output, mrow + row, mcol) = (opt::at(input, mrow + row / 2, mcol)); + + // others + + for (unsigned row = 2; row < output.nrows(); row += 2) + { + for (unsigned col = 2; col < output.ncols(); col += 2) + { + value = (opt::at(input, mrow + row / 2, mcol + col / 2)); + value += (opt::at(input, mrow + row / 2 - 1, mcol + col / 2)); + value += (opt::at(input, mrow + row / 2, mcol + col / 2 - 1)); + value += (opt::at(input, mrow + row / 2 - 1, mcol + col / 2 - 1)); + opt::at(output, mrow + row, mcol + col) = ((unsigned(value)+2) / 4); + } + for (unsigned col = 1; col < output.ncols(); col += 2) + { + value = (opt::at(input, mrow + row / 2, mcol + col / 2)); + value += (opt::at(input, mrow + row / 2 - 1, mcol + col / 2)); + opt::at(output, mrow + row, mcol + col) = (value / 2); + } + } + + for (unsigned row = 1; row < output.nrows(); row += 2) + { + for (unsigned col = 2; col < output.ncols(); col += 2) + { + value = (opt::at(input, mrow + row / 2, mcol + col / 2)); + value += (opt::at(input, mrow + row / 2, mcol + col / 2 - 1)); + opt::at(output, mrow + row, mcol + col) = (value / 2); + } + for (unsigned col = 1; col < output.ncols(); col += 2) + opt::at(output, mrow + row, mcol + col) + = (opt::at(input, mrow + row / 2, mcol + col / 2)); + } + + return output; + } + + + template <typename I> + inline + mln_ch_value(I,value::int_u8) + do_enlarge_gl(const I& input, unsigned n) + { + using value::int_u8; + + mln_ch_value(I,int_u8) output = enlargex2(input); + + while (--n) + output = enlargex2(output); + + return output; + } + + + template <typename I> + inline + mln_concrete(I) + do_enlarge_bool(const I& input, unsigned n) + { + mln_ch_value(I,value::int_u8) tmp = do_enlarge_gl(input, n); + I output + = level::transform(tmp, fun::v2b::threshold<value::int_u8>(150)); + return output; + } + + + } // end of namespace mln::world::binary_2d::impl + + + + + // Dispatch + + namespace internal + { + + template<typename I> + inline + mln_concrete(I) + enlarge_dispatch(const I& input, const bool&, unsigned n) + { + return impl::do_enlarge_bool(input, n); + } + + template<typename I> + inline + mln_concrete(I) + enlarge_dispatch(const I& input, const value::int_u8&, unsigned n) + { + return impl::do_enlarge_gl(input, n); + } + + template<typename I> + inline + mln_concrete(I) + enlarge_dispatch(const I& input, const mln_value(I)&, unsigned n) + { + mlc_abort(I)::check(); + return mln_concrete(I)(); + } + + template<typename I> + inline + mln_concrete(I) + enlarge_dispatch(const Image<I>& input, unsigned n) + { + return enlarge_dispatch(exact(input), mln_value(I)(), n); + } + + } // end of namespace mln::world::binary_2d::internal + + + + // Facade + + template <typename I> + inline + mln_concrete(I) + enlarge(const Image<I>& input, unsigned n) + { + trace::entering("mln::world::binary_2d::enlarge"); + + mln_precondition(exact(input).is_valid()); + mlc_bool(mln_site_(I)::dim == 2)::check(); + + mln_concrete(I) output; + if (n == 0) + output = duplicate(input); + else + output = internal::enlarge_dispatch(input, n); + + trace::exiting("mln::world::binary_2d::enlarge"); + return output; + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::world::binary_2d + + } // end of namespace mln::world + +} // mln + +#endif // ! MLN_WORLD_BINARY_2D_ENLARGE_HH diff --git a/milena/tests/world/Makefile.am b/milena/tests/world/Makefile.am index 7a41ecd..75f3a7a 100644 --- a/milena/tests/world/Makefile.am +++ b/milena/tests/world/Makefile.am @@ -1,2 +1,3 @@ SUBDIRS = \ + binary_2d \ inter_pixel diff --git a/milena/tests/world/binary_2d/Makefile.am b/milena/tests/world/binary_2d/Makefile.am new file mode 100644 index 0000000..e04c66a --- /dev/null +++ b/milena/tests/world/binary_2d/Makefile.am @@ -0,0 +1,12 @@ +## Process this file through Automake to create Makefile.in -*- Makefile -*- + +include $(top_srcdir)/milena/tests/tests.mk + +check_PROGRAMS = \ + enlarge \ + enlarge_hq2x + +enlarge_SOURCES = enlarge.cc +enlarge_hq2x_SOURCES = enlarge_hq2x.cc + +TESTS = $(check_PROGRAMS) diff --git a/milena/tests/world/binary_2d/enlarge.cc b/milena/tests/world/binary_2d/enlarge.cc new file mode 100644 index 0000000..0ef1981 --- /dev/null +++ b/milena/tests/world/binary_2d/enlarge.cc @@ -0,0 +1,47 @@ +#include <mln/core/image/image2d.hh> +#include <mln/level/compare.hh> +#include <mln/world/binary_2d/enlarge.hh> +#include <mln/make/image.hh> +#include <mln/value/int_u8.hh> + +#include "tests/data.hh" + +mln::value::int_u8 vals_i[][4] = { { 4, 4, 4, 5 }, + { 4, 4, 4, 5 }, + { 3, 3, 4, 3 }, + { 3, 3, 2, 2 } }; + +bool vals_b[][4] = { { 0, 0, 0, 1 }, + { 0, 0, 0, 1 }, + { 0, 0, 0, 0 }, + { 1, 1, 0, 0 } }; + +int main() +{ + using namespace mln; + + { + value::int_u8 vals[][2] = { { 4, 5 }, + { 3, 2 } } ; + + image2d<value::int_u8> input = make::image(vals); + image2d<value::int_u8> input_2x = world::binary_2d::enlarge(input,1); + + image2d<value::int_u8> ref = make::image(vals_i); + + mln_assertion(ref == input_2x); + } + + { + bool vals[][2] = { { 0, 1 }, + { 1, 0 } } ; + + image2d<bool> input = make::image(vals); + image2d<bool> input_2x = world::binary_2d::enlarge(input,1); + + image2d<bool> ref = make::image(vals_b); + + mln_assertion(ref == input_2x); + } + +} -- 1.5.6.5
participants (1)
-
Guillaume Lazzara