Commit 2e66d4d3 authored by Thierry Geraud's avatar Thierry Geraud
Browse files

Augment tools for linear filtering; add sobel.

	* mln/core/decorated_image.hh
	(helper_decorated_image_write_): Replace by...
	(decorated_image_impl_): ...this.
	(impl_): New.
	(lvalue): Update.
	(write_): Remove; now in impl_.

	* mln/value/all.hh: Update.
	* mln/value/props.hh,
	* mln/value/int_u.hh,
	* mln/value/int_s.hh (min, max): Change to proc.
	* mln/value/props.hh (mln_min, mln_max): Update.
	(epsilon): Change to proc.
	* mln/value/aliases.hh: New.
	* mln/level/stretch.hh: Update.

	* mln/arith/abs.hh: New.
	* mln/arith/plus.hh: Overload.
	* mln/fun/v2v/abs.hh: New.
	* mln/level/apply.hh: Fix meaning; add todo.
	* mln/math/abs.hh: Overload.

	* mln/core/concept/iterator.hh (for_all_3): New.
	* mln/math/round_sat.hh: New.
	* mln/make/w_window_line.hh: New.
	* mln/metal/abort.hh: New.
	* mln/linear/line_convolve.hh: New.
	* mln/linear/line_x2_convolve.hh: New.
	* mln/linear/sobel.hh: New.
	* tests/line_convolve.cc: New.
	* tests/sobel.cc: New.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@1055 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 0b6be5d5
2007-08-27 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Augment tools for linear filtering; add sobel.
* mln/core/decorated_image.hh
(helper_decorated_image_write_): Replace by...
(decorated_image_impl_): ...this.
(impl_): New.
(lvalue): Update.
(write_): Remove; now in impl_.
* mln/value/all.hh: Update.
* mln/value/props.hh,
* mln/value/int_u.hh,
* mln/value/int_s.hh (min, max): Change to proc.
* mln/value/props.hh (mln_min, mln_max): Update.
(epsilon): Change to proc.
* mln/value/aliases.hh: New.
* mln/level/stretch.hh: Update.
* mln/arith/abs.hh: New.
* mln/arith/plus.hh: Overload.
* mln/fun/v2v/abs.hh: New.
* mln/level/apply.hh: Fix meaning; add todo.
* mln/math/abs.hh: Overload.
* mln/core/concept/iterator.hh (for_all_3): New.
* mln/math/round_sat.hh: New.
* mln/make/w_window_line.hh: New.
* mln/metal/abort.hh: New.
* mln/linear/line_convolve.hh: New.
* mln/linear/line_x2_convolve.hh: New.
* mln/linear/sobel.hh: New.
* tests/line_convolve.cc: New.
* tests/sobel.cc: New.
2007-08-27 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Add local convolution.
......
......@@ -57,19 +57,41 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
template <typename L, typename R, typename O>
void plus(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
namespace impl
{
const L& lhs = exact(lhs_);
const R& rhs = exact(rhs_);
O& output = exact(output_);
mln_precondition(rhs.domain() == lhs.domain());
mln_precondition(output.domain() == lhs.domain());
template <typename L, typename R, typename O>
void plus_(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
{
const L& lhs = exact(lhs_);
const R& rhs = exact(rhs_);
O& output = exact(output_);
mln_piter(L) p(lhs.domain());
for_all(p)
output(p) = lhs(p) + rhs(p);
}
template <typename L, typename R, typename O>
void plus_(const Fast_Image<L>& lhs, const Fast_Image<R>& rhs, Fast_Image<O>& output)
{
mln_pixter(const L) lp(exact(lhs));
mln_pixter(const R) rp(exact(rhs));
mln_pixter(O) op(exact(output));
for_all_3(lp, rp, op)
op.val() = lp.val() + rp.val();
}
} // end of namespace mln::arith::impl
mln_piter(I) p(output.domain());
for_all(p)
output(p) = lhs(p) + rhs(p);
// Facade.
template <typename L, typename R, typename O>
void plus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output)
{
mln_precondition(exact(rhs).domain() == exact(lhs).domain());
mln_precondition(exact(output).domain() == exact(lhs).domain());
impl::plus_(exact(lhs), exact(rhs), exact(output));
}
# endif // ! MLN_INCLUDE_ONLY
......
......@@ -46,6 +46,15 @@
# define for_all_2(x1, x2) for(x1.start(),x2.start(); x1.is_valid(); x1.next(),x2.next())
/*! \brief Loop to browse all the elements targetted by the triplet of
* iterators \p x1, \p x2, and \p x3.
*/
# define for_all_3(x1, x2, x3) \
for(x1.start(), x2.start(), x3.start(); \
x1.is_valid(); \
x1.next(), x2.next(), x3.next())
/*! \brief Loop to browse all the remaining elements targetted by the
* iterator \p x.
*/
......
......@@ -35,13 +35,39 @@
namespace mln
{
// Fwd decl.
template <typename I, typename D> class decorated_image;
namespace internal
{
template <typename I, typename E>
struct decorated_image_impl_
{
typedef mln::value::proxy<E> lvalue;
void write_(const mln_psite(I)& p, const mln_value(I)& v);
};
template <typename I, typename E>
struct decorated_image_impl_< const I, E >
{
typedef mln::value::proxy<const E> lvalue;
};
} // end of namespace::internal
// FIXME: Doc!
template <typename I, typename D>
class decorated_image : public internal::image_adaptor_< I, decorated_image<I,D> >
class decorated_image : public internal::image_adaptor_< I, decorated_image<I,D> >,
public internal::decorated_image_impl_< I, decorated_image<I,D> >
{
typedef decorated_image<I, D> self_;
typedef internal::image_adaptor_< I, self_ > super_;
typedef internal::decorated_image_impl_< I, self_ > impl_;
public:
decorated_image(I& ima, const D& deco);
......@@ -49,13 +75,12 @@ namespace mln
typedef mln_value(I) value;
typedef mln::value::proxy<const self_> rvalue;
typedef mln::value::proxy<self_> lvalue;
typedef typename impl_::lvalue lvalue;
rvalue operator()(const mln_psite(I)& p) const;
lvalue operator()(const mln_psite(I)& p);
mln_value(I) read_(const mln_psite(I)& p) const;
void write_(const mln_psite(I)& p, const mln_value(I)& v);
template <typename V>
struct change_value
......@@ -110,7 +135,7 @@ namespace mln
}
template <typename I, typename D>
mln::value::proxy< const decorated_image<I,D> >
typename decorated_image<I,D>::rvalue
decorated_image<I,D>::operator()(const mln_psite(I)& p) const
{
rvalue tmp(*this, p);
......@@ -118,7 +143,7 @@ namespace mln
}
template <typename I, typename D>
mln::value::proxy< decorated_image<I,D> >
typename decorated_image<I,D>::lvalue
decorated_image<I,D>::operator()(const mln_psite(I)& p)
{
lvalue tmp(*this, p);
......@@ -128,31 +153,17 @@ namespace mln
namespace internal
{
template <typename I, typename D>
template <typename I, typename E>
void
helper_decorated_image_write_(decorated_image<I,D>& ima,
const mln_psite(I)& p, const mln_value(I)& v)
decorated_image_impl_<I,E>::write_(const mln_psite(I)& p, const mln_value(I)& v)
{
E& ima = internal::force_exact<E>(*this);
ima.decoration().writing(ima.adaptee(), p, v);
ima.adaptee()(p) = v;
}
template <typename I, typename D>
void
helper_decorated_image_write_(decorated_image<const I,D>&,
const mln_psite(I)&, const mln_value(I)&)
// FIXME: Static assertion instead.
;
} // end of namespace mln::internal
template <typename I, typename D>
void
decorated_image<I,D>::write_(const mln_psite(I)& p, const mln_value(I)& v)
{
internal::helper_decorated_image_write_(*this, p, v);
}
template <typename I, typename D>
mln_value(I)
decorated_image<I,D>::read_(const mln_psite(I)& p) const
......
// Copyright (C) 2007 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License version 2 as published by the
// Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; see the file COPYING. If not, write to
// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
// Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free
// software library without restriction. Specifically, if other files
// instantiate templates or use macros or inline functions from this
// file, or you compile this file and link it with other files to
// produce an executable, this file does not by itself cause the
// resulting executable to be covered by the GNU General Public
// License. This exception does not however invalidate any other
// reasons why the executable file might be covered by the GNU General
// Public License.
#ifndef MLN_FUN_V2V_ABS_HH
# define MLN_FUN_V2V_ABS_HH
/*! \file mln/fun/v2v/abs.hh
*
* \brief FIXME.
*/
# include <mln/core/concept/function.hh>
# include <mln/math/abs.hh>
namespace mln
{
namespace fun
{
namespace v2v
{
// FIXME: Doc!
template <typename V>
struct abs : public Function_v2v< abs<V> >
{
typedef V result;
V operator()(const V& v) const;
};
# ifndef MLN_INCLUDE_ONLY
template <typename V>
V
abs<V>::operator()(const V& v) const
{
return mln::math::abs(v);
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::fun::v2v
} // end of namespace mln::fun
} // end of namespace mln
#endif // ! MLN_FUN_V2V_ABS_HH
......@@ -34,7 +34,7 @@
*/
# include <mln/core/concept/image.hh>
# include <mln/core/concept/accumulator.hh>
# include <mln/core/concept/function.hh>
namespace mln
......@@ -45,19 +45,19 @@ namespace mln
/*! Apply a function-object to the image \p input.
*
* \param[in] input The input image.
* \param[in,out] input The input image.
* \param[in] f The function-object.
* \result A copy of the function-object.
*
* This routine runs: \n
* for all p of \p input, \p f( \p input(p) ) \n
* return \p f
* for all p of \p input, \p input(p) = \p f( \p input(p) ) \n
*
* \todo Find a meaning for this routine! (Clue: f is mutable
* and/or same for input?)
* This routine is equivalent to level::tranform(input, f, input)
* but it is faster since a single iterator is required.
*
* \todo Add versions for lowq images.
*/
template <typename I, typename F>
F apply(const Image<I>& input, const Function<F>& f);
void apply(Image<I>& input, const Function_v2v<F>& f);
......@@ -67,39 +67,33 @@ namespace mln
{
template <typename I, typename F>
F apply(const Image<I>& input_, const Function<F>& f_)
void apply_(Image<I>& input_, const F& f)
{
const I& input = exact(input_);
F f = exact(f_);
I& input = exact(input_);
mln_piter(I) p(input.domain());
for_all(p)
f(input(p));
return f;
input(p) = f(input(p));
}
template <typename I, typename F>
F apply(const Fast_Image<I>& input_, const Function<F>& f_)
void apply_(Fast_Image<I>& input_, const F& f)
{
const I& input = exact(input_);
F f = exact(f_);
mln_pixter(const I) pxl(input);
I& input = exact(input_);
mln_pixter(I) pxl(input);
for_all(pxl)
f(pxl.val());
return f;
pxl.val() = f(pxl.val());
}
} // end of namespace mln::level::impl
// Facades.
// Facade.
template <typename I, typename F>
F apply(const Image<I>& input, const Function<F>& f)
void apply(Image<I>& input, const Function_v2v<F>& f)
{
mln_precondition(exact(input).has_data());
return impl::apply(exact(input), f);
impl::apply_(exact(input), exact(f));
}
# endif // ! MLN_INCLUDE_ONLY
......
......@@ -71,7 +71,7 @@ namespace mln
if (max_ == min_)
return; // FIXME
float min = float(min_), max = float(max_);
const float epsilon = value::props<float>::epsilon;
const float epsilon = value::props<float>::epsilon();
float m = 0.0f - 0.5f + epsilon;
float M = mln_max(value::int_u<n>) + 0.5f - epsilon;
float a = (M - m) / (max - min);
......
......@@ -46,7 +46,7 @@ namespace mln
namespace linear
{
/*! Convolution of image \p input by the weighted window \p w_win.
/*! Convolution of an image \p input by the weighted window \p w_win.
*
* \warning Computation of \p output(p) is performed with the
* value type of \p output.
......@@ -67,8 +67,8 @@ namespace mln
{
template <typename I, typename W, typename O>
void convolve(const Image<I>& input_, const Weighted_Window<W>& w_win_,
Image<O>& output_)
void convolve_(const Image<I>& input_, const Weighted_Window<W>& w_win_,
Image<O>& output_)
{
const I& input = exact(input_);
const W& w_win = exact(w_win_);
......@@ -87,8 +87,8 @@ namespace mln
}
template <typename I, typename W, typename O>
void convolve(const Fast_Image<I>& input_, const Weighted_Window<W>& w_win_,
Fast_Image<O>& output_)
void convolve_(const Fast_Image<I>& input_, const Weighted_Window<W>& w_win_,
Fast_Image<O>& output_)
{
const I& input = exact(input_);
const W& w_win = exact(w_win_);
......@@ -122,7 +122,7 @@ namespace mln
Image<O>& output)
{
mln_precondition(exact(output).domain() == exact(input).domain());
impl::convolve(exact(input), exact(w_win), exact(output));
impl::convolve_(exact(input), exact(w_win), exact(output));
}
# endif // ! MLN_INCLUDE_ONLY
......
// Copyright (C) 2007 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License version 2 as published by the
// Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; see the file COPYING. If not, write to
// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
// Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free
// software library without restriction. Specifically, if other files
// instantiate templates or use macros or inline functions from this
// file, or you compile this file and link it with other files to
// produce an executable, this file does not by itself cause the
// resulting executable to be covered by the GNU General Public
// License. This exception does not however invalidate any other
// reasons why the executable file might be covered by the GNU General
// Public License.
#ifndef MLN_LINEAR_LINE_CONVOLVE_HH
# define MLN_LINEAR_LINE_CONVOLVE_HH
/*! \file mln/linear/line_convolve.hh
*
* \brief Convolution by an horizontal kernel.
*/
# include <vector>
# include <mln/linear/convolve.hh>
# include <mln/make/w_window_line.hh>
# include <mln/core/t_image.hh>
namespace mln
{
namespace linear
{
/*! Convolution of an image \p input by an horizontal weighted
* window defined by the array of \p weights.
*
* \warning Computation of \p output(p) is performed with the
* value type of \p output.
*
* \warning The weighted window is used as-is, considering that
* its symmetrization is handled by the client.
*
* \pre output.domain = input.domain
*/
template <typename I, typename W, unsigned N, typename O>
void line_convolve(const Image<I>& input, const W (&weights)[N],
Image<O>& output);
// FIXME: Doc!
template <typename I, typename W, unsigned Nr, unsigned Nc, typename O>
void line_convolve(const Image<I>& input,
const W (&row_weights)[Nr], const W (&col_weights)[Nc],
Image<O>& output);
# ifndef MLN_INCLUDE_ONLY
template <typename I, typename W, unsigned N, typename O>
void line_convolve(const Image<I>& input, const W (&weights)[N],
Image<O>& output)
{
mln_precondition(exact(output).domain() == exact(input).domain());
linear::convolve(input,
make::w_window_line<mln_dpoint(I)>(weights),
output);
}
template <typename I, typename W, unsigned Nr, unsigned Nc, typename O>
void line_convolve(const Image<I>& input,
const W (&row_weights)[Nr], const W (&col_weights)[Nc],
Image<O>& output)
{
// FIXME: Check 2D.
mln_precondition(exact(output).domain() == exact(input).domain());
O tmp(exact(output).domain());
linear::convolve(input,
make::w_window_line<mln_dpoint(I)>(row_weights),
tmp);
t_image<O> swap_output = swap_coords(output, 0, 1);
linear::convolve(swap_coords(tmp, 0, 1),
make::w_window_line<mln_dpoint(I)>(col_weights),
swap_output);
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::linear
} // end of namespace mln
#endif // ! MLN_LINEAR_LINE_CONVOLVE_HH
// Copyright (C) 2007 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License version 2 as published by the
// Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; see the file COPYING. If not, write to
// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
// Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free
// software library without restriction. Specifically, if other files
// instantiate templates or use macros or inline functions from this
// file, or you compile this file and link it with other files to
// produce an executable, this file does not by itself cause the
// resulting executable to be covered by the GNU General Public
// License. This exception does not however invalidate any other
// reasons why the executable file might be covered by the GNU General
// Public License.
#ifndef MLN_LINEAR_LINE_CONVOLVE_HH
# define MLN_LINEAR_LINE_CONVOLVE_HH
/*! \file mln/linear/line_convolve.hh
*
* \brief Convolution by a line-shaped kernel.
*/
# include <mln/linear/convolve.hh>
# include <mln/make/w_window_line.hh>
namespace mln
{
namespace linear
{
/*! Convolution of an image \p input by a line-shaped weighted
* window defined by the array of \p weights.
*
* \warning Computation of \p output(p) is performed with the
* value type of \p output.
*
* \warning The weighted window is used as-is, considering that
* its symmetrization is handled by the client.
*
* \pre output.domain = input.domain
*/
template <typename I, typename W, unsigned N, typename O>
void line_convolve(const Image<I>& input, const W (&weights)[N],
Image<O>& output);
# ifndef MLN_INCLUDE_ONLY
template <typename I, typename W, unsigned N, typename O>
void line_convolve(const Image<I>& input, const W (&weights)[N],
Image<O>& output)
{
mln_precondition(exact(output).domain() == exact(input).domain());
linear::convolve(input,
make::w_window_line<mln_dpoint(I)>(weights),
output);
}
# endif // ! MLN_INCLUDE_ONLY