Commit 4a1c591a authored by Thierry Geraud's avatar Thierry Geraud
Browse files

Add stack and transpose morphers.

	* tests/t_image.cc: New.
	* tests/stack.cc: New.
	* tests/approx_median.cc: New.
	* mln/core/t_image.hh: New.
	* mln/value/stack.hh: New.
	* tests/median.cc: Update.
	* tests/README: Update.
	* mln/core/internal/image_base.hh
	(morpher_lvalue_): New.
	* mln/core/internal/image_adaptor.hh: Use morpher_lvalue_.
	(image_adaptor_): Change Image<I> into I.
	* mln/core/safe.hh: Update.
	* mln/core/image2d_b.hh: Remove dead code.
	* mln/metal/vec.hh: Split decls and defs.
	(operator<<): New.
	* mln/level/median.hh (hline2d): Update.
	(vline2d): New.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@1042 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent 585b68e6
2007-07-26 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Add stack and transpose morphers.
* tests/t_image.cc: New.
* tests/stack.cc: New.
* tests/approx_median.cc: New.
* mln/core/t_image.hh: New.
* mln/value/stack.hh: New.
* tests/median.cc: Update.
* tests/README: Update.
* mln/core/internal/image_base.hh
(morpher_lvalue_): New.
* mln/core/internal/image_adaptor.hh: Use morpher_lvalue_.
(image_adaptor_): Change Image<I> into I.
* mln/core/safe.hh: Update.
* mln/core/image2d_b.hh: Remove dead code.
* mln/metal/vec.hh: Split decls and defs.
(operator<<): New.
* mln/level/median.hh (hline2d): Update.
(vline2d): New.
2007-07-26 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Fix doc.
......
......@@ -78,28 +78,14 @@ namespace mln
struct image2d_b : public internal::image_base_< box2d, image2d_b<T> >,
public internal::box_impl_< 2, int, image2d_b<T> >
{
// warning: just to make effective types appear in Doxygen
// Warning: just to make effective types appear in Doxygen:
typedef box2d pset;
typedef point2d psite;
typedef point2d point;
typedef dpoint2d dpoint;
typedef mln_fwd_piter(box2d) fwd_piter;
typedef mln_bkd_piter(box2d) bkd_piter;
// end of warning
// FIXME:
// /// Forward pixel iterator associated to image2d
// typedef fwd_pixter2d_b<T> fwd_pixter;
// /// Foward pixel iterator on dpoints assoicated to image 2d
// typedef dpoints_pixter< image2d_b<T> > fwd_qixter;
// typedef fwd_pixter pixter;
// typedef fwd_qixter qixter;
// End of warning.
/// Value associated type.
......
......@@ -68,7 +68,7 @@ namespace mln
typedef mln_rvalue(I) rvalue;
/// Return type of read-write access.
typedef mln_lvalue(I) lvalue;
typedef typename internal::morpher_lvalue_<I>::ret lvalue;
/// Test if this image has been initialized.
......@@ -94,7 +94,7 @@ namespace mln
I& adaptee_;
/// Constructor from an \p adaptee image.
image_adaptor_(Image<I>& adaptee);
image_adaptor_(I& adaptee);
};
// FIXME: image_const_adaptor_
......@@ -148,8 +148,8 @@ namespace mln
}
template <typename I, typename E, typename S>
image_adaptor_<I,E,S>::image_adaptor_(Image<I>& adaptee)
: adaptee_(exact(adaptee))
image_adaptor_<I,E,S>::image_adaptor_(I& adaptee)
: adaptee_(adaptee)
{
}
......
......@@ -43,6 +43,19 @@ namespace mln
{
template <typename I>
struct morpher_lvalue_
{
typedef mln_lvalue(I) ret;
};
template <typename I>
struct morpher_lvalue_< const I >
{
typedef mln_rvalue(I) ret;
};
template <typename Is_fast, typename E>
struct select_image_concept_;
......
......@@ -51,6 +51,7 @@ namespace mln
{
typedef safe_image<mln_ch_value(I, U)> ret;
};
};
......@@ -62,10 +63,9 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
template <typename I>
safe_image<I>::safe_image(Image<I>& ima)
: super(ima)
: super(exact(ima))
{
}
......
// 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_CORE_T_IMAGE_HH
# define MLN_CORE_T_IMAGE_HH
/*! \file mln/core/t_image.hh
*
* \brief Definition of the "transposed" image class mln::t_image.
*/
# include <mln/core/internal/image_adaptor.hh>
namespace mln
{
/*! \brief Transposed image class.
*
* Swap a couple of coordinates.
*
* \warning This class only works on images whose domain is a box.
*/
template <typename I>
struct t_image : public internal::image_adaptor_< I, t_image<I> >
{
/// Test if a pixel value is accessible at \p p.
bool owns_(const mln_point(I)& p) const;
/// Give the definition domain.
const box_<mln_point(I)>& domain() const;
/// Read-only access of pixel value at point site \p p.
mln_rvalue(I) operator()(const mln_point(I)& p) const;
/// Type returned by the read-write pixel value operator.
typedef typename internal::morpher_lvalue_<I>::ret lvalue;
/// Read-write access of pixel value at point site \p p.
lvalue operator()(const mln_point(I)& p);
/// Change value type.
template <typename U>
struct change_value
{
typedef mln_ch_value(I, U) ret;
};
/// Constructor.
t_image(I& ima, unsigned c1, unsigned c2);
protected:
typedef internal::image_adaptor_< I, t_image<I> > super_;
const unsigned c1_, c2_; // coords to swap
box_<mln_point(I)> b_;
mln_point(I) transpose_(const mln_point(I)& p) const;
};
template <typename I>
t_image<I> swap_coords(Image<I>& ima, unsigned c1, unsigned c2);
template <typename I>
t_image<const I> swap_coords(const Image<I>& ima, unsigned c1, unsigned c2);
# ifndef MLN_INCLUDE_ONLY
template <typename I>
t_image<I> swap_coords(Image<I>& ima, unsigned c1, unsigned c2)
{
typedef mln_point(I) P;
mln_precondition(c1 != c2);
mln_precondition(c1 <= P::dim && c2 <= P::dim);
t_image<I> tmp(exact(ima), c1, c2);
return tmp;
}
template <typename I>
t_image<const I> swap_coords(const Image<I>& ima, unsigned c1, unsigned c2)
{
typedef mln_point(I) P;
mln_precondition(c1 != c2);
mln_precondition(c1 <= P::dim && c2 <= P::dim);
t_image<const I> tmp(exact(ima), c1, c2);
return tmp;
}
template <typename I>
t_image<I>::t_image(I& ima, unsigned c1, unsigned c2)
: super_(ima),
c1_(c1),
c2_(c2)
{
mln_precondition(ima.has_data());
b_.pmin() = transpose_(this->adaptee_.bbox().pmin());
b_.pmax() = transpose_(this->adaptee_.bbox().pmax());
}
template <typename I>
mln_point(I)
t_image<I>::transpose_(const mln_point(I)& p) const
{
mln_point(I) tmp(p);
tmp[c1_] = p[c2_];
tmp[c2_] = p[c1_];
return tmp;
}
template <typename I>
const box_<mln_point(I)>&
t_image<I>::domain() const
{
mln_precondition(this->has_data());
return b_;
}
template <typename I>
bool
t_image<I>::owns_(const mln_point(I)& p) const
{
mln_precondition(this->has_data());
return this->adaptee_.owns_(transpose_(p));
}
template <typename I>
mln_rvalue(I)
t_image<I>::operator()(const mln_point(I)& p) const
{
mln_precondition(this->owns_(p));
return this->adaptee_(transpose_(p));
}
template <typename I>
typename internal::morpher_lvalue_<I>::ret
t_image<I>::operator()(const mln_point(I)& p)
{
mln_precondition(this->owns_(p));
return this->adaptee_(transpose_(p));
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
#endif // ! MLN_CORE_T_IMAGE_HH
......@@ -38,6 +38,7 @@
# include <mln/core/window2d.hh>
# include <mln/core/win/hline2d.hh>
# include <mln/core/t_image.hh>
# include <mln/accu/median.hh>
# include <mln/canvas/sbrowsing.hh>
......@@ -156,37 +157,41 @@ namespace mln
}
template <typename I, typename O>
void median(const I& input, const win::hline2d& win, O& output)
{
typedef mln_coord(I) coord;
const coord
max_row = input.max_row(),
min_col = input.min_col(),
max_col = input.max_col();
max_row = input.bbox().max_row(),
min_col = input.bbox().min_col(),
max_col = input.bbox().max_col();
const coord half = win.length() / 2;
point2d p;
coord& row = p.row();
coord& col = p.col();
point2d pt;
coord& ct = pt.col();
point2d pu;
coord& cu = pu.col();
accu::median<mln_vset(I)> med(input.values());
for (row = input.min_row(); row <= max_row; ++row)
for (row = input.bbox().min_row(); row <= max_row; ++row)
{
coord ct, cu;
pt.row() = pu.row() = row;
// initialization (before first point of the row)
med.init();
for (ct = min_col; ct < min_col + half; ++ct)
med.take(input.at(row, ct));
med.take(input(pt));
// left columns (just take new points)
for (col = min_col; col <= min_col + half; ++col, ++ct)
{
med.take(input.at(row, ct));
med.take(input(pt));
output(p) = med;
}
......@@ -194,29 +199,29 @@ namespace mln
cu = min_col;
for (; col <= max_col - half; ++cu, ++col, ++ct)
{
med.take(input.at(row, ct));
med.untake(input.at(row, cu));
med.take(input(pt));
med.untake(input(pu));
output(p) = med;
}
// right columns (now just untake old points)
for (; col <= max_col; ++cu, ++col)
{
med.untake(input.at(row, cu));
med.untake(input(pu));
output(p) = med;
}
}
}
// FIXME: Use transpose.
// template <typename I, typename O>
// void median(const I& input, const win::vline2d& win, O& output)
// {
// median(, win::hline2d(win.length()), output);
// }
template <typename I, typename O>
void median(const I& input, const win::vline2d& win, O& output)
{
t_image<O> swap_output = swap_coords(output, 0, 1);
impl::median(swap_coords(input, 0, 1),
win::hline2d(win.length()),
swap_output);
}
} // end of namespace mln::level::impl
......
......@@ -28,6 +28,8 @@
#ifndef MLN_CORE_METAL_VEC_HH
# define MLN_CORE_METAL_VEC_HH
# include <cstdarg>
# include <mln/core/concept/object.hh>
......@@ -37,27 +39,55 @@ namespace mln
namespace metal
{
// FIXME: Doc! + Change coord into comp.
template <unsigned n, typename T>
struct vec : public Object< vec<n,T> >
{
enum { dim = n };
typedef T coord;
T& operator[](unsigned i)
{
assert(i < n);
return coord_[i];
}
T operator[](unsigned i) const
{
assert(i < n);
return coord_[i];
}
T& operator[](unsigned i);
T operator[](unsigned i) const;
protected:
T coord_[n];
};
template <unsigned n, typename T>
std::ostream& operator<<(std::ostream& ostr, const vec<n,T>& v);
# ifndef MLN_INCLUDE_ONLY
template <unsigned n, typename T>
T&
vec<n,T>::operator[](unsigned i)
{
mln_precondition(i < n);
return coord_[i];
}
template <unsigned n, typename T>
T
vec<n,T>::operator[](unsigned i) const
{
mln_precondition(i < n);
return coord_[i];
}
template <unsigned n, typename T>
std::ostream& operator<<(std::ostream& ostr, const vec<n,T>& v)
{
ostr << "[ ";
for (unsigned i = 0; i < n; ++i)
ostr << v[i] << ' ';
return ostr << ']';
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::metal
......
// 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_VALUE_STACK_HH
# define MLN_VALUE_STACK_HH
/*! \file mln/value/stack.hh
*
* \brief Definition of an image class FIXME
*/
# include <mln/core/internal/image_base.hh>
# include <mln/metal/vec.hh>
# include <mln/value/set.hh>
namespace mln
{
namespace value
{
/*! \brief FIXME
*
*/
template <unsigned n, typename I>
struct stack_image : public mln::internal::image_base_< mln_pset(I), stack_image<n,I> >
{
/// Point_Site associated type.
typedef mln_psite(I) psite;
/// Point_Set associated type.
typedef mln_pset(I) pset;
/// Value associated type.
typedef metal::vec<n, mln_value(I)> value;
/// Return type of read-only access.
typedef value rvalue;
/// Return type of read-write access.
typedef void lvalue; // FIXME
/// Value set associated type.
typedef mln::value::set<value> vset;
/// Constructor.
stack_image(const metal::vec<n,I*>& imas);
/// Test if this image has been initialized.
bool has_data() const;
/// Test if a pixel value is accessible at \p p.
bool owns_(const psite& p) const;
/// Give the definition domain.
const mln_pset(I)& domain() const;
/// Read-only access of pixel value at point site \p p.
rvalue operator()(const psite& p) const;
/// Read-write access of pixel value at point site \p p.
void operator()(const psite&);
/// Give the set of values of the image.
const vset& values() const;
/// Change value type.
template <typename U>
struct change_value
{
typedef metal::vec<n,U> vec_n_U;
typedef mln_ch_value(I, vec_n_U) ret;
};
protected:
metal::vec<n,I*> imas_;
};
template <typename I>
stack_image<2,const I>
stack(const Image<I>& ima1, const Image<I>& ima2)
{
mln_precondition(exact(ima1).domain() == exact(ima2).domain());
metal::vec<2, const I*> imas;
imas[0] = & exact(ima1);
imas[1] = & exact(ima2);
stack_image<2, const I> tmp(imas);
return tmp;
}
# ifndef MLN_INCLUDE_ONLY
template <unsigned n, typename I>
stack_image<n,I>::stack_image(const metal::vec<n,I*>& imas)
: imas_(imas)
{
for (unsigned i = 0; i < n; ++i)
{
mln_precondition(imas[i] != 0);
mln_precondition(imas[i]->has_data());
}
}
template <unsigned n, typename I>
bool stack_image<n,I>::has_data() const
{
for (unsigned i = 0; i < n; ++i)
mln_invariant(imas_[i]->has_data());