Commit 1681fb5f authored by Roland Levillain's avatar Roland Levillain
Browse files

apps/bench: More comparisons on dilation (static windows and qixters).

	* apps/bench/static_array.hh,
	* apps/bench/static_dpoints_pixter.hh,
	* apps/bench/static_window.hh:
	New.
	* apps/bench/dilation-lena.cc (fast_static::dilation):
	New function.
	Exercise it...
	(main): ...here.
	* apps/bench/Makefile.am (noinst_HEADERS): Add static_array.hh,
	static_dpoints_pixter.hh and static_window.hh.
	(MOSTLYCLEANFILES): Update.
parent ad8c64bf
2010-12-14 Roland Levillain <roland@lrde.epita.fr>
apps/bench: More comparisons on dilation (static windows and qixters).
* apps/bench/static_array.hh,
* apps/bench/static_dpoints_pixter.hh,
* apps/bench/static_window.hh:
New.
* apps/bench/dilation-lena.cc (fast_static::dilation):
New function.
Exercise it...
(main): ...here.
* apps/bench/Makefile.am (noinst_HEADERS): Add static_array.hh,
static_dpoints_pixter.hh and static_window.hh.
(MOSTLYCLEANFILES): Update.
2010-12-13 Roland Levillain <roland@lrde.epita.fr>
 
apps/bench: Comparison on dilation.
......@@ -25,13 +25,17 @@ noinst_PROGRAMS = \
noinst_HEADERS = \
and_not.hh \
minus.hh
minus.hh \
static_array.hh \
static_dpoints_pixter.hh \
static_window.hh
MOSTLYCLEANFILES = \
dilation-lena-out-spe.pgm \
dilation-lena-out-gen.pgm \
dilation-lena-out-fast.pgm \
dilation-lena-out-faster.pgm \
dilation-lena-out-fast_static.pgm \
gradient-lena-out.pgm \
gradient-spe-lena-out-0.pgm \
gradient-spe-lena-out-1.pgm \
......
......@@ -37,6 +37,8 @@
#include <mln/util/timer.hh>
#include "apps/bench/static_window.hh"
#include "apps/bench/static_dpoints_pixter.hh"
#include "apps/data.hh"
......@@ -134,6 +136,33 @@ namespace faster
}
}
namespace fast_static
{
using namespace mln;
template <typename I, typename W>
mln_concrete(I) dilation(const I& input, const W& win)
{
typedef mln_concrete(I) O;
O output; initialize(output, input); // Initialize output.
mln_pixter(const I) pi(input); // Iterator on the pixels of `input'.
mln_pixter(O) po(output); // Iterator on the pixels of `output'.
typedef mln::static_dpoints_fwd_pixter<const I, W::Size> mln_static_qixter;
mln_static_qixter q(pi, win);
for_all_2(pi, po)
{
// FIXME: Cheat: replace the accu::supremum by a maximum.
mln::accu::stat::max<mln_value(I)> sup; // Accumulator computing the supremum.
for_all(q)
sup.take(q.val());
po.val() = sup.to_result();
}
return output;
}
}
int main()
{
......@@ -170,4 +199,20 @@ int main()
t.stop();
std::cout << t.read() << std::endl;
io::pgm::save(d, "dilation-lena-out-faster.pgm");
const unsigned n = 5;
mln::dpoint2d dps[n] = { mln::dpoint2d( 0, -1),
mln::dpoint2d(-1, 0),
mln::dpoint2d( 0, 0),
mln::dpoint2d(+1, 0),
mln::dpoint2d( 0, +1) };
mln::util::static_array<mln::dpoint2d, n> sa(dps, dps + n);
mln::static_window<mln::dpoint2d, n> static_win_c4p (sa);
t.start();
d = fast_static::dilation(lena, static_win_c4p);
t.stop();
std::cout << t.read() << std::endl;
io::pgm::save(d, "dilation-lena-out-fast_static.pgm");
}
// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
// Olena is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, version 2 of the License.
//
// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
//
// As a special exception, you may use this file as part of a free
// software project 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_UTIL_STATIC_ARRAY_HH
# define MLN_UTIL_STATIC_ARRAY_HH
// FIXME: Add documentation.
# include <cstddef>
# include <algorithm>
# include <mln/core/internal/window_base.hh>
# include <mln/core/concept/gdpoint.hh>
# include <mln/metal/is_a.hh>
# include <mln/util/set.hh>
# include <mln/fun/i2v/all_to.hh>
# include <mln/norm/linfty.hh>
# include <mln/literal/zero.hh>
namespace mln
{
namespace util
{
template <typename T, std::size_t n>
class static_array
{
public:
// FIXME: Careful, this ctor initializes nothing.
static_array();
// FIXME: Find a better way to build this static array.
template <typename InputIterator>
static_array(InputIterator first, InputIterator last);
T& operator[](std::size_t i);
const T& operator[](std::size_t i) const;
bool has(const T& value) const;
private:
T data_[n];
};
template <typename D, std::size_t n>
bool
operator==(const static_array<D, n>& lhs, const static_array<D, n>& rhs);
# ifndef MLN_INCLUDE_ONLY
template <typename T, std::size_t n>
inline
static_array<T, n>::static_array()
{
}
template <typename T, std::size_t n>
template <typename InputIterator>
inline
static_array<T, n>::static_array(InputIterator first, InputIterator last)
{
mln_precondition(std::distance(first, last) == n);
std::copy(first, last, data_);
}
template <typename T, std::size_t n>
inline
T&
static_array<T, n>::operator[](std::size_t i)
{
return data_[i];
}
template <typename T, std::size_t n>
inline
const T&
static_array<T, n>::operator[](std::size_t i) const
{
return data_[i];
}
template <typename T, std::size_t n>
inline
bool
static_array<T, n>::has(const T& value) const
{
return std::find(data_, data_ + n, value) != data_ + n;
}
template <typename D, std::size_t n>
inline
bool
operator==(const static_array<D, n>& lhs, const static_array<D, n>& rhs)
{
for(std::size_t i = 0; i < n; ++i)
if (lhs[i] != rhs[i])
return false;
return true;
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::util
} // end of namespace mln
#endif // ! MLN_UTIL_STATIC_ARRAY_HH
// Copyright (C) 2007, 2008, 2009, 2010 EPITA Research and Development
// Laboratory (LRDE)
//
// This file is part of Olena.
//
// Olena is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, version 2 of the License.
//
// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
//
// As a special exception, you may use this file as part of a free
// software project 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_CORE_STATIC_DPOINTS_PIXTER_HH
# define MLN_CORE_STATIC_DPOINTS_PIXTER_HH
// FIXME: Review and update the documentation.
/// \file
///
/// \brief Definition of forward and backward mln::dpoint-based
/// iterators for pixels iterations.
///
/// \todo In ::init_ use offsets_wrt (defined in concept/window.hh).
# include <cassert>
# include <vector>
# include <mln/core/concept/proxy.hh>
# include <mln/core/concept/pixel_iterator.hh>
# include <mln/core/internal/pixel_impl.hh>
# include <mln/metal/converts_to.hh>
# include "apps/bench/static_array.hh"
namespace mln
{
/*----------------------------------.
| static_dpoints_fwd_pixter<I, n>. |
`----------------------------------*/
/// \brief A generic forward iterator on the pixels of a
/// dpoint-based window or neighborhood.
///
/// Parameter \c I is the image type.
template <typename I, unsigned n>
class static_dpoints_fwd_pixter
: public Pixel_Iterator< static_dpoints_fwd_pixter<I, n> >,
public internal::pixel_impl_< I, static_dpoints_fwd_pixter<I, n> >
{
typedef typename internal::pixel_impl_< I, static_dpoints_fwd_pixter<I, n> > super_;
public:
/// \brief Constructor (using an image).
///
/// \param[in] image The image to iterate over.
/// \param[in] dps An object (neighborhood or window) that can
/// provide a set of delta-points.
/// \param[in] p_ref Center (resp. reference) point of the
/// neighborhood (resp. window).
template <typename Dps, typename Pref>
static_dpoints_fwd_pixter(I& image,
const Dps& dps,
const Pref& p_ref);
/// \brief Constructor (using a generalized pixel).
///
/// \param[in] pxl_ref Center (generalized) pixel to iterate around.
/// \param[in] dps An object (neighborhood or window) that can
/// provide a set of delta-points.
template <typename Dps, typename Pref>
static_dpoints_fwd_pixter(const Generalized_Pixel<Pref>& pxl_ref,
const Dps& dps);
/// Manipulation.
/// \{
/// Start an iteration.
void start();
/// Go to the next pixel.
void next_();
/// Invalidate the iterator.
void invalidate();
/// Test the iterator validity.
bool is_valid() const;
/// Force this iterator to update its location to take into
/// account that its center point may have moved.
void update();
/// \}
/// The value around which this iterator moves.
const mln_value(I)& center_val() const;
private:
template <typename Dps>
void init_(const Dps& dps);
private:
/// \brief Offset of each delta-point.
///
/// offset_[0] is absolute, while other offsets are relative
/// (i.e., offset_[i] is the memory difference to go from pixel
/// i-1 to pixel i.
util::static_array<int, n> offset_;
/// Current offset.
std::size_t i_;
/// \brief Reference value or pixel.
///
/// One and only one of these pointers should be non-null.
/// \{
/// Reference value the image
mln_qlf_value(I)** value_ref_;
/// Reference pixel / point in the image
const mln_psite(I)* p_ref_;
/// \}
};
/*----------------------------------.
| static_dpoints_bkd_pixter<I, n>. |
`----------------------------------*/
/// \brief A generic backward iterator on the pixels of a
/// dpoint-based window or neighborhood.
///
/// Parameter \c I is the image type.
template <typename I, unsigned n>
class static_dpoints_bkd_pixter
: public Pixel_Iterator< static_dpoints_bkd_pixter<I, n> >,
public internal::pixel_impl_< I, static_dpoints_bkd_pixter<I, n> >
{
typedef typename internal::pixel_impl_< I, static_dpoints_bkd_pixter<I, n> > super_;
public:
/// \brief Constructor (using an image).
///
/// \param[in] image The image to iterate over.
/// \param[in] dps An object (neighborhood or window) that can
/// provide a set of delta-points.
/// \param[in] p_ref Center (resp. reference) point of the
/// neighborhood (resp. window).
template <typename Dps, typename Pref>
static_dpoints_bkd_pixter(I& image,
const Dps& dps,
const Pref& p_ref);
/// \brief Constructor (using a generalized pixel).
///
/// \param[in] pxl_ref Center (generalized) pixel to iterate around.
/// \param[in] dps An object (neighborhood or window) that can
/// provide a set of delta-points.
template <typename Dps, typename Pref>
static_dpoints_bkd_pixter(const Generalized_Pixel<Pref>& pxl_ref,
const Dps& dps);
/// Manipulation.
/// \{
/// Start an iteration.
void start();
/// Go to the next pixel.
void next_();
/// Invalidate the iterator.
void invalidate();
/// Test the iterator validity.
bool is_valid() const;
/// Force this iterator to update its location to take into
/// account that its center point may have moved.
void update();
/// \}
/// The value around which this iterator moves.
const mln_value(I)& center_val() const;
private:
template <typename Dps>
void init_(const Dps& dps);
private:
/// \brief Offset of each delta-point.
///
/// offset_[dps.size() - 1] is absolute, while other offsets
/// are relative (i.e., offset_[i] is the memory difference to go
/// from pixel i+1 to pixel i.
util::static_array<int, n> offset_;
/// Current offset.
std::size_t i_;
/// \brief Reference value or pixel.
///
/// One and only one of these pointers should be non-null.
/// \{
/// Reference value the image
mln_qlf_value(I)** value_ref_;
/// Reference pixel / point in the image
const mln_psite(I)* p_ref_;
/// \}
};
#ifndef MLN_INCLUDE_ONLY
/*----------------------------------.
| static_dpoints_fwd_pixter<I, n>. |
`----------------------------------*/
template <typename I, unsigned n>
template <typename Dps, typename Pref>
inline
static_dpoints_fwd_pixter<I, n>::static_dpoints_fwd_pixter(I& image,
const Dps& dps,
const Pref& p_ref)
: super_(image)
{
mln_precondition(image.is_valid());
mlc_converts_to(Pref, const mln_psite(I)&)::check();
p_ref_ = & static_cast< const mln_psite(I)& >(p_ref);
value_ref_ = 0;
init_(dps);
}
template <typename I, unsigned n>
template <typename Dps, typename Pref>
inline
static_dpoints_fwd_pixter<I, n>::static_dpoints_fwd_pixter(const Generalized_Pixel<Pref>& pxl_ref_,
const Dps& dps)
: super_(internal::force_exact<Pref>(pxl_ref_).ima())
{
const Pref& pxl_ref = internal::force_exact<Pref>(pxl_ref_);
mln_precondition(pxl_ref.ima().is_valid());
p_ref_ = 0;
// Potential promotion from (T**) to (const T**) shall be forced.
value_ref_ = const_cast<mln_qlf_value(I)**>(pxl_ref.address_());
init_(dps);
}
template <typename I, unsigned n>
inline
const mln_value(I)&
static_dpoints_fwd_pixter<I, n>::center_val() const
{
mln_invariant(value_ref_ != 0 || p_ref_ != 0);
if (p_ref_)
return this->image_(*p_ref_);
else
return **value_ref_;
}
template <typename I, unsigned n>
template <typename Dps>
inline
void
static_dpoints_fwd_pixter<I, n>::init_(const Dps& dps)
{
for (unsigned i = 0; i < dps.size(); ++i)
offset_[i] = this->image_.delta_offset(dps.dp(i));
// offset_[0] is absolute
// other offsets are relative:
if (dps.size() > 1)
for (unsigned i = dps.size() - 1; i > 0; --i)
offset_[i] -= offset_[i - 1];
invalidate();
}
template <typename I, unsigned n>
inline
void
static_dpoints_fwd_pixter<I, n>::update()
{
if (is_valid())
{
if (p_ref_)
this->value_ptr_ = & this->image_(*p_ref_) + offset_[i_];
else
this->value_ptr_ = * value_ref_ + offset_[i_];
}
}
template <typename I, unsigned n>
inline
void
static_dpoints_fwd_pixter<I, n>::start()
{
i_ = 0;
update();
}
template <typename I, unsigned n>
inline
void
static_dpoints_fwd_pixter<I, n>::next_()
{
++i_;
if (is_valid())
this->value_ptr_ += offset_[i_];
}
template <typename I, unsigned n>
inline
bool
static_dpoints_fwd_pixter<I, n>::is_valid() const
{
return i_ < n;
}
template <typename I, unsigned n>
inline
void
static_dpoints_fwd_pixter<I, n>::invalidate()
{
i_ = n;
}
/*----------------------------------.
| static_dpoints_bkd_pixter<I, n>. |
`----------------------------------*/
template <typename I, unsigned n>
template <typename Dps, typename Pref>
inline
static_dpoints_bkd_pixter<I, n>::static_dpoints_bkd_pixter(I& image,
const Dps& dps,
const Pref& p_ref)
: super_(image)
{
mln_precondition(image.is_valid());
internal::get_adr(p_ref_, p_ref);
value_ref_ = 0;
init_(dps);
}
template <typename I, unsigned n>
template <typename Dps, typename Pref>
inline
static_dpoints_bkd_pixter<I, n>::static_dpoints_bkd_pixter(const Generalized_Pixel<Pref>& pxl_ref_,
const Dps& dps)
: super_(internal::force_exact<Pref>(pxl_ref_).ima())
{
const Pref& pxl_ref = internal::force_exact<Pref>(pxl_ref_);
mln_precondition(pxl_ref.ima().is_valid());
p_ref_ = 0;
// Potential promotion from (T**) to (const T**) shall be forced.
value_ref_ = const_cast<mln_qlf_value(I)**>(pxl_ref.address_());
init_(dps);
}
template <typename I, unsigned n>
inline
const mln_value(I)&
static_dpoints_bkd_pixter<I, n>::center_val() const
{
mln_invariant(value_ref_ != 0 || p_ref_ != 0);
if (p_ref_)
return this->image_(*p_ref_);
else
return **value_ref_;
}