Index: ChangeLog from Damien Thivolle <damien@lrde.epita.fr> * oln/morpho/reconstruction.hh: Remove a comment. * oln/morpho/hit_or_miss.hh: New. Hit or miss implementation. * oln/arith/ops.hh: Add comment to make it compile with g++-3.4. * oln/arith/min.hh: Add a template parameter. * oln/arith/max.hh: Add a template parameter. arith/max.hh | 38 +++++---- arith/min.hh | 38 +++++---- arith/ops.hh | 24 +++--- morpho/hit_or_miss.hh | 186 +++++++++++++++++++++++++++++++++++++++++++++++ morpho/reconstruction.hh | 2 5 files changed, 244 insertions(+), 44 deletions(-) Index: oln/morpho/reconstruction.hh --- oln/morpho/reconstruction.hh (revision 164) +++ oln/morpho/reconstruction.hh (working copy) @@ -45,8 +45,6 @@ # include <oln/utils/clone.hh> -// FIXME: ADD TESTS !!!! - namespace oln { Index: oln/morpho/hit_or_miss.hh --- oln/morpho/hit_or_miss.hh (revision 0) +++ oln/morpho/hit_or_miss.hh (revision 0) @@ -0,0 +1,186 @@ +// Copyright (C) 2001, 2003, 2004, 2005 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, 59 Temple Place - Suite 330, 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 OLENA_MORPHO_HIT_OR_MISS_HH +# define OLENA_MORPHO_HIT_OR_MISS_HH + +# include <oln/core/gen/image_with_nbh.hh> +# include <oln/morpho/erosion.hh> +# include <oln/morpho/dilation.hh> +# include <oln/arith/min.hh> +# include <oln/utils/invert.hh> + +namespace oln { + + namespace tag { + + // No tags yet + + } // end of namespace oln::morpho::tag + + + namespace morpho { + template <typename I, typename W1, typename W2> struct hit_or_miss_ret; + } // end of namespace oln::morpho + + // super_type + + template <typename I, typename W1, typename W2> + struct set_super_type< morpho::hit_or_miss_ret<I, W1, W2> > + { + typedef oln_type_of(I, concrete) output_type; + + typedef morpho::hit_or_miss_ret<I, W1, W2> self_type; + typedef abstract::image_unary_operator<output_type, I, self_type > ret; + }; + + namespace morpho { + + // Reconstruction as a 'classical' procedure returning an image (do not + // use it; prefer morpho::hit_or_miss). + + namespace proc { + + // FIXME: ... + + } // end of namespace oln::morpho::proc + + + template <typename I, typename W1, typename W2> + struct hit_or_miss_ret : + // FIXME: oln_super_of_ + public oln::internal::get_super_type< hit_or_miss_ret<I, W1, W2> >::ret + { + typedef hit_or_miss_ret<I, W1, W2> self_type; + typedef typename oln::internal::get_super_type<self_type>::ret super_type; + const W1& win1; + const W2& win2; + + hit_or_miss_ret(const abstract::image<I>& input, + const abstract::regular_window<oln_type_of(I, grid), W1> win1, + const abstract::regular_window<oln_type_of(I, grid), W2> win2) : + super_type(input), + win1(win1.exact()), + win2(win2.exact()) + { + } + + }; + + + namespace impl { + + template <typename I, typename W1, typename W2> + struct generic_hit_or_miss : public hit_or_miss_ret<I, W1, W2> + { + typedef hit_or_miss_ret<I, W1, W2> super_type; + + generic_hit_or_miss(const abstract::image<I>& input, + const abstract::regular_window<oln_type_of(I, grid), W1> win1, + const abstract::regular_window<oln_type_of(I, grid), W2> win2) : + super_type(input, win1, win2) + { + } + + void impl_run() + { + this->output = arith::min(erosion(this->input, this->win1), + erosion(utils::invert(this->input), + this->win2)); + } + }; + + template <typename I, typename W1, typename W2> + hit_or_miss_ret<I, W1, W2> + hit_or_miss(const abstract::image<I>& input, + const abstract::regular_window<oln_type_of(I, grid), W1> win1, + const abstract::regular_window<oln_type_of(I, grid), W2> win2) + { + generic_hit_or_miss<I, W1, W2> tmp(input, win1, win2); + tmp.run(); + return tmp; + } + + } //end of namespace impl + + template <typename I, typename W1, typename W2> + hit_or_miss_ret<I, W1, W2> + hit_or_miss(const abstract::image<I>& input, + const abstract::regular_window<oln_type_of(I, grid), W1> win1, + const abstract::regular_window<oln_type_of(I, grid), W2> win2) + { + // FIXME: win1 inter win2 must be empty + return impl::hit_or_miss(input.exact(), win1.exact(), win2.exact()); + } + + + template<class I, class W1, class W2> + dilation_ret<hit_or_miss_ret<I, W1, W2>, W1> + hit_or_miss_opening(const abstract::image<I>& input, + const abstract::regular_window<oln_type_of(I, grid), W1> win1, + const abstract::regular_window<oln_type_of(I, grid), W2> win2) + { + return dilation(hit_or_miss(input, win1, win2), -win1); + } + + template<class I, class W1, class W2> + dilation_ret<hit_or_miss_ret<I, W2, W1>, W2> + hit_or_miss_opening_bg(const abstract::image<I>& input, + const abstract::regular_window<oln_type_of(I, grid), W1> win1, + const abstract::regular_window<oln_type_of(I, grid), W2> win2) + { + return hit_or_miss_opening(input, win2, win1); + } + + template<class I, class W1, class W2> + utils::image_inverted<dilation_ret<hit_or_miss_ret<utils::image_inverted<I>, + W1, W2>, W1> > // !!! + hit_or_miss_closing(const abstract::image<I>& input, + const abstract::regular_window<oln_type_of(I, grid), W1> win1, + const abstract::regular_window<oln_type_of(I, grid), W2> win2) + { + return utils::invert(hit_or_miss_opening(utils::invert(input), + win1, win2)); + } + + template<class I, class W1, class W2> + utils::image_inverted<dilation_ret<hit_or_miss_ret<utils::image_inverted<I>, + W2, W1>, W2> > // !!! + hit_or_miss_closing_bg(const abstract::image<I>& input, + const abstract::regular_window<oln_type_of(I, grid), W1> win1, + const abstract::regular_window<oln_type_of(I, grid), W2> win2) + { + return hit_or_miss_closing(input, win2, win1); + } + + + + } // end of namespace morpho + +} // end of namespace oln + +#endif // ! OLENA_MORPHO_HIT_OR_MISS_HH Index: oln/arith/ops.hh --- oln/arith/ops.hh (revision 164) +++ oln/arith/ops.hh (working copy) @@ -131,18 +131,18 @@ -template <typename I, typename F> -void operator + (const oln::abstract::image<I>&, - const oln::pw::abstract::function<F>&) -{ - struct OLENA_ERROR__args_are_not_compatible(); -} -template <typename F, typename I> -void operator + (const oln::pw::abstract::function<F>&, - const oln::abstract::image<I>&) -{ - struct OLENA_ERROR__args_are_not_compatible(); -} +// template <typename I, typename F> +// void operator + (const oln::abstract::image<I>&, +// const oln::pw::abstract::function<F>&) +// { +// struct OLENA_ERROR__args_are_not_compatible(); +// } +// template <typename F, typename I> +// void operator + (const oln::pw::abstract::function<F>&, +// const oln::abstract::image<I>&) +// { +// struct OLENA_ERROR__args_are_not_compatible(); +// } // FIXME: to be continued... Index: oln/arith/min.hh --- oln/arith/min.hh (revision 164) +++ oln/arith/min.hh (working copy) @@ -38,38 +38,45 @@ namespace arith { // fwd decl namespace impl { - template <typename I> struct min_type; + template <typename I1, typename I2> struct min_type; } } // super_type - template <typename I> - struct set_super_type< arith::impl::min_type<I> > + template <typename I1, typename I2> + struct set_super_type< arith::impl::min_type<I1, I2> > { - typedef abstract::image_binary_operator<I, I, I, arith::impl::min_type<I> > ret; + typedef oln_type_of(I1, concrete) output_type; + typedef arith::impl::min_type<I1, I2> self_type; + typedef abstract::image_binary_operator<output_type, I1, I2, self_type> ret; }; namespace arith { namespace impl { - template <class I> - struct min_type : public abstract::image_binary_operator<I, I, I, min_type<I> > + template <typename I1, typename I2> + struct min_type : + // FIXME: oln_super_of_ + public oln::internal::get_super_type< min_type<I1,I2> >::ret { - typedef abstract::image_binary_operator<I, I, I, min_type<I> > super_type; + typedef typename oln::internal::get_super_type< min_type<I1,I2> >::ret + super_type; + typedef oln_type_of(I1, concrete) output_type; - min_type(const abstract::image<I>& input1, - const abstract::image<I>& input2) : + min_type(const abstract::image<I1>& input1, + const abstract::image<I2>& input2) : super_type(input1.exact(), input2.exact()) {} void impl_run() { precondition(this->input1.size() == this->input2.size()); - I output(this->input1.size()); - oln_type_of(I, fwd_piter) p(this->input1.size()); + output_type output(this->input1.size()); + oln_type_of(I1, fwd_piter) p(this->input1.size()); + for_all_p (p) output[p] = ntg::min(this->input1[p].value(), this->input2[p].value()); @@ -80,11 +87,12 @@ } - template <typename I> - impl::min_type<I> min(const abstract::image<I>& input1, - const abstract::image<I>& input2) + template <typename I1, typename I2> + impl::min_type<I1, I2> min(const abstract::image<I1>& input1, + const abstract::image<I2>& input2) { - impl::min_type<I> tmp(input1, input2); + mlc::eq<oln_type_of(I1, grid), oln_type_of(I2, grid)>::ensure(); + impl::min_type<I1, I2> tmp(input1, input2); tmp.run(); return tmp; } Index: oln/arith/max.hh --- oln/arith/max.hh (revision 164) +++ oln/arith/max.hh (working copy) @@ -38,38 +38,45 @@ namespace arith { // fwd decl namespace impl { - template <typename I> struct max_type; + template <typename I1, typename I2> struct max_type; } } // super_type - template <typename I> - struct set_super_type< arith::impl::max_type<I> > + template <typename I1, typename I2> + struct set_super_type< arith::impl::max_type<I1, I2> > { - typedef abstract::image_binary_operator<I, I, I, arith::impl::max_type<I> > ret; + typedef oln_type_of(I1, concrete) output_type; + typedef arith::impl::max_type<I1, I2> self_type; + typedef abstract::image_binary_operator<output_type, I1, I2, self_type> ret; }; namespace arith { namespace impl { - template <class I> - struct max_type : public abstract::image_binary_operator<I, I, I, max_type<I> > + template <typename I1, typename I2> + struct max_type : + // FIXME: oln_super_of_ + public oln::internal::get_super_type< max_type<I1,I2> >::ret { - typedef abstract::image_binary_operator<I, I, I, max_type<I> > super_type; + typedef typename oln::internal::get_super_type< max_type<I1,I2> >::ret + super_type; + typedef oln_type_of(I1, concrete) output_type; - max_type(const abstract::image<I>& input1, - const abstract::image<I>& input2) : + max_type(const abstract::image<I1>& input1, + const abstract::image<I2>& input2) : super_type(input1.exact(), input2.exact()) {} void impl_run() { precondition(this->input1.size() == this->input2.size()); - I output(this->input1.size()); - oln_type_of(I, fwd_piter) p(this->input1.size()); + output_type output(this->input1.size()); + oln_type_of(I1, fwd_piter) p(this->input1.size()); + for_all_p (p) output[p] = ntg::max(this->input1[p].value(), this->input2[p].value()); @@ -80,11 +87,12 @@ } - template <typename I> - impl::max_type<I> max(const abstract::image<I>& input1, - const abstract::image<I>& input2) + template <typename I1, typename I2> + impl::max_type<I1, I2> max(const abstract::image<I1>& input1, + const abstract::image<I2>& input2) { - impl::max_type<I> tmp(input1, input2); + mlc::eq<oln_type_of(I1, grid), oln_type_of(I2, grid)>::ensure(); + impl::max_type<I1, I2> tmp(input1, input2); tmp.run(); return tmp; }