Index: ChangeLog
from Damien Thivolle <damien(a)lrde.epita.fr>
* tests/morpho/tests/reconstruction: New.
* oln/convert/nbh_to_se.hh: Adapt to new neighborhoods.
* oln/core/abstract/image_neighbness.hh (impl_get_nbh): Add missing
method.
* oln/morpho/reconstruction.hh: New hierarchy.
* oln/morpho/splitse.hh: Adapt to new neighborhoods.
* oln/morpho/reconstruction_by_erosion.inc: New. Implementation for
reconstruction by erosion.
* oln/morpho/reconstruction_canvas.inc: New. Canvas for reconstruction:
sequential & hybrid.
* oln/morpho/reconstruction_by_dilation.inc: New. Implementation for
reconstruction by dilation.
* img/marker.pbm: New.
* img/mask.pbm: New.
img/marker.pbm | 0
img/mask.pbm | 0
oln/convert/nbh_to_se.hh | 8
oln/core/abstract/image_neighbness.hh | 6
oln/morpho/reconstruction.hh | 514 +++++++-----------------------
oln/morpho/reconstruction_by_dilation.inc | 142 ++++++++
oln/morpho/reconstruction_by_erosion.inc | 141 ++++++++
oln/morpho/reconstruction_canvas.inc | 238 +++++++++++++
oln/morpho/splitse.hh | 127 +++----
tests/morpho/tests/reconstruction | 66 +++
10 files changed, 780 insertions, 462 deletions
Index: tests/morpho/tests/reconstruction
--- tests/morpho/tests/reconstruction (revision 0)
+++ tests/morpho/tests/reconstruction (revision 0)
@@ -0,0 +1,66 @@
+// -*- C++ -*-
+
+#include "data.hh"
+#include <oln/basics2d.hh>
+#include <ntg/all.hh>
+
+#include <oln/core/gen/image_with_nbh.hh>
+
+#include <oln/morpho/reconstruction.hh>
+
+#include <oln/io/read_image.hh>
+#include <oln/io/write_image.hh>
+
+#include <oln/level/compare.hh>
+#include <oln/utils/md5.hh>
+#include <oln/utils/invert.hh>
+
+bool check()
+{
+ using namespace oln;
+ image2d<ntg::bin> marker;
+ image2d<ntg::bin> mask;
+ image2d<ntg::bin> res_dil_hyb;
+ image2d<ntg::bin> res_dil_seq;
+ image2d<ntg::bin> res_ero_hyb;
+ image2d<ntg::bin> res_ero_seq;
+
+ utils::key::value_type data_key[16] =
+ {
+ 0x36, 0xa6, 0x2e, 0x7e, 0xbf, 0x21, 0xf6, 0x2b,
+ 0xbf, 0x57, 0x58, 0xdc, 0x9d, 0x72, 0x41, 0x8f
+ };
+ utils::key key(data_key);
+
+ marker = io::read(rdata("marker.pbm"));
+ mask = io::read(rdata("mask.pbm"));
+
+ res_dil_hyb = morpho::reconstruction(tag::by_dilation(),
+ join(marker, neighb_c4()),
+ mask,
+ tag::hybrid());
+ res_dil_seq = morpho::reconstruction(tag::by_dilation(),
+ join(marker, neighb_c4()),
+ mask,
+ tag::sequential());
+
+ res_ero_hyb = morpho::reconstruction(tag::by_erosion(),
+ utils::invert(join(marker, neighb_c4())),
+ utils::invert(mask),
+ tag::hybrid());
+ res_ero_seq = morpho::reconstruction(tag::by_erosion(),
+ utils::invert(join(marker, neighb_c4())),
+ utils::invert(mask),
+ tag::sequential());
+
+ if (utils::md5(res_dil_hyb) != key)
+ return true;
+ if (!level::is_equal(res_dil_hyb, res_dil_seq))
+ return true;
+ if (!level::is_equal(res_ero_hyb, res_ero_seq))
+ return true;
+ if (!level::is_equal(res_dil_hyb, utils::invert(res_ero_seq)))
+ return true;
+
+ return false;
+}
Index: oln/convert/nbh_to_se.hh
--- oln/convert/nbh_to_se.hh (revision 162)
+++ oln/convert/nbh_to_se.hh (working copy)
@@ -40,12 +40,12 @@
*/
template<class N>
oln_nbh_type_of(N, window)
- nbh_to_se(const oln::abstract::neighborhood<N>& nbh)
+ nbh_to_se(const N& nbh) // FIXME: UGLY
oln::abstract::neighborhood<N>& nbh)
{
oln_nbh_type_of(N, window) output;
for (unsigned i = 0; i < nbh.card(); i++)
- output.add(nbh[i]);
+ output.add(nbh.dp(i));
return output;
}
@@ -61,12 +61,12 @@
*/
template<class N>
oln_nbh_type_of(N, window)
- nbh_to_cse(const oln::abstract::neighborhood<N>& nbh)
+ nbh_to_cse(const N& nbh) // FIXME: UGLY oln::abstract::neighborhood<N>&
nbh)
{
oln_nbh_type_of(N, window) output;
for (unsigned i = 0; i < nbh.card(); i++)
- output.add(nbh[i]);
+ output.add(nbh.dp(i));
oln_nbh_type_of(N, dpoint) zero;
dpoint_zero(zero);
Index: oln/core/abstract/image_neighbness.hh
--- oln/core/abstract/image_neighbness.hh (revision 162)
+++ oln/core/abstract/image_neighbness.hh (working copy)
@@ -53,6 +53,12 @@
return this->exact().impl_nbh_get();
}
+ //FIXME: is it the right way ?
+ const neighb_type& impl_nbh_get() const
+ {
+ return this->exact().delegate().nbh_get();
+ }
+
protected:
image_with_nbh() {}
Index: oln/morpho/reconstruction.hh
--- oln/morpho/reconstruction.hh (revision 162)
+++ oln/morpho/reconstruction.hh (working copy)
@@ -49,453 +49,181 @@
namespace oln {
- namespace morpho {
- // fwd decl
- template <typename I, typename E> struct reconstruction_ret;
+ namespace tag {
- }
+ template <typename Op> struct oper {};
- // category
- template <typename I, typename E>
- struct set_category< morpho::reconstruction_ret<I,E> > { typedef
category::image ret; };
+ struct by_dilation : public oper< by_dilation > {};
+ struct by_erosion : public oper< by_erosion > {};
- // super_type
- template <typename I, typename E>
- struct set_super_type< morpho::reconstruction_ret<I,E> >
- {
- typedef abstract::image_binary_operator<I, I, I, morpho::reconstruction_ret<I,
E> > ret;
- // FIXME: see below
- };
+ template <typename A> struct algo {};
- namespace morpho {
+ struct sequential : public algo< sequential > {};
+ struct hybrid : public algo< hybrid > {};
- template <typename I, typename N>
- struct reconstruction_ret : public abstract::image_binary_operator<I, I, I,
reconstruction_ret<I, N> >
- // FIXME: abstract::image_binary_operator<oln_type_of(I, concrete), ...
- {
- typedef abstract::image_binary_operator<I, I, I, reconstruction_ret<I, N>
> super_type;
+ } // end of namespace oln::morpho::tag
- const N nbh;
- reconstruction_ret(const abstract::image<I>& input1,
- const abstract::image<I>& input2,
- const abstract::neighborhood<N>& nbh) :
- super_type(input1.exact(), input2.exact()),
- nbh(nbh.exact())
- {}
- };
+ namespace morpho {
+ template <typename I1, typename I2> struct reconstruction_ret;
+ } // end of namespace oln::morpho
- namespace sequential {
+ // super_type
- namespace impl {
+ template <typename I1, typename I2>
+ struct set_super_type< morpho::reconstruction_ret<I1, I2> >
+ {
+ typedef oln_type_of(I1, concrete) output_type;
- template <typename I, typename N, typename E>
- struct reconstruction_sequential_ret : public reconstruction_ret<I, N>
- {
- typedef reconstruction_ret<I, N> super_type;
+ typedef morpho::reconstruction_ret<I1,I2> self_type;
+ typedef abstract::image_binary_operator<output_type, I1, I2, self_type > ret;
+ };
- void fwd_loop_body()
- {
- static_cast<E*>((void*)this)->fwd_loop_body_impl();
- }
+ namespace morpho {
- void bkd_loop_body()
- {
- static_cast<E*>((void*)this)->bkd_loop_body_impl();
- }
+ // Reconstruction as a 'classical' procedure returning an image (do not
+ // use it; prefer morpho::reconstruction).
- void preconditions()
- {
- precondition(this->input1.size() == this->input2.size());
- static_cast<E*>((void*)this)->preconditions_impl();
- }
+ namespace proc {
- void impl_run()
- {
- mlc::eq<oln_type_of(I, size), oln_type_of(N, size)>::ensure();
+ // FIXME: ...
- I output;
- output = utils::clone(this->input1);
- bool non_stability = true;
- while (non_stability)
- {
- work.unbox() = utils::clone(output);
- for_all_p (fwd_p)
- fwd_loop_body();
- for_all_p (bkd_p)
- bkd_loop_body();
+ } // end of namespace oln::morpho::proc
- non_stability = !(level::is_equal(work, output));
- output = work.unbox();
- }
- this->output = output;
- }
- protected:
- reconstruction_sequential_ret(const abstract::image<I>& input1, //marker
- const abstract::image<I>& input2, //mask
- const abstract::neighborhood<N>& nbh)
- : super_type(input1, input2, nbh),
- fwd_p(input1.size()),
- bkd_p(input1.size())
- {
- se_plus = get_plus_se_p(convert::nbh_to_cse(this->nbh));
- se_minus = get_minus_se_p(convert::nbh_to_cse(this->nbh));
- }
+ template <typename I1, typename I2>
+ struct reconstruction_ret :
+ // FIXME: oln_super_of_
+ public oln::internal::get_super_type< reconstruction_ret<I1,I2> >::ret
+ {
+ typedef reconstruction_ret<I1, I2> self_type;
+ typedef typename oln::internal::get_super_type<self_type>::ret super_type;
- oln_type_of(N, window) se_plus;
- oln_type_of(N, window) se_minus;
- oln_type_of(I, fwd_piter) fwd_p;
- oln_type_of(I, bkd_piter) bkd_p;
- box<I> work;
+ box<const I1> marker;
+ box<const I2> mask;
- };
+ reconstruction_ret(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask) :
+ super_type(marker, mask),
+ marker(marker),
+ mask(mask)
+ {
+ }
- template <typename I, typename N>
- struct reconstruction_dilation_ret :
- public reconstruction_sequential_ret<I, N, reconstruction_dilation_ret<I, N>
>
- {
- typedef reconstruction_sequential_ret<I, N, reconstruction_dilation_ret<I, N>
> super_type;
+ const oln_type_of(I1, neighb)& impl_nbh_get() const
+ {
+ return marker.nbh_get();
+ }
- reconstruction_dilation_ret(const abstract::image<I>& input1, //marker
- const abstract::image<I>& input2, //mask
- const abstract::neighborhood<N>& nbh)
+ };
- : super_type(input1, input2, nbh)
- {}
+ } // end of namespace morpho
- void fwd_loop_body_impl()
- {
- this->work[this->fwd_p] = ntg::min(morpho::max(this->work.unbox(),
- this->fwd_p,
- this->se_plus),
- this->input2[this->fwd_p].value());
- }
+} // end of namespace oln
- void bkd_loop_body_impl()
- {
- this->work[this->bkd_p] = ntg::min(morpho::max(this->work.unbox(),
- this->bkd_p,
- this->se_minus),
- this->input2[this->bkd_p].value());
- }
+# include <oln/morpho/reconstruction_canvas.inc>
- void preconditions_impl()
- {
- precondition(level::is_greater_or_equal(this->input2, this->input1));
- }
+namespace oln {
- };
+ namespace morpho {
+ namespace impl {
- template <typename I, typename N>
- struct reconstruction_erosion_ret :
- public reconstruction_sequential_ret<I, N, reconstruction_erosion_ret<I, N>
>
- {
- typedef reconstruction_sequential_ret<I, N, reconstruction_erosion_ret<I, N>
> super_type;
+ template<typename Op, typename A, typename I1, typename I2>
+ struct generic_reconstruction;
- reconstruction_erosion_ret(const abstract::image<I>& input1, //marker
- const abstract::image<I>& input2, //mask
- const abstract::neighborhood<N>& nbh)
+ } // end of namespace impl
- : super_type(input1, input2, nbh)
- {}
+ } // end of namespace morpho
- void fwd_loop_body_impl()
- {
- this->work[this->fwd_p] = ntg::max(morpho::min(this->work.unbox(),
- this->fwd_p,
- this->se_plus),
- this->input2[this->fwd_p].value());
- }
+} // end of namespace oln
- void bkd_loop_body_impl()
- {
- this->work[this->bkd_p] = ntg::max(morpho::min(this->work.unbox(),
- this->bkd_p,
- this->se_minus),
- this->input2[this->bkd_p].value());
- }
+# include <oln/morpho/reconstruction_by_dilation.inc>
+# include <oln/morpho/reconstruction_by_erosion.inc>
- void preconditions_impl()
- {
- precondition(level::is_greater_or_equal(this->input1, this->input2));
- }
+namespace oln {
- };
+ namespace morpho {
- }
+ namespace impl {
- template<class I, class N>
- reconstruction_ret<I, N>
- geodesic_reconstruction_dilation(const abstract::image<I> & marker,
- const abstract::image<I> & mask,
- const abstract::neighborhood<N>& nbh)
- {
- impl::reconstruction_dilation_ret<I, N> tmp(marker, mask, nbh);
- tmp.run();
- return tmp;
- }
+ // Generic implementation of reconstruction (routine).
- template<class I, class N>
- reconstruction_ret<I, N>
- geodesic_reconstruction_erosion(const abstract::image<I> & marker,
- const abstract::image<I> & mask,
- const abstract::neighborhood<N>& nbh)
+ template<typename Op, typename A, typename I1, typename I2>
+ reconstruction_ret<I1,I2>
+ reconstruction(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask)
{
- impl::reconstruction_erosion_ret<I, N> tmp(marker, mask, nbh);
+ generic_reconstruction<Op, A, I1, I2> tmp(marker, mask);
tmp.run();
return tmp;
}
- }// sequential
+ } // end of namespace impl
+ /// Generic reconstruction (facade).
- namespace hybrid {
+ template<typename Op, typename I1, typename I2, typename A>
+ reconstruction_ret<I1,I2>
+ reconstruction(const tag::oper<Op>& oper_,
+ const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask,
+ const tag::algo<A>& algo_)
+ {
+ return impl::reconstruction<Op,A>(marker.exact(), mask.exact());
+ }
- namespace impl {
+ // by dilation
- template <typename I, typename N, typename E>
- struct reconstruction_hybrid_ret : public reconstruction_ret<I, N>
- {
- typedef reconstruction_ret<I, N> super_type;
+ template<typename I1, typename I2, typename A>
+ reconstruction_ret<I1,I2>
+ reconstruction_by_dilation(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask,
+ const tag::algo<A>& algo_)
+ {
+ mlc::eq<oln_type_of(I1, grid), oln_type_of(I2, grid)>::ensure();
+ precondition(marker.size() == mask.size());
+ return reconstruction(tag::by_dilation(), marker, mask, algo_);
+ }
- bool exist_init()
- {
- // FIXME: to many changes => rewrite!
-// typedef oln_type_of(N, window) se_type;
-// oln_type_of(se_type, fwd_qiter) dp(se_minus);
-// for_all (dp)
-// {
-// q = (oln_type_of(se_type, dpoint))dp +
-// (oln_type_of(I, point))bkd_p;
-// if (static_cast<E*>((void*)this)->exist_init_impl())
-// return true;
-// }
- return false;
- }
+ template<typename I1, typename I2>
+ reconstruction_ret<I1,I2>
+ reconstruction_by_dilation(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask)
+ {
+ mlc::eq<oln_type_of(I1, grid), oln_type_of(I2, grid)>::ensure();
+ precondition(marker.size() == mask.size());
+ return reconstruction(tag::by_dilation(), marker, mask, tag::hybrid());
+ }
- void fwd_loop_body()
- {
- static_cast<E*>((void*)this)->fwd_loop_body_impl();
- }
+ // by erosion
- void bkd_loop_body()
- {
- static_cast<E*>((void*)this)->bkd_loop_body_impl();
- }
+ template<typename I1, typename I2, typename A>
+ reconstruction_ret<I1,I2>
+ reconstruction_by_erosion(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask,
+ const tag::algo<A>& algo_)
+ {
+ mlc::eq<oln_type_of(I1, grid), oln_type_of(I2, grid)>::ensure();
+ precondition(marker.size() == mask.size());
+ return reconstruction(tag::by_erosion(), marker, mask, algo_);
+ }
- void fifo_loop_body()
- {
- static_cast<E*>((void*)this)->fifo_loop_body_impl();
- }
+ template<typename I1, typename I2>
+ reconstruction_ret<I1,I2>
+ reconstruction_by_erosion(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask)
+ {
+ mlc::eq<oln_type_of(I1, grid), oln_type_of(I2, grid)>::ensure();
+ precondition(marker.size() == mask.size());
+ return reconstruction(tag::by_erosion(), marker, mask, tag::hybrid());
+ }
- void preconditions()
- {
- precondition(this->input1.size() == this->input2.size());
- static_cast<E*>((void*)this)->preconditions_impl();
- }
+ } // end of namespace oln::morpho
- void impl_run()
- {
- mlc::eq<oln_type_of(I, size), oln_type_of(N, size)>::ensure();
- preconditions();
+} // end of namespace oln
- this->output.unbox() = utils::clone(this->input1);
-
- for_all_p (fwd_p)
- fwd_loop_body();
-
- for_all_p (bkd_p)
- {
- bkd_loop_body();
- if (exist_init())
- fifo.push(bkd_p);
- }
- // Propagation Step
- while (!fifo.empty())
- {
- p = fifo.front();
- fifo.pop();
- // FIXME: AWFUL commented cause too many changes!
-// typedef oln_type_of(N, window) window_type;
-// window_type w = convert::nbh_to_se(this->nbh);
-// oln_wn_type_of(window_type, fwd_iter) q(w);
-
-// for_all_q_of_p (q)
-// {
-// if (this->output.hold(q))
-// fifo_loop_body();
-// }
- }
- }
-
- protected:
-
- reconstruction_hybrid_ret(const abstract::image<I>& input1, //marker
- const abstract::image<I>& input2, //mask
- const abstract::neighborhood<N>& nbh)
-
- : super_type(input1, input2, nbh),
- fwd_p(input1.size()),
- bkd_p(input1.size())
- {
- se_plus = get_plus_se_p(convert::nbh_to_cse(this->nbh));
- se_minus = get_minus_se_p(convert::nbh_to_cse(this->nbh));
- }
-
- oln_type_of(N, window) se_plus;
- oln_type_of(N, window) se_minus;
- oln_type_of(I, fwd_piter) fwd_p;
- oln_type_of(I, bkd_piter) bkd_p;
- oln_type_of(I, point) p;
- oln_type_of(I, point) q;
- std::queue<oln_type_of(I, point) > fifo;
-
-
- };
-
-
- template <typename I, typename N>
- struct reconstruction_dilation_ret :
- public reconstruction_hybrid_ret<I, N, reconstruction_dilation_ret<I, N>
>
- {
- typedef reconstruction_hybrid_ret<I, N, reconstruction_dilation_ret<I, N>
> super_type;
-
- reconstruction_dilation_ret(const abstract::image<I>& input1, //marker
- const abstract::image<I>& input2, //mask
- const abstract::neighborhood<N>& nbh)
-
- : super_type(input1, input2, nbh)
- {}
-
- void fwd_loop_body_impl()
- {
- this->output[this->fwd_p] = ntg::min(morpho::max(this->output.unbox(),
- this->fwd_p,
- this->se_plus),
- this->input2[this->fwd_p].value());
- }
-
- void bkd_loop_body_impl()
- {
- this->output[this->bkd_p] = ntg::min(morpho::max(this->output.unbox(),
- this->bkd_p,
- this->se_minus),
- this->input2[this->bkd_p].value());
- }
-
- void fifo_loop_body_impl()
- {
- if ((this->output[this->q] < this->output[this->p]) &&
- (this->input2[this->q] != this->output[this->q]))
- {
- this->output[this->q] = ntg::min(this->output[this->p].value(),
- this->input2[this->q].value());
- this->fifo.push(this->q);
- }
- }
-
- bool exist_init_impl()
- {
- return this->output.hold(this->q) &&
- (this->output[this->q] < this->output[this->bkd_p]) &&
- (this->output[this->q] < this->input2[this->q]);
- }
-
- void preconditions_impl()
- {
- precondition(level::is_greater_or_equal(this->input2, this->input1));
- }
-
- };
-
-
-
- template <typename I, typename N>
- struct reconstruction_erosion_ret :
- public reconstruction_hybrid_ret<I, N, reconstruction_erosion_ret<I, N> >
- {
- typedef reconstruction_hybrid_ret<I, N, reconstruction_erosion_ret<I, N> >
super_type;
-
- reconstruction_erosion_ret(const abstract::image<I>& input1, //marker
- const abstract::image<I>& input2, //mask
- const abstract::neighborhood<N>& nbh)
-
- : super_type(input1, input2, nbh)
- {}
-
- void fwd_loop_body_impl()
- {
- this->output[this->fwd_p] = ntg::max(morpho::min(this->output.unbox(),
- this->fwd_p,
- this->se_plus),
- this->input2[this->fwd_p].value());
- }
-
- void bkd_loop_body_impl()
- {
- this->output[this->bkd_p] = ntg::max(morpho::min(this->output.unbox(),
- this->bkd_p,
- this->se_minus),
- this->input2[this->bkd_p].value());
- }
-
- void fifo_loop_body_impl()
- {
- if ((this->output[this->q] > this->output[this->p]) &&
- (this->input2[this->q] != this->output[this->q]))
- {
- this->output[this->q] = ntg::max(this->output[this->p].value(),
- this->input2[this->q].value());
- this->fifo.push(this->q);
- }
- }
-
- bool exist_init_impl()
- {
- return this->output.hold(this->q) &&
- (this->output[this->q] > this->output[this->bkd_p]) &&
- (this->output[this->q] > this->input2[this->q]);
- }
-
- void preconditions_impl()
- {
- precondition(level::is_greater_or_equal(this->input1, this->input2));
- }
-
- };
-
- }
-
- template<class I, class N>
- reconstruction_ret<I, N>
- geodesic_reconstruction_dilation(const abstract::image<I> & marker,
- const abstract::image<I> & mask,
- const abstract::neighborhood<N>& nbh)
- {
- impl::reconstruction_dilation_ret<I, N> tmp(marker, mask, nbh);
- tmp.run();
- return tmp;
- }
-
- template<class I, class N>
- reconstruction_ret<I, N>
- geodesic_reconstruction_erosion(const abstract::image<I> & marker,
- const abstract::image<I> & mask,
- const abstract::neighborhood<N>& nbh)
- {
- impl::reconstruction_erosion_ret<I, N> tmp(marker, mask, nbh);
- tmp.run();
- return tmp;
- }
- }// hybrid
-
- }
-
-}
-
#endif // ! OLENA_MORPHO_RECONSTRUCTION_HH
Index: oln/morpho/splitse.hh
--- oln/morpho/splitse.hh (revision 162)
+++ oln/morpho/splitse.hh (working copy)
@@ -34,6 +34,10 @@
# include <oln/core/2d/size2d.hh>
# include <oln/core/3d/size3d.hh>
+# include <oln/core/abstract/window.hh>
+# include <oln/core/abstract/window.hh>
+
+
namespace oln {
namespace morpho {
@@ -76,22 +80,21 @@
template<class W>
W
- get_plus_win_only(const abstract::window<W>& win)
+ get_plus_win_only(const W& win) // FIXME: abstract::window<W>& win)
{
- oln_wn_type_of(W, fwd_iter) q(win.exact());
W out;
- // FIXME: too many changes: rewrite!
-// for_all (q)
-// {
-// unsigned n;
-// for (n = 0; n < dim_traits<oln_wn_type_of(W, size)>::dim; ++n)
-// if (dp.nth(n) < 0) {
-// out.add(dp);
-// break;
-// } else if (dp.nth(n) > 0) {
-// break;
-// }
-// }
+ for (unsigned i = 0; i < win.card(); ++i)
+ {
+ const oln_wn_type_of(W, dpoint)& dp = win.get_dp()[i];
+ unsigned n;
+ for (n = 0; n < dim_traits<oln_wn_type_of(W, size)>::dim; ++n)
+ if (dp.nth(n) < 0) {
+ out.add(dp);
+ break;
+ } else if (dp.nth(n) > 0) {
+ break;
+ }
+ }
return out;
}
@@ -110,26 +113,24 @@
*/
template<class W>
W
- get_plus_win_p(const abstract::window<W>& win)
+ get_plus_win_p(const W& win) // abstract::window<W>& win)
{
- oln_wn_type_of(W, fwd_iter) q(win.exact());
W out;
-
- // FIXME: too many changes: rewrite!
-// for_all (dp)
-// {
-// unsigned n;
-// for (n = 0; n < dim_traits<oln_wn_type_of(W, size)>::dim; ++n)
-// if (dp.nth(n) < 0) {
-// out.add(dp);
-// break;
-// } else if (dp.nth(n) > 0) {
-// break;
-// }
-// // All p.nth(n) are 0.
-// if (n == dim_traits<oln_wn_type_of(W, size)>::dim)
-// out.add(dp);
-// }
+ for (unsigned i = 0; i < win.card(); ++i)
+ {
+ const oln_wn_type_of(W, dpoint)& dp = win.get_dp()[i];
+ unsigned n;
+ for (n = 0; n < dim_traits<oln_wn_type_of(W, size)>::dim; ++n)
+ if (dp.nth(n) < 0) {
+ out.add(dp);
+ break;
+ } else if (dp.nth(n) > 0) {
+ break;
+ }
+ // All p.nth(n) are 0.
+ if (n == dim_traits<oln_wn_type_of(W, size)>::dim)
+ out.add(dp);
+ }
return out;
}
@@ -147,23 +148,21 @@
*/
template<class W>
W
- get_minus_win_only(const abstract::window<W>& win)
+ get_minus_win_only(const W& win) // abstract::window<W>& win)
{
- oln_wn_type_of(W, fwd_iter) q(win.exact());
W out;
-
- // FIXME: too many changes: rewrite!
-// for_all (dp)
-// {
-// unsigned n;
-// for (n = 0; n < dim_traits<oln_wn_type_of(W, size)>::dim; ++n)
-// if (dp.nth(n) > 0) {
-// out.add(dp);
-// break;
-// } else if (dp.nth(n) < 0) {
-// break;
-// }
-// }
+ for (unsigned i = 0; i < win.card(); ++i)
+ {
+ const oln_wn_type_of(W, dpoint)& dp = win.get_dp()[i];
+ unsigned n;
+ for (n = 0; n < dim_traits<oln_wn_type_of(W, size)>::dim; ++n)
+ if (dp.nth(n) > 0) {
+ out.add(dp);
+ break;
+ } else if (dp.nth(n) < 0) {
+ break;
+ }
+ }
return out;
}
@@ -182,26 +181,24 @@
*/
template<class W>
W
- get_minus_win_p(const abstract::window<W>& win)
+ get_minus_win_p(const W& win) // abstract::window<W>& win)
{
- oln_wn_type_of(W, fwd_iter) q(win.exact());
W out;
-
- // FIXME: too many changes: rewrite!
-// for_all (dp)
-// {
-// unsigned n;
-// for (n = 0; n < dim_traits<oln_wn_type_of(W, size)>::dim; ++n)
-// if (dp.nth(n) > 0) {
-// out.add(dp);
-// break;
-// } else if (dp.nth(n) < 0) {
-// break;
-// }
-// // All p.nth(n) are 0.
-// if (n == dim_traits<oln_wn_type_of(W, size)>::dim)
-// out.add(dp);
-// }
+ for (unsigned i = 0; i < win.card(); ++i)
+ {
+ const oln_wn_type_of(W, dpoint)& dp = win.get_dp()[i];
+ unsigned n;
+ for (n = 0; n < dim_traits<oln_wn_type_of(W, size)>::dim; ++n)
+ if (dp.nth(n) > 0) {
+ out.add(dp);
+ break;
+ } else if (dp.nth(n) < 0) {
+ break;
+ }
+ // All p.nth(n) are 0.
+ if (n == dim_traits<oln_wn_type_of(W, size)>::dim)
+ out.add(dp);
+ }
return out;
}
Index: oln/morpho/reconstruction_by_erosion.inc
--- oln/morpho/reconstruction_by_erosion.inc (revision 0)
+++ oln/morpho/reconstruction_by_erosion.inc (revision 0)
@@ -0,0 +1,141 @@
+// Copyright (C) 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 filek 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.
+
+namespace oln {
+
+ namespace morpho {
+
+ namespace impl {
+
+ // Sequential version
+
+ template<typename I1, typename I2>
+ struct generic_reconstruction <tag::by_erosion, tag::sequential, I1, I2>
+ : public generic_reconstruction_canvas<I1, I2, tag::sequential,
+ generic_reconstruction<tag::by_erosion, tag::sequential, I1, I2> >
+ {
+ typedef generic_reconstruction<tag::by_erosion,
+ tag::sequential, I1,I2> self_type;
+ typedef generic_reconstruction_canvas<I1, I2, tag::sequential,
+ self_type> super_type;
+
+ generic_reconstruction(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask) :
+ super_type(marker, mask)
+ {
+ }
+
+
+ void impl_bkd_loop_body()
+ {
+ this->output[this->bkd_p] = ntg::max(morpho::min(this->output,
+ this->bkd_p,
+ this->win_minus),
+ this->mask[this->bkd_p].value());
+ }
+
+ void impl_fwd_loop_body()
+ {
+ this->output[this->fwd_p] = ntg::max(morpho::min(this->output,
+ this->fwd_p,
+ this->win_plus),
+ this->mask[this->fwd_p].value());
+ }
+
+ void impl_preconditions()
+ {
+ precondition(level::is_greater_or_equal(this->marker, this->mask));
+ }
+
+ };
+
+ // Hybrid version
+
+ template<typename I1, typename I2>
+ struct generic_reconstruction <tag::by_erosion, tag::hybrid, I1, I2>
+ : public generic_reconstruction_canvas<I1, I2, tag::hybrid,
+ generic_reconstruction<tag::by_erosion, tag::hybrid, I1, I2> >
+ {
+ typedef generic_reconstruction<tag::by_erosion,
+ tag::hybrid, I1,I2> self_type;
+ typedef generic_reconstruction_canvas<I1, I2, tag::hybrid,
+ self_type> super_type;
+
+ generic_reconstruction(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask) :
+ super_type(marker, mask)
+ {
+ }
+
+
+
+ void impl_bkd_loop_body()
+ {
+ this->output[this->bkd_p] = ntg::max(morpho::min(this->work,
+ this->bkd_p,
+ this->win_minus),
+ this->mask[this->bkd_p].value());
+ }
+
+ void impl_fwd_loop_body()
+ {
+ this->output[this->fwd_p] = ntg::max(morpho::min(this->work,
+ this->fwd_p,
+ this->win_plus),
+ this->mask[this->fwd_p].value());
+ }
+
+ void impl_fifo_loop_body()
+ {
+ if ((this->output[this->q] > this->output[this->p]) &&
+ (this->mask[this->q] != this->output[this->q]))
+ {
+ this->output[this->q] = ntg::min(this->output[this->p].value(),
+ this->mask[this->q].value());
+ this->fifo.push(this->q);
+ }
+ }
+
+ bool impl_exist_init()
+ {
+ return this->output.hold(this->q) &&
+ (this->output[this->q] > this->output[this->bkd_p]) &&
+ (this->output[this->q] > this->mask[this->q]);
+ }
+
+ void impl_preconditions()
+ {
+ precondition(level::is_greater_or_equal(this->marker, this->mask));
+ }
+
+ };
+
+ }
+
+ }
+
+}
Index: oln/morpho/reconstruction_canvas.inc
--- oln/morpho/reconstruction_canvas.inc (revision 0)
+++ oln/morpho/reconstruction_canvas.inc (revision 0)
@@ -0,0 +1,238 @@
+// Copyright (C) 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 filek 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.
+
+
+namespace oln {
+
+ namespace morpho {
+
+ namespace impl {
+
+ template <typename I1, typename I2, typename A, typename E>
+ struct generic_reconstruction_canvas;
+
+ template <typename I1, typename I2, typename E>
+ struct generic_reconstruction_canvas<I1, I2, tag::sequential, E> :
+ public reconstruction_ret<I1, I2>
+ {
+ typedef reconstruction_ret<I1, I2> super_type;
+ typedef oln_type_of(I1, neighb) nbh_type;
+ typedef oln_type_of(I1, concrete) output_type;
+
+ E& exact__()
+ {
+ return *(E*)(void*)(this);
+ }
+
+ void bkd_loop_body()
+ {
+ this->exact__().impl_bkd_loop_body();
+ }
+ void fwd_loop_body()
+ {
+ this->exact__().impl_fwd_loop_body();
+ }
+
+ void preconditions()
+ {
+ mlc::eq<oln_type_of(I1, grid), oln_type_of(I2, grid)>::ensure();
+ precondition(this->marker.size() == this->mask.size());
+ this->exact__().impl_preconditions();
+ }
+
+ void init()
+ {
+ // no call to impl_init here because this canvas can't be generalized yet.
+ this->output = utils::clone(this->marker);
+ this->work = utils::clone(this->marker);
+
+ win_plus = get_plus_win_p(convert::nbh_to_cse(this->marker.nbh_get()));
+ win_minus = get_minus_win_p(convert::nbh_to_cse(this->marker.nbh_get()));
+ }
+
+ bool is_stable()
+ {
+ // same explanation as above
+ return level::is_equal(this->work, this->output);
+ }
+
+ void impl_run()
+ {
+ this->preconditions();
+ this->init();
+ for (;;)
+ {
+ for_all_p (fwd_p)
+ this->fwd_loop_body();
+ for_all_p (bkd_p)
+ this->bkd_loop_body();
+ if (this->is_stable())
+ return;
+ work = utils::clone(this->output);
+ }
+ }
+
+ protected:
+
+ generic_reconstruction_canvas(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask) :
+ super_type(marker, mask),
+ bkd_p(marker.size()),
+ fwd_p(marker.size())
+ {
+ }
+
+
+ oln_type_of(I1, bkd_piter) bkd_p;
+ oln_type_of(I1, fwd_piter) fwd_p;
+
+ oln_nbh_type_of(nbh_type, window) win_plus;
+ oln_nbh_type_of(nbh_type, window) win_minus;
+
+ box<oln_type_of(I1, concrete)> work;
+ };
+
+ template <typename I1, typename I2, typename E>
+ struct generic_reconstruction_canvas<I1, I2, tag::hybrid, E> :
+ public reconstruction_ret<I1, I2>
+ {
+ typedef reconstruction_ret<I1, I2> super_type;
+ typedef oln_type_of(I1, neighb) nbh_type;
+ typedef oln_nbh_type_of(nbh_type, window) window_type;
+ typedef oln_type_of(I1, concrete) output_type;
+
+ E& exact__()
+ {
+ return *(E*)(void*)(this);
+ }
+
+
+ bool exist_init()
+ {
+ for (unsigned i = 0; i < win_minus.card(); ++i)
+ {
+ q = win_minus.get_dp()[i] + (oln_type_of(I1, point))bkd_p;
+ if (this->exact__().impl_exist_init())
+ return true;
+ }
+ return false;
+ }
+
+ void bkd_loop_body()
+ {
+ this->exact__().impl_bkd_loop_body();
+ }
+ void fwd_loop_body()
+ {
+ this->exact__().impl_fwd_loop_body();
+ }
+
+ void fifo_loop_body()
+ {
+ this->exact__().impl_fifo_loop_body();
+ }
+
+ void preconditions()
+ {
+ mlc::eq<oln_type_of(I1, grid), oln_type_of(I2, grid)>::ensure();
+ precondition(this->marker.size() == this->mask.size());
+ this->exact__().impl_preconditions();
+ }
+
+ void init()
+ {
+ output_type tmp(this->marker.size());
+
+ this->output = tmp;
+ this->work = utils::clone(this->marker);
+
+ win_plus = get_plus_win_p(convert::nbh_to_cse(this->marker.nbh_get()));
+ win_minus = get_minus_win_p(convert::nbh_to_cse(this->marker.nbh_get()));
+ }
+
+ void impl_run()
+ {
+ this->preconditions();
+ this->init();
+
+ for_all_p (fwd_p)
+ this->fwd_loop_body();
+
+ for_all_p (bkd_p)
+ {
+ bkd_loop_body();
+ if (exist_init())
+ fifo.push(bkd_p);
+ }
+ // Propagation Step
+ while (!fifo.empty())
+ {
+ p = fifo.front();
+ fifo.pop();
+
+ window_type win = convert::nbh_to_se(this->marker.nbh_get());
+ for (unsigned i = 0; i < win.card(); ++i)
+ {
+ q = win.get_dp()[i] + p;
+
+ if (this->output.hold(q))
+ fifo_loop_body();
+ }
+ }
+ }
+
+ protected:
+
+ generic_reconstruction_canvas(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask) :
+ super_type(marker, mask),
+ bkd_p(marker.size()),
+ fwd_p(marker.size())
+ {
+ }
+
+
+ oln_type_of(I1, bkd_piter) bkd_p;
+ oln_type_of(I1, fwd_piter) fwd_p;
+
+ oln_type_of(I1, point) p;
+ oln_type_of(I1, point) q;
+
+ window_type win_plus;
+ window_type win_minus;
+
+ box<oln_type_of(I1, concrete)> work;
+
+ std::queue<oln_type_of(I1, point) > fifo;
+
+ };
+
+ } // end of namespace impl
+
+ } // end of namespace morpho
+
+} // end of namespace oln
Index: oln/morpho/reconstruction_by_dilation.inc
--- oln/morpho/reconstruction_by_dilation.inc (revision 0)
+++ oln/morpho/reconstruction_by_dilation.inc (revision 0)
@@ -0,0 +1,142 @@
+// Copyright (C) 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 filek 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.
+
+namespace oln {
+
+ namespace morpho {
+
+ namespace impl {
+
+ // Sequential version
+
+ template<typename I1, typename I2>
+ struct generic_reconstruction <tag::by_dilation, tag::sequential, I1, I2>
+ : public generic_reconstruction_canvas<I1, I2, tag::sequential,
+ generic_reconstruction<tag::by_dilation, tag::sequential, I1, I2> >
+ {
+ typedef generic_reconstruction<tag::by_dilation,
+ tag::sequential, I1,I2> self_type;
+ typedef generic_reconstruction_canvas<I1, I2, tag::sequential,
+ self_type> super_type;
+
+ generic_reconstruction(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask) :
+ super_type(marker, mask)
+ {
+ }
+
+
+ void impl_bkd_loop_body()
+ {
+ this->output[this->bkd_p] = ntg::min(morpho::max(this->output,
+ this->bkd_p,
+ this->win_minus),
+ this->mask[this->bkd_p].value());
+ }
+
+ void impl_fwd_loop_body()
+ {
+ this->output[this->fwd_p] = ntg::min(morpho::max(this->output,
+ this->fwd_p,
+ this->win_plus),
+ this->mask[this->fwd_p].value());
+ }
+
+ void impl_preconditions()
+ {
+ precondition(level::is_greater_or_equal(this->mask, this->marker));
+ }
+
+ };
+
+
+ // Hybrid version
+
+ template<typename I1, typename I2>
+ struct generic_reconstruction <tag::by_dilation, tag::hybrid, I1, I2>
+ : public generic_reconstruction_canvas<I1, I2, tag::hybrid,
+ generic_reconstruction<tag::by_dilation, tag::hybrid, I1, I2> >
+ {
+ typedef generic_reconstruction<tag::by_dilation,
+ tag::hybrid, I1,I2> self_type;
+ typedef generic_reconstruction_canvas<I1, I2, tag::hybrid,
+ self_type> super_type;
+
+ generic_reconstruction(const abstract::image_with_nbh<I1>& marker,
+ const abstract::image<I2>& mask) :
+ super_type(marker, mask)
+ {
+ }
+
+
+
+ void impl_bkd_loop_body()
+ {
+ this->output[this->bkd_p] = ntg::min(morpho::max(this->work,
+ this->bkd_p,
+ this->win_minus),
+ this->mask[this->bkd_p].value());
+ }
+
+ void impl_fwd_loop_body()
+ {
+ this->output[this->fwd_p] = ntg::min(morpho::max(this->work,
+ this->fwd_p,
+ this->win_plus),
+ this->mask[this->fwd_p].value());
+ }
+
+ void impl_fifo_loop_body()
+ {
+ if ((this->output[this->q] < this->output[this->p]) &&
+ (this->mask[this->q] != this->output[this->q]))
+ {
+ this->output[this->q] = ntg::min(this->output[this->p].value(),
+ this->mask[this->q].value());
+ this->fifo.push(this->q);
+ }
+ }
+
+ bool impl_exist_init()
+ {
+ return this->output.hold(this->q) &&
+ (this->output[this->q] < this->output[this->bkd_p]) &&
+ (this->output[this->q] < this->mask[this->q]);
+ }
+
+ void impl_preconditions()
+ {
+ precondition(level::is_greater_or_equal(this->mask, this->marker));
+ }
+
+ };
+
+ }
+
+ }
+
+}
Index: img/marker.pbm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: img/marker.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: img/mask.pbm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: img/mask.pbm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream