
Index: olena/ChangeLog from Giovanni Palma <giovanni@lrde.epita.fr> * tests/morpho/tests/attribute: Fix function call problems. * tests/morpho/tests/attr_op_cl: Add attribute opening/closing tests. * oln/morpho/attribute_closing_opening_map.hh: Add slow namespace. Correct type problems. * oln/morpho/attribute_closing_opening_map.hxx: Likewise. * oln/morpho/attributes.hh: Fix bugs. * oln/morpho/attribute_union_find.hh: Add fast namespace. * oln/morpho/attribute_closing_opening.hh: Likewise. Index: olena/oln/morpho/attribute_closing_opening.hh --- olena/oln/morpho/attribute_closing_opening.hh Tue, 10 Feb 2004 17:32:17 +0100 palma_g (oln/q/49_attribute_ 1.13 640) +++ olena/oln/morpho/attribute_closing_opening.hh Mon, 16 Feb 2004 08:38:59 +0100 palma_g (oln/q/49_attribute_ 1.13 640) @@ -32,8 +32,8 @@ namespace oln { namespace morpho { + namespace fast { namespace tarjan { - namespace internal { // attribute closing @@ -43,7 +43,6 @@ const abstract::neighborhood<N>& Ng, const attr_lambda_type(A) &lambda) { - typedef N toto; typedef tarjan::tarjan_set<oln_concrete_type(I), A > tarjan_set_type; tarjan_set_type attr_closing(input.exact(), attr_env_type(A)()); return attr_closing.template get_comptute<true>(lambda, Ng); @@ -62,7 +61,7 @@ } } // !internal - + } // !tarjan // macro for some attribute opening/closing declarations # define xxx_opening_decl(T) \ template<class I, class N> \ @@ -71,7 +70,7 @@ const abstract::neighborhood<N>& Ng, \ const attr_lambda_type(T##_type<unsigned>) &lambda) \ { \ - return internal::attr_opening_<I, N, T##_type<unsigned> >(input, Ng, lambda); \ + return tarjan::internal::attr_opening_<I, N, T##_type<unsigned> >(input, Ng, lambda); \ } # define xxx_closing_decl(T) \ @@ -81,7 +80,7 @@ const abstract::neighborhood<N>& Ng, \ const attr_lambda_type(T##_type<unsigned>) &lambda) \ { \ - return internal::attr_closing_<I, N, T##_type<unsigned> >(input, Ng, lambda); \ + return tarjan::internal::attr_closing_<I, N, T##_type<unsigned> >(input, Ng, lambda); \ } @@ -93,7 +92,7 @@ const abstract::neighborhood<N>& Ng, \ const attr_lambda_type(T##_type<I>) &lambda) \ { \ - return internal::attr_opening_<I, N, T##_type<I> >(input, Ng, lambda); \ + return tarjan::internal::attr_opening_<I, N, T##_type<I> >(input, Ng, lambda); \ } # define xxx_closing_im_decl(T) \ @@ -103,7 +102,7 @@ const abstract::neighborhood<N>& Ng, \ const attr_lambda_type(T##_type<I>) &lambda) \ { \ - return internal::attr_closing_<I, N, T##_type<I> >(input, Ng, lambda); \ + return tarjan::internal::attr_closing_<I, N, T##_type<I> >(input, Ng, lambda); \ } /*=processing area_closing @@ -124,7 +123,7 @@ * exi: lena256.pgm * exo: out.pgm =*/ - xxx_closing_decl(area) + xxx_closing_decl(area); /*=processing area_opening * ns: morpho @@ -144,27 +143,27 @@ * exi: lena256.pgm * exo: out.pgm =*/ - xxx_opening_decl(area) - - xxx_opening_decl(volume) - xxx_closing_decl(volume) - xxx_opening_decl(height) - xxx_closing_decl(height) - xxx_opening_decl(maxvalue) - xxx_closing_decl(maxvalue) - xxx_opening_decl(minvalue) - xxx_closing_decl(minvalue) - xxx_opening_im_decl(disk) - xxx_closing_im_decl(disk) - xxx_opening_im_decl(dist) - xxx_closing_im_decl(dist) - xxx_closing_im_decl(square) - xxx_opening_im_decl(square) - xxx_closing_im_decl(rectangle) - xxx_opening_im_decl(rectangle) + xxx_opening_decl(area); - } - } -} + xxx_opening_decl(volume); + xxx_closing_decl(volume); + xxx_opening_decl(height); + xxx_closing_decl(height); + xxx_opening_decl(maxvalue); + xxx_closing_decl(maxvalue); + xxx_opening_decl(minvalue); + xxx_closing_decl(minvalue); + xxx_opening_im_decl(disk); + xxx_closing_im_decl(disk); + xxx_opening_im_decl(dist); + xxx_closing_im_decl(dist); + xxx_closing_im_decl(square); + xxx_opening_im_decl(square); + xxx_closing_im_decl(rectangle); + xxx_opening_im_decl(rectangle); + + } // !fast + } // !morpho +} // !oln #endif Index: olena/oln/morpho/attribute_union_find.hh --- olena/oln/morpho/attribute_union_find.hh Tue, 10 Feb 2004 17:32:17 +0100 palma_g (oln/q/50_attribute_ 1.11 640) +++ olena/oln/morpho/attribute_union_find.hh Thu, 12 Feb 2004 14:14:57 +0100 palma_g (oln/q/50_attribute_ 1.11 640) @@ -38,6 +38,7 @@ namespace oln { namespace morpho { + namespace fast { namespace tarjan { template< class T> @@ -231,7 +232,8 @@ const lambda_type *lambda_; const env_type env_; }; - } - } -} + } // !tarjan + } // !fast + } // !morph +} // !oln #endif Index: olena/oln/morpho/attributes.hh --- olena/oln/morpho/attributes.hh Tue, 10 Feb 2004 15:35:04 +0100 palma_g (oln/j/45_attributes 1.3 644) +++ olena/oln/morpho/attributes.hh Mon, 16 Feb 2004 18:57:01 +0100 palma_g (oln/j/45_attributes 1.3 644) @@ -31,9 +31,9 @@ # include <vector> // attribute dedicated macros -# define attr_lambda_type(T) typename attr_traits<T>::lambda_type -# define attr_env_type(T) typename attr_traits<T>::env_type -# define attr_value_type(T) typename attr_traits<T>::value_type +# define attr_lambda_type(T) typename oln::morpho::attr_traits<T>::lambda_type +# define attr_env_type(T) typename oln::morpho::attr_traits<T>::env_type +# define attr_value_type(T) typename oln::morpho::attr_traits<T>::value_type # define attr_type_decl(slef_type) \ typedef mlc_exact_vt_type(self_type, Exact) exact_type; \ @@ -43,7 +43,6 @@ namespace oln { namespace morpho { - namespace tarjan { namespace tools { // should be moved elsewhere template <class T> @@ -51,8 +50,8 @@ { return v1 > v2 ? v1 - v2 : v2 - v1; } + } // !tools - } // environment herarchy // not used yet template <class Exact> @@ -265,7 +264,10 @@ { }; - height_type(const lambda_type &lambda): value_(lambda) + height_type(const lambda_type &lambda): + value_(lambda), + min_(ntg_zero_val(value_type)), + max_(lambda) { }; @@ -273,25 +275,38 @@ height_type(const abstract::image<I> &input, const oln_point_type(I) &p, const env_type&): - reflevel_(input[p]), - value_(ntg_zero_val(value_type)) + value_(ntg_zero_val(value_type)), + min_(input[p]), + max_(input[p]) { }; - const value_type &getReflevel() const + + const value_type &getMin() const { - mlc_dispatch(getReflevel)(); + mlc_dispatch(getMin)(); }; + const value_type &getMax() const + { + mlc_dispatch(getMax)(); + }; // impl part - const value_type &getReflevel_impl() const + const value_type &getMin_impl() const { - return reflevel_; + return min_; + }; + + const value_type &getMax_impl() const + { + return max_; }; void pe_impl(const height_type &rhs) { - value_ = tools::diffabs(reflevel_, rhs.getReflevel()); + min_ = ntg::min(min_, rhs.getMin()); + max_ = ntg::max(max_, rhs.getMax()); + value_ = max_ - min_; }; bool less_impl(const lambda_type &lambda) const @@ -305,8 +320,9 @@ }; protected: - value_type reflevel_; value_type value_; + value_type min_; + value_type max_; }; @@ -413,7 +429,7 @@ bool less_impl(const lambda_type &lambda) const { - return value_ < lambda; + return value_ > lambda; }; bool ne_impl(const lambda_type &lambda) const @@ -452,17 +468,27 @@ }; disk_type(const im_type&, const point_type &p, const env_type &) : - value_(1), pts_() + value_(ntg_zero_val(value_type)), pts_() + { pts_.push_back(p); }; + const value_type &getValue() const + { + mlc_dispatch(getValue)(); + }; + const pts_type &getPts() const { mlc_dispatch(getPts)(); }; // impl + const value_type &getValue_impl() const + { + return value_; + }; const pts_type &getPts_impl() const { @@ -471,7 +497,10 @@ void pe_impl(const disk_type &rhs) { - std::copy(rhs.getPts().begin(), rhs.getPts().end(), std::back_inserter(pts_)); + value_type last = value_; + std::copy(rhs.getPts().begin(), + rhs.getPts().end(), + std::back_inserter(pts_)); value_ = ntg_zero_val(value_type); for (cst_iter_type p1 = pts_.begin(); p1 != pts_.end(); ++p1) for (cst_iter_type p2 = pts_.begin(); p2 != pts_.end(); ++p2) @@ -484,6 +513,8 @@ value_ = d; } value_ /= 2; + value_ = ntg::max(value_, last); + value_ = ntg::max(value_, rhs.getValue()); }; bool less_impl(const lambda_type &lambda) const @@ -530,6 +561,11 @@ { }; + const value_type &getValue() const + { + mlc_dispatch(getValue)(); + }; + dist_type(const lambda_type lambda): value_(lambda) { }; @@ -545,14 +581,22 @@ return center_; }; + const value_type &getValue_impl() const + { + return value_; + }; + void pe_impl(const dist_type &rhs) { + value_type last = value_; dpoint_type p = center_ - rhs.getCenter(); value_ = ntg_zero_val(value_type); for (int i = 0; i < point_traits<point_type>::dim; ++i) value_ += p.nth(i) * p.nth(i); value_ = sqrt(value_); + value_ = ntg::max(value_, last); + value_ = ntg::max(value_, rhs.getValue()); }; bool less_impl(const lambda_type &lambda) const @@ -841,9 +885,8 @@ typedef ntg::vec<I::dim, value_type, mlc::final> lambda_type; typedef NullEnv env_type; }; - } - } -} + } // !morpho +} //!oln /*-----------* | diamond | Index: olena/oln/morpho/attribute_closing_opening_map.hxx --- olena/oln/morpho/attribute_closing_opening_map.hxx Tue, 10 Feb 2004 19:49:03 +0100 van-vl_n (oln/j/48_attribute_ 1.1 644) +++ olena/oln/morpho/attribute_closing_opening_map.hxx Thu, 12 Feb 2004 14:05:43 +0100 palma_g (oln/j/48_attribute_ 1.1 644) @@ -30,6 +30,8 @@ { namespace morpho { + namespace slow + { template <class I, class D, class Env> template <class N> f_tarjan_map<I, D, Env>::f_tarjan_map(bool is_closing, @@ -189,6 +191,7 @@ } } } + } // end of namespace slow } // end of namespace morpho } // end of namespace oln Index: olena/oln/morpho/attribute_closing_opening_map.hh --- olena/oln/morpho/attribute_closing_opening_map.hh Tue, 10 Feb 2004 19:49:03 +0100 van-vl_n (oln/j/49_attribute_ 1.1 600) +++ olena/oln/morpho/attribute_closing_opening_map.hh Mon, 16 Feb 2004 08:39:58 +0100 palma_g (oln/j/49_attribute_ 1.1 600) @@ -33,6 +33,7 @@ # include <ntg/int.hh> # include <oln/utils/histogram.hh> # include <oln/utils/special_points.hh> +# include <oln/morpho/attributes.hh> # include <iterator> # include <vector> @@ -45,14 +46,15 @@ { namespace morpho { - + namespace slow + { /*! Attribute closing using map. Smaller memory usage, but * slower computation than the attribute_closing_opening * * See "Fast morphological attribute operations using Tarjan's union-find * algorithm" by Michael H. F. Wilkinson and Jos B. T. M. Roerdink */ - template <class I, class D, class Env = morpho::tarjan::NullEnv> + template <class I, class D, class Env = morpho::NullEnv> struct f_tarjan_map { public: @@ -63,7 +65,7 @@ typedef oln_value_type(input_type) value_type; typedef typename mute<input_type, point_type>::ret parent_type; typedef typename mute<input_type, bool>::ret is_proc_type; - typedef typename D::lambda_type lambda_type; + typedef attr_lambda_type(D) lambda_type; // e.g., // when I is image2d<int_u8> and D is area_type, we've got: @@ -82,8 +84,7 @@ const lambda_type& lambda, const Env & env = Env()); - template<typename DestValue> - typename mute<I, DestValue>::ret + oln_concrete_type(I) res() { return output; @@ -128,21 +129,92 @@ * See "Fast morphological attribute operations using Tarjan's union-find * algorithm" by Michael H. F. Wilkinson and Jos B. T. M. Roerdink */ - template <typename DestValue, class I, class D, class Env, class N> - typename mute<I, DestValue>::ret + template <class D, class I, class N> + oln_concrete_type(I) tarjan_map(bool is_closing, const abstract::image<I>& input, const abstract::neighborhood<N>& ng, - const typename D::lambda_type& lambda, - const Env & env = Env()) + const attr_lambda_type(D)& lambda, + const attr_env_type(D)& env/* = Env()*/) { - oln::morpho::f_tarjan_map<I, D, Env > t(is_closing, + oln::morpho::slow::f_tarjan_map<I, D, attr_env_type(D) > t(is_closing, input, ng, lambda, env); - return t. template res<DestValue>(); + return t.res(); + } + + /*! Some macro to declare friendly function for different attributes + * opening/closing + */ +# define xxx_opening_map_decl(T) \ +template <class I, class N> \ +oln_concrete_type(I) \ +T##_opening(const abstract::image<I>& input, \ + const abstract::neighborhood<N>& ng, \ + const attr_lambda_type(T##_type<>)& lambda) \ + { \ + return tarjan_map<T##_type<>, I, N>(false, input, ng, lambda, \ + attr_env_type(T##_type<>)()); \ + } + + // same but attribute take care of the image type +# define xxx_opening_im_map_decl(T) \ +template <class I, class N> \ +oln_concrete_type(I) \ +T##_opening(const abstract::image<I>& input, \ + const abstract::neighborhood<N>& ng, \ + const attr_lambda_type(T##_type<I>)& lambda) \ + { \ + return tarjan_map<T##_type<I>, I, N>(false, input, ng, lambda, \ + attr_env_type(T##_type<I>)()); \ } + + //return input; + // return tarjan_map<T##_type, I, N>(false, input, ng, lambda, attr_env_type(T##_type<>)()); +# define xxx_closing_map_decl(T) \ +template <class I, class N> \ +oln_concrete_type(I) \ +T##_closing(const abstract::image<I>& input, \ + const abstract::neighborhood<N>& ng, \ + const attr_lambda_type(T##_type<>)& lambda) \ + { \ + return tarjan_map<T##_type<>, I, N>(true, input, ng, lambda, attr_env_type(T##_type<>)()); \ + } + + // same but attribute take care of the image type +# define xxx_closing_im_map_decl(T) \ +template <class I, class N> \ +oln_concrete_type(I) \ +T##_closing(const abstract::image<I>& input, \ + const abstract::neighborhood<N>& ng, \ + const attr_lambda_type(T##_type<I>)& lambda) \ + { \ + return tarjan_map<T##_type<I>, I, N>(true, input, ng, lambda, attr_env_type(T##_type<I>)()); \ + } + + xxx_opening_map_decl(area); + xxx_closing_map_decl(area); + xxx_opening_map_decl(volume); + xxx_closing_map_decl(volume); + xxx_opening_map_decl(height); + xxx_closing_map_decl(height); + xxx_opening_map_decl(maxvalue); + xxx_closing_map_decl(maxvalue); + xxx_opening_map_decl(minvalue); + xxx_closing_map_decl(minvalue); + xxx_opening_im_map_decl(disk); + xxx_closing_im_map_decl(disk); + xxx_opening_im_map_decl(dist); + xxx_closing_im_map_decl(dist); + xxx_closing_im_map_decl(square); + xxx_opening_im_map_decl(square); + xxx_closing_im_map_decl(rectangle); + xxx_opening_im_map_decl(rectangle); + + + } // end of namespace slow } // end of namespace morpho } // end of namespace oln Index: olena/tests/morpho/tests/attribute --- olena/tests/morpho/tests/attribute Tue, 10 Feb 2004 19:49:03 +0100 van-vl_n (oln/j/51_attribute 1.1 644) +++ olena/tests/morpho/tests/attribute Mon, 16 Feb 2004 08:40:49 +0100 palma_g (oln/j/51_attribute 1.1 644) @@ -28,10 +28,10 @@ bool fail(false); typedef image2d<int_u8> img_type; - typedef oln::morpho::tarjan::area_type<unsigned> area_type; + typedef oln::morpho::area_type<unsigned> area_type; const area_type::lambda_type area = 100; const neighborhood2d nb = neighb_c8(); - const oln::morpho::tarjan::NullEnv env; + // const oln::morpho::NullEnv env; img_type lena = load(rdata("lena.pgm")); img_type lena_sure_closing = oln::morpho::sure_minima_killer(lena, area, nb); @@ -41,9 +41,10 @@ img_type lena_tst_closing; std::cerr << "testing tarjan_map..." << std::endl; - lena_tst_closing = morpho::tarjan_map<ntg::int_u8,img_type,area_type>(true, lena, nb, area, env); - lena_tst_opening= morpho::tarjan_map<ntg::int_u8,img_type,area_type>(false, lena, nb, area, env); - +// lena_tst_closing = morpho::slow::tarjan_map<area_type,ntg::int_u8,img_type>(true, lena, nb, area, env); +// lena_tst_opening= morpho::slow::tarjan_map<area_type,ntg::int_u8,img_type>(false, lena, nb, area, env); + lena_tst_closing = morpho::slow::area_closing(lena, nb, area); + lena_tst_opening = morpho::slow::area_opening(lena, nb, area); fail = fail || !level::is_equal(lena_sure_closing, lena_tst_closing)|| @@ -59,8 +60,8 @@ std::cerr << "fail:" << fail << std::endl; std::cerr << "testing area_closin and area_opeing..." << std::endl; - lena_tst_closing = morpho::tarjan::area_closing(lena, nb, area); - lena_tst_opening = morpho::tarjan::area_opening(lena, nb, area); + lena_tst_closing = morpho::fast::area_closing(lena, nb, area); + lena_tst_opening = morpho::fast::area_opening(lena, nb, area); fail = fail || !level::is_equal(lena_sure_closing, lena_tst_closing)|| !level::is_equal(lena_sure_opening, lena_tst_opening); @@ -70,12 +71,13 @@ return fail; } - bool check_attribute() { + bool fail = false; + //FIXME attributes should be checked - return false; + return fail; } Index: olena/tests/morpho/tests/attr_op_cl --- olena/tests/morpho/tests/attr_op_cl Mon, 16 Feb 2004 19:05:52 +0100 palma_g () +++ olena/tests/morpho/tests/attr_op_cl Mon, 16 Feb 2004 18:48:30 +0100 palma_g (oln/k/0_attr_op_cl 644) @@ -0,0 +1,77 @@ +// -*- c++ -*- + +#include <oln/basics2d.hh> +#include <oln/morpho/attribute_closing_opening.hh> +#include <oln/morpho/attribute_closing_opening_map.hh> +#include <oln/level/compare.hh> +#include <ntg/all.hh> + +#include "check.hh" +#include "data.hh" + +using namespace oln; +using namespace ntg; + +#define OK_OR_FAIL \ + std::cout << "OK" << std::endl; \ + else \ + { \ + std::cout << "FAIL" << std::endl; \ + fail = true; \ + } + +# define test_op_cl(T, A, im, lambda) \ +{ \ + bool last_fail = fail; \ + fail = false; \ + { \ + image2d<T> im2 = oln::morpho::slow::A##_opening(im, neighb_c4(), lambda); \ + image2d<T> im1 = oln::morpho::fast::A##_opening(im, neighb_c4(), lambda); \ + image2d<T>::iter_type it(lena); \ + std::cout << #A << " opening: "; \ + for_all(it) \ + { \ + if (im1[it] != im2[it]) \ + fail = true; \ + } \ + if (!fail) \ + OK_OR_FAIL \ + } \ + { \ + image2d<T> im2 = oln::morpho::slow::A##_closing(im, neighb_c4(), lambda); \ + image2d<T> im1 = oln::morpho::fast::A##_closing(im, neighb_c4(), lambda); \ + image2d<T>::iter_type it(lena); \ + std::cout << #A <<" closing: "; \ + for_all(it) \ + { \ + if (im1[it] != im2[it]) \ + fail = true; \ + } \ + if (!fail) \ + OK_OR_FAIL \ + } \ + fail = last_fail || fail; \ +} + + +bool +check() +{ + bool fail = false; + + image2d<int_u8> lena(rdata("lena256.pgm")); + std::cout << std::endl; + test_op_cl(int_u8, area, lena, 200) + test_op_cl(int_u8, volume, lena, 200) + test_op_cl(int_u8, height, lena, 4) + test_op_cl(int_u8, maxvalue, lena, 100) + test_op_cl(int_u8, minvalue, lena, 100) + test_op_cl(int_u8, dist, lena, 100) + test_op_cl(int_u8, disk, lena, 100) + test_op_cl(int_u8, square, lena, 50) + + ntg::vec<2, unsigned, mlc::final> lambda; + test_op_cl(int_u8, rectangle, lena, lambda) + + return fail; +} -- Giovanni Palma EPITA - promo 2005 - membre d'EpX - LRDE Mob. : +33 (0)6 60 97 31 74