Commit 0b6be5d5 authored by Thierry Geraud's avatar Thierry Geraud
Browse files

Add local convolution.

	* mln/core/concept/doc/generalized_pixel.hh,
	* mln/core/concept/generalized_pixel.hh,
	* mln/core/internal/pixel_impl.hh (ima): New.
	* mln/core/concept/doc/generalized_pixel.hh,
	* mln/core/concept/doc/pixel_iterator.hh 
	* mln/core/concept/generalized_pixel.hh,
	* mln/core/concept/pixel_iterator.hh,
	* mln/core/dpoints_pixter.hh (ctor): Better sig.
	(center_value): Rename as...
	(center_val): ...this.
	* mln/core/internal/pixel_impl.hh (operator*): Rename as...
	(val): ...this.
	* mln/debug/iota.hh,
	* mln/histo/compute.hh,
	* mln/level/apply.hh,
	* mln/level/assign.hh,
	* mln/level/fast_median.hh,
	* mln/level/take.hh,
	* mln/level/transform.hh,
	* mln/linear/convolve.hh,
	: Update.
	* mln/core/pixel.hh (is_valid): Disambiguate.
	(include): Fix.

	* mln/linear/local: New directory.
	* mln/linear/local/convolve.hh: New.
	* mln/make/pixel.hh: New.
	* mln/metal/const.hh: New.
	* tests/decorated_image.cc: Fix warning.
	* tests/local_convolve.cc: New.
	* tests/pixel.cc: Update and augment.
	* tests/pixter_point2d.cc: Rename as...
	* tests/pixter2d_b.cc: ...this.
	Clean, update, and augment.
	* tests/pixter_dpoint2d.cc: Rename as...
	* tests/dpoints_pixter.cc: ...this.
	Clean, update, and augment.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@1054 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent ef48f52d
2007-08-27 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Add local convolution.
* mln/core/concept/doc/generalized_pixel.hh,
* mln/core/concept/generalized_pixel.hh,
* mln/core/internal/pixel_impl.hh (ima): New.
* mln/core/concept/doc/generalized_pixel.hh,
* mln/core/concept/doc/pixel_iterator.hh
* mln/core/concept/generalized_pixel.hh,
* mln/core/concept/pixel_iterator.hh,
* mln/core/dpoints_pixter.hh (ctor): Better sig.
(center_value): Rename as...
(center_val): ...this.
* mln/core/internal/pixel_impl.hh (operator*): Rename as...
(val): ...this.
* mln/debug/iota.hh,
* mln/histo/compute.hh,
* mln/level/apply.hh,
* mln/level/assign.hh,
* mln/level/fast_median.hh,
* mln/level/take.hh,
* mln/level/transform.hh,
* mln/linear/convolve.hh,
: Update.
* mln/core/pixel.hh (is_valid): Disambiguate.
(include): Fix.
* mln/linear/local: New directory.
* mln/linear/local/convolve.hh: New.
* mln/make/pixel.hh: New.
* mln/metal/const.hh: New.
* tests/decorated_image.cc: Fix warning.
* tests/local_convolve.cc: New.
* tests/pixel.cc: Update and augment.
* tests/pixter_point2d.cc: Rename as...
* tests/pixter2d_b.cc: ...this.
Clean, update, and augment.
* tests/pixter_dpoint2d.cc: Rename as...
* tests/dpoints_pixter.cc: ...this.
Clean, update, and augment.
2007-08-27 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Add proper inheritance to functions.
......
......@@ -61,7 +61,14 @@ namespace mln
*
* \return A read-only value.
*/
rvalue operator*() const;
rvalue val() const;
/*! \brief Give the image of this generalized pixel.
*
* The constness of a pixel object is not transmitted to the
* underlying image.
*/
image& ima() const;
/*! \brief Give a hook to the value address.
*
......
......@@ -47,12 +47,12 @@ namespace mln
*/
typedef void lvalue;
/*! \brief Dereference operator.
/*! \brief Give the pixel value.
*
* \return The current pixel value; this value cannot be
* modified.
*/
lvalue operator*() const;
lvalue val() const;
protected:
Pixel_Iterator();
......
......@@ -62,9 +62,10 @@ namespace mln
/*
typedef value;
typedef rvalue;
typedef image;
typedef image; // is const or not
rvalue operator*() const;
rvalue val() const;
image& ima() const;
mln_qlf_value(image)** address_() const;
*/
protected:
......@@ -80,13 +81,16 @@ namespace mln
typedef mln_value(E) value;
typedef mln_rvalue(E) rvalue;
rvalue (E::*m1)() const = & E::operator*;
rvalue (E::*m1)() const = & E::val;
m1 = 0;
typedef mln_image(E) image;
mln_qlf_value(image)** (E::*m2)() const = & E::address_;
// FIXME: check "without &"
image& (E::*m2)() const = & E::ima;
m2 = 0;
mln_qlf_value(image)** (E::*m3)() const = & E::address_;
m3 = 0;
}
# endif // ! MLN_INCLUDE_ONLY
......
......@@ -57,7 +57,7 @@ namespace mln
only if the iterator is constructed on a mutable image:
typedef lvalue;
lvalue operator*();
lvalue val();
*/
protected:
Pixel_Iterator();
......@@ -70,7 +70,7 @@ namespace mln
Pixel_Iterator<E>::Pixel_Iterator()
{
// typedef mln_lvalue(E) lvalue;
// lvalue (E::*m)() = & E::operator*;
// lvalue (E::*m)() = & E::val;
// m = 0;
}
......
......@@ -71,14 +71,12 @@ namespace mln
/*! \brief Constructor.
*
* \param[in] image Image subject to iteration.
* \param[in] dps Object that can provide a set of delta-points.
* \param[in] p_ref Center (generalized) pixel to iterate around.
* \param[in] pxl_ref Center (generalized) pixel to iterate around.
* \param[in] dps Object that can provide a set of delta-points.
*/
template <typename Dps, typename Pref>
dpoints_fwd_pixter(I& image,
const Dps& dps,
const Generalized_Pixel<Pref>& p_ref);
dpoints_fwd_pixter(const Generalized_Pixel<Pref>& pxl_ref,
const Dps& dps);
/// Start an iteration.
void start();
......@@ -97,7 +95,7 @@ namespace mln
void update();
/// The value around which this iterator moves.
const mln_value(I)& center_value() const;
const mln_value(I)& center_val() const;
private:
......@@ -140,23 +138,23 @@ namespace mln
init_(dps);
}
template <typename I>
template <typename Dps, typename Pref>
dpoints_fwd_pixter<I>::dpoints_fwd_pixter(I& image,
const Dps& dps,
const Generalized_Pixel<Pref>& p_ref)
: super_(image)
dpoints_fwd_pixter<I>::dpoints_fwd_pixter(const Generalized_Pixel<Pref>& pxl_ref_,
const Dps& dps)
: super_(internal::force_exact<Pref>(pxl_ref_).ima())
{
mln_precondition(image.has_data());
const Pref& pxl_ref = internal::force_exact<Pref>(pxl_ref_);
mln_precondition(pxl_ref.ima().has_data());
p_ref_ = 0;
value_ref_ = internal::force_exact<Pref>(p_ref).address_();
// potential promotion from (T**) to (const T**) shall be forced:
value_ref_ = (mln_qlf_value(I)**)(void*)(pxl_ref.address_());
init_(dps);
}
template <typename I>
const mln_value(I)&
dpoints_fwd_pixter<I>::center_value() const
dpoints_fwd_pixter<I>::center_val() const
{
mln_invariant(value_ref_ != 0 || p_ref_ != 0);
if (p_ref_)
......
......@@ -67,10 +67,14 @@ namespace mln
/// pixel iterator value.
lvalue operator*();
lvalue val();
/// Get the pixel iterator value.
rvalue operator*() const;
rvalue val() const;
/// Give the pixel image.
I& ima() const;
/// Address of the current iterator value/pixel.
......@@ -113,7 +117,11 @@ namespace mln
/// Get the pixel iterator value.
rvalue operator*() const;
rvalue val() const;
/// Give the pixel image.
const I& ima() const;
/// Address of the current iterator value/pixel.
......@@ -155,7 +163,7 @@ namespace mln
template <typename I, typename E>
mln_lvalue(I)
pixel_impl_<I, E>::operator*()
pixel_impl_<I, E>::val()
{
mln_precondition(is_valid_());
return *value_ptr_;
......@@ -163,12 +171,20 @@ namespace mln
template <typename I, typename E>
mln_rvalue(I)
pixel_impl_<I, E>::operator*() const
pixel_impl_<I, E>::val() const
{
mln_precondition(is_valid_());
return *value_ptr_;
}
template <typename I, typename E>
I&
pixel_impl_<I, E>::ima() const
{
// a const pixel, yet a mutable image
return const_cast<I&>(image_);
}
template <typename I, typename E>
mln_value(I) **
pixel_impl_<I, E>::address_() const
......@@ -195,12 +211,19 @@ namespace mln
template <typename I, typename E>
mln_rvalue(I)
pixel_impl_<const I, E>::operator*() const
pixel_impl_<const I, E>::val() const
{
mln_precondition(is_valid_());
return *value_ptr_;
}
template <typename I, typename E>
const I&
pixel_impl_<const I, E>::ima() const
{
return image_;
}
template <typename I, typename E>
const mln_value(I) **
pixel_impl_<const I, E>::address_() const
......
......@@ -94,6 +94,7 @@
/// Shortcut to access the image type associated to T.
# define mln_image(T) typename T::image
# define mln_image_(T) T::image
// l
......
......@@ -96,12 +96,11 @@ namespace mln
bool
pixel<I>::is_valid() const
{
I& ima = this->image_;
if (this->value_ptr_ == 0 || ! ima.has_data())
if (this->value_ptr_ == 0 || ! this->image_.has_data())
return false;
int o = this->value_ptr_ - ima.buffer();
mln_point(I) p = ima.point_at_offset(o);
return ima.owns_(p);
int o = this->value_ptr_ - this->image_.buffer();
mln_point(I) p = this->image_.point_at_offset(o);
return this->image_.owns_(p);
}
# endif // ! MLN_INCLUDE_ONLY
......@@ -109,4 +108,7 @@ namespace mln
} // end of namespace mln
# include <mln/make/pixel.hh>
#endif // ! MLN_CORE_PIXEL_HH
......@@ -69,7 +69,7 @@ namespace mln
I& input = exact(input_);
mln_pixter(I) p(input);
for_all(p)
*p = ++i;
p.val() = ++i;
}
} // end of namespace mln::debug::impl
......
......@@ -71,7 +71,7 @@ namespace mln
data<mln_vset(I)> h(input.values());
mln_pixter(const I) p(input);
for_all(p)
++h(*p);
++h(p.val());
return h;
}
......
......@@ -86,7 +86,7 @@ namespace mln
mln_pixter(const I) pxl(input);
for_all(pxl)
f(input(*pxl));
f(pxl.val());
return f;
}
......
......@@ -80,7 +80,7 @@ namespace mln
mln_pixter(L) lhs(target);
mln_pixter(const R) rhs(data);
for_all_2(lhs, rhs)
*lhs = *rhs;
lhs.val() = rhs.val();
}
} // end of namespace mln::level::impl
......
......@@ -99,7 +99,7 @@ namespace mln
{
mln_qixter(const I, W) q(input, win, p);
for_all(q)
med.take(*q);
med.take(q.val());
}
int& row = p.row();
......@@ -114,10 +114,10 @@ namespace mln
// "go down"
for_all(q_top)
med.untake(*q_top);
med.untake(q_top.val());
for_all(q_bot)
med.take(*q_bot);
med.take(q_bot.val());
output(p) = med.to_value();
......@@ -127,9 +127,9 @@ namespace mln
{
++col;
for_all(q_fm)
med.untake(*q_fm);
med.untake(q_fm.val());
for_all(q_fp)
med.take(*q_fp);
med.take(q_fp.val());
output(p) = med.to_value();
}
else
......@@ -138,9 +138,9 @@ namespace mln
{
--col;
for_all(q_bm)
med.untake(*q_bm);
med.untake(q_bm.val());
for_all(q_bp)
med.take(*q_bp);
med.take(q_bp.val());
output(p) = med.to_value();
}
// change browsing
......
......@@ -77,7 +77,7 @@ namespace mln
const I& input = exact(input_);
mln_pixter(const I) pxl(input);
for_all(pxl)
a.take(*pxl);
a.take(pxl.val());
}
} // end of namespace mln::level::impl
......
......@@ -31,6 +31,8 @@
/*! \file mln/level/transform.hh
*
* \brief Transform the contents of an image into another one.
*
* \todo Clean this file + overload with pixel iterators.
*/
# include <mln/core/concept/image.hh>
......@@ -110,7 +112,7 @@ namespace mln
// po.start();
// for_all(pi)
// {
// *po = lut(*pi);
// po.val() = lut(pi.val());
// po.next();
// }
// }
......
......@@ -46,11 +46,14 @@ namespace mln
namespace linear
{
/*! Convolution of image \p input by the weighted window \p win.
/*! Convolution of 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.
*
* \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, typename O>
......@@ -97,26 +100,29 @@ namespace mln
mln_pixter(O) p_out(output);
mln_pixter(const I) p(input);
mln_qixter(const I, W) q(input, w_win, p);
mln_qixter(const I, W) q(p, w_win);
for_all_2(p, p_out)
{
mln_value(O) v = 0;
unsigned i = 0;
for_all(q)
v += w_win.w(i++) * *q;
*p_out = v;
v += w_win.w(i++) * q.val();
p_out.val() = v;
}
}
} // end of namespace mln::linear::impl
// Facade.
template <typename I, typename W, typename O>
void convolve(const Image<I>& input, const Weighted_Window<W>& w_win,
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_LOCAL_CONVOLVE_HH
# define MLN_LINEAR_LOCAL_CONVOLVE_HH
/*! \file mln/linear/local/convolve.hh
*
* \brief Local convolution at a point.
*/
# include <mln/core/concept/image.hh>
# include <mln/core/concept/generalized_point.hh>
# include <mln/core/concept/generalized_pixel.hh>
# include <mln/core/concept/weighted_window.hh>
# include <mln/metal/const.hh>
namespace mln
{
namespace linear
{
namespace local
{
/*! Local convolution of image \p input at point \p p by the
* weighted window \p w_win.
*
* \warning Computation of the \p result is performed with the
* type \c R.
*
* \warning The weighted window is used as-is, considering that
* its symmetrization is handled by the client.
*/
template <typename I, typename P, typename W, typename R>
void convolve(const Image<I>& input,
const Generalized_Point<P>& p,
const Weighted_Window<W>& w_win,
R& result);
/*! Local convolution around (generalized) pixel \p by the
* weighted window \p w_win.
*
* \warning Computation of the \p result is performed with the
* type \c R.
*
* \warning The weighted window is used as-is, considering that
* its symmetrization is handled by the client.
*/
template <typename P, typename W, typename R>
void convolve(const Generalized_Pixel<P>& p,
const Weighted_Window<W>& w_win,
R& result);
# ifndef MLN_INCLUDE_ONLY
namespace impl
{
template <typename I, typename P, typename W, typename R>
void convolve(const Image<I>& input_,
const Generalized_Point<P>& p_,
const W& w_win,
R& result)
{
const I& input = exact(input_);
const P& p = internal::force_exact<P>(p_);
R tmp = 0; // FIXME: zero?
mln_qiter(W) q(w_win, p);
for_all(q) if (input.has(q))
tmp += input(q) * q.w();
result = tmp;
}
template <typename I, typename P, typename W, typename R>
void convolve(const Fast_Image<I>& input_,
const Generalized_Point<P>& p_,
const W& w_win,
R& result)
{
const I& input = exact(input_);
const P& p = internal::force_exact<P>(p_);
mln_precondition(input.border() >= w_win.delta());
R tmp = 0;
unsigned i = 0;
mln_qixter(const I, W) q(input, w_win, p);
for_all(q)
tmp += w_win.w(i++) * q.val();
result = tmp;
}
template <typename P, typename W, typename R>
void convolve(const Generalized_Pixel<P>& p_,
const W& w_win,
R& result)
{
const P& p = internal::force_exact<P>(p_);
mln_precondition(p.ima().border() >= w_win.delta());
R tmp = 0;
unsigned i = 0;
// FIXME: mln_qixter(const P, W) should work
// FIXME: so make the trait make this job...
mln_qixter(mlc_const(mln_image(P)), W) q(p, w_win);
for_all(q)
tmp += w_win.w(i++) * q.val();
result = tmp;
}
} // end of namespace mln::linear::impl
// Facades.
template <typename I, typename P, typename W, typename R>
void convolve(const Image<I>& input,