proto-1.0 130: Better code factorization in morphological reconstruction

Index: ChangeLog from Damien Thivolle <damien@lrde.epita.fr> * oln/morpho/reconstruction.hh: Improve factorization. reconstruction.hh | 367 ++++++++++++++++++++++++++++++------------------------ 1 files changed, 207 insertions(+), 160 deletions(-) Index: oln/morpho/reconstruction.hh --- oln/morpho/reconstruction.hh (revision 129) +++ oln/morpho/reconstruction.hh (working copy) @@ -93,47 +93,44 @@ namespace impl { - template <typename I, typename N> + template <typename I, typename N, typename E> struct reconstruction_sequential_ret : public reconstruction_ret<I, N> { typedef reconstruction_ret<I, N> super_type; + void fwd_loop_body() + { + static_cast<E*>((void*)this)->fwd_loop_body_impl(); + } - virtual const oln_type_of(I, value) process(const I& work, - const oln_type_of(I, point)& p, - const oln_type_of(N, window)& se, - const oln_type_of(I, value)& v) + void bkd_loop_body() { - std::cerr << "oops in " << __func__ << std::endl; - return oln_type_of(I, value)(); + static_cast<E*>((void*)this)->bkd_loop_body_impl(); } + void preconditions() + { + precondition(this->input1.size() == this->input2.size()); + static_cast<E*>((void*)this)->preconditions_impl(); + } + void impl_run() { mlc::eq<oln_type_of(I, size), oln_type_of(N, size)>::ensure(); - precondition(this->input1.size() == this->input2.size()); - precondition(level::is_greater_or_equal(this->input2, this->input1)); - // Conversion of neighborhood into a SE. - oln_type_of(N, window) se_plus = get_plus_se_p(convert::nbh_to_cse(this->nbh)); - oln_type_of(N, window) se_minus = get_minus_se_p(convert::nbh_to_cse(this->nbh)); - I output; output = utils::clone(this->input1); bool non_stability = true; - oln_type_of(I, fwd_piter) fwd_p(output.size()); - oln_type_of(I, bkd_piter) bkd_p(output.size()); while (non_stability) { - I work; - work = utils::clone(output); + work.unbox() = utils::clone(output); for_all (fwd_p) - work[fwd_p] = this->process(work, fwd_p, se_plus, this->input2[fwd_p].value()); + fwd_loop_body(); for_all (bkd_p) - work[bkd_p] = this->process(work, bkd_p, se_minus, this->input2[bkd_p].value()); + bkd_loop_body(); non_stability = !(level::is_equal(work, output)); - output = work; + output = work.unbox(); } this->output = output; } @@ -142,17 +139,27 @@ 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) - {} + : 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; + box<I> work; }; - template <typename I, typename N> - struct reconstruction_dilation_ret : public reconstruction_sequential_ret<I, N> + struct reconstruction_dilation_ret : + public reconstruction_sequential_ret<I, N, reconstruction_dilation_ret<I, N> > { - typedef reconstruction_sequential_ret<I, N> super_type; + typedef reconstruction_sequential_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 @@ -161,21 +168,35 @@ : super_type(input1, input2, nbh) {} - const oln_type_of(I, value) process(const I& work, - const oln_type_of(I, point)& p, - const oln_type_of(N, window)& se, - const oln_type_of(I, value)& v) + void fwd_loop_body_impl() { - return ntg::min(morpho::max(work, p, se), v); + this->work[this->fwd_p] = ntg::min(morpho::max(this->work.unbox(), + this->fwd_p, + this->se_plus), + this->input2[this->fwd_p].value()); } + 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()); + } + + void preconditions_impl() + { + precondition(level::is_greater_or_equal(this->input2, this->input1)); + } + }; template <typename I, typename N> - struct reconstruction_erosion_ret : public reconstruction_sequential_ret<I, N> + struct reconstruction_erosion_ret : + public reconstruction_sequential_ret<I, N, reconstruction_erosion_ret<I, N> > { - typedef reconstruction_sequential_ret<I, N> super_type; + typedef reconstruction_sequential_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 @@ -184,13 +205,27 @@ : super_type(input1, input2, nbh) {} - const oln_type_of(I, value) process(const I& work, - const oln_type_of(I, point)& p, - const oln_type_of(N, window)& se, - const oln_type_of(I, value)& v) const + void fwd_loop_body_impl() { - return ntg::max(morpho::min(work, p, se), v); + this->work[this->fwd_p] = ntg::max(morpho::min(this->work.unbox(), + this->fwd_p, + this->se_plus), + this->input2[this->fwd_p].value()); } + + 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()); + } + + void preconditions_impl() + { + precondition(level::is_greater_or_equal(this->input1, this->input2)); + } + }; } @@ -224,93 +259,113 @@ namespace impl { - template <typename I, typename N> + template <typename I, typename N, typename E> struct reconstruction_hybrid_ret : public reconstruction_ret<I, N> { typedef reconstruction_ret<I, N> super_type; - reconstruction_hybrid_ret(const abstract::image<I>& input1, //marker - const abstract::image<I>& input2, //mask - const abstract::neighborhood<N>& nbh) + bool exist_init() + { + typedef oln_type_of(N, window) se_type; + oln_type_of(se_type, fwd_witer) 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; + } - : super_type(input1, input2, nbh) - {} + void fwd_loop_body() + { + static_cast<E*>((void*)this)->fwd_loop_body_impl(); + } - virtual const oln_type_of(I, value) process(const I& work, - const oln_type_of(I, point)& p, - const oln_type_of(N, window)& se, - const oln_type_of(I, value)& v) const + void bkd_loop_body() { - std::cerr << "oops in " << __func__ << std::endl; - return oln_type_of(I, value)(); + static_cast<E*>((void*)this)->bkd_loop_body_impl(); } - virtual void loop_body(const oln_type_of(I, point)& p, - const oln_type_of(I, point)& q, - oln_type_of(I, concrete)& output, - std::queue<oln_type_of(I, point) >& fifo) + void fifo_loop_body() { - std::cerr << "oops in " << __func__ << std::endl; + static_cast<E*>((void*)this)->fifo_loop_body_impl(); } - virtual bool exist_init(const oln_type_of(I, point)& p, - const oln_type_of(I, concrete)& output, - const oln_type_of(N, window)& se) const + void preconditions() { - std::cerr << "oops in " << __func__ << std::endl; - return true; + precondition(this->input1.size() == this->input2.size()); + static_cast<E*>((void*)this)->preconditions_impl(); } - void impl_run() { mlc::eq<oln_type_of(I, size), oln_type_of(N, size)>::ensure(); - precondition(this->input1.size() == this->input2.size()); - precondition(level::is_greater_or_equal(this->input2, this->input1)); + preconditions(); - oln_type_of(I, concrete) output; - output = utils::clone(this->input1); - { - oln_type_of(N, window) se_plus = get_plus_se_p(convert::nbh_to_cse(this->nbh)); - oln_type_of(N, window) se_minus = get_minus_se_p(convert::nbh_to_cse(this->nbh)); - oln_type_of(I, fwd_piter) fwd_p(output.size()); - oln_type_of(I, fwd_piter) bkd_p(output.size()); + this->output.unbox() = utils::clone(this->input1); - for_all (fwd_p) - output[fwd_p] = this->process(output, fwd_p, se_plus, this->input2[fwd_p].value()); + std::cout << "for_all (fwd_p)" << std::endl; + for_all (fwd_p) + fwd_loop_body(); - std::queue<oln_type_of(I, point) > fifo; - for_all (bkd_p) - { - output[bkd_p] = this->process(output, bkd_p, se_minus, this->input2[bkd_p].value()); - if (this->exist_init((oln_type_of(I, point))bkd_p, output, se_minus)) - fifo.push(bkd_p); - } + std::cout << "for_all (bkd_p)" << std::endl; + for_all (bkd_p) + { + bkd_loop_body(); + if (exist_init()) + fifo.push(bkd_p); + } // Propagation Step - while (!fifo.empty()) - { - oln_type_of(I, point) p = fifo.front(); - fifo.pop(); - typedef oln_type_of(N, window) window_type; - window_type w = convert::nbh_to_se(this->nbh); - oln_type_of(window_type, fwd_witer) dp(w); + while (!fifo.empty()) + { + p = fifo.front(); + fifo.pop(); + typedef oln_type_of(N, window) window_type; + window_type w = convert::nbh_to_se(this->nbh); + oln_type_of(window_type, fwd_witer) dp(w); - for_all (dp) - { - oln_type_of(I, point) q = (oln_type_of(window_type, dpoint))dp + p; - this->loop_body(p, q, output, fifo); - } - } - } - this->output = output; + for_all (dp) + { + q = (oln_type_of(window_type, dpoint))dp + p; + 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> + struct reconstruction_dilation_ret : + public reconstruction_hybrid_ret<I, N, reconstruction_dilation_ret<I, N> > { - typedef reconstruction_hybrid_ret<I, N> super_type; + 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 @@ -319,47 +374,43 @@ : super_type(input1, input2, nbh) {} - const oln_type_of(I, value) process(const I& work, - const oln_type_of(I, point)& p, - const oln_type_of(N, window)& se, - const oln_type_of(I, value)& v) const + void fwd_loop_body_impl() { - return ntg::min(morpho::max(work, p, se), v); + this->output[this->fwd_p] = ntg::min(morpho::max(this->output.unbox(), + this->fwd_p, + this->se_plus), + this->input2[this->fwd_p].value()); } - virtual void loop_body(const oln_type_of(I, point)& p, - const oln_type_of(I, point)& q, - oln_type_of(I, concrete)& output, - std::queue<oln_type_of(I, point) >& fifo) + void bkd_loop_body_impl() { - if (output.hold(q)) + 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])) { - if ((output[q] < output[p]) && - (this->input2[q] != output[q])) - { - output[q] = ntg::min(output[p].value(), - this->input2[q].value()); - fifo.push(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]); } - - virtual bool exist_init(const oln_type_of(I, point)& p, - const oln_type_of(I, concrete)& marker, - const oln_type_of(N, window)& se) const + void preconditions_impl() { - typedef oln_type_of(N, window) se_type; - oln_type_of(se_type, fwd_witer) dp(se); - for_all (dp) - { - oln_type_of(I, point) q = (oln_type_of(se_type, dpoint))dp + p; - if (marker.hold(q) && (marker[q] < marker[p]) && - (marker[q] < this->input2[q])) - return true; - } - return false; + precondition(level::is_greater_or_equal(this->input2, this->input1)); } }; @@ -367,9 +418,10 @@ template <typename I, typename N> - struct reconstruction_erosion_ret : public reconstruction_hybrid_ret<I, N> + struct reconstruction_erosion_ret : + public reconstruction_hybrid_ret<I, N, reconstruction_erosion_ret<I, N> > { - typedef reconstruction_hybrid_ret<I, N> super_type; + 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 @@ -378,52 +430,47 @@ : super_type(input1, input2, nbh) {} - const oln_type_of(I, value) process(const I& work, - const oln_type_of(I, point)& p, - const oln_type_of(N, window)& se, - const oln_type_of(I, value)& v) const + void fwd_loop_body_impl() { - return ntg::max(morpho::min(work, p, se), v); + this->output[this->fwd_p] = ntg::max(morpho::min(this->output.unbox(), + this->fwd_p, + this->se_plus), + this->input2[this->fwd_p].value()); } - virtual void loop_body(const oln_type_of(I, point)& p, - const oln_type_of(I, point)& q, - oln_type_of(I, concrete)& output, - std::queue<oln_type_of(I, point) >& fifo) + void bkd_loop_body_impl() { - if (output.hold(q)) + 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])) { - if ((output[q] > output[p]) && - (this->input2[q] != output[q])) - { - output[q] = ntg::max(output[p].value(), - this->input2[q].value()); - fifo.push(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]); + } - virtual bool exist_init(const oln_type_of(I, point)& p, - const oln_type_of(I, concrete)& marker, - const oln_type_of(N, window)& se) const + void preconditions_impl() { - typedef oln_type_of(N, window) se_type; - oln_type_of(se_type, fwd_witer) dp(se); - for_all (dp) - { - oln_type_of(I, point) q = (oln_type_of(se_type, dpoint))dp + p; - if (marker.hold(q) && (marker[q] > marker[p]) && - (marker[q] > this->input2[q])) - return true; - } - return false; + precondition(level::is_greater_or_equal(this->input1, this->input2)); } }; - - } template<class I, class N>
participants (1)
-
Damien Thivolle