Index: ChangeLog from Damien Thivolle damien@lrde.epita.fr
* tests/morpho/tests/reconstruction: Add tests for the selfdual reconstruction. * oln/morpho/reconstruction.hh: Uncomment parts related to the selfdual reconstruction. * oln/morpho/reconstruction_selfdual.hh: Selfdual reconstruction now use neighborhood in place of windows.
oln/morpho/reconstruction.hh | 20 ++--- oln/morpho/reconstruction_selfdual.hh | 118 +++++++++++++++++++++++++--------- tests/morpho/tests/reconstruction | 20 +++++ 3 files changed, 117 insertions(+), 41 deletions(-)
Index: oln/morpho/reconstruction.hh --- oln/morpho/reconstruction.hh (revision 262) +++ oln/morpho/reconstruction.hh (working copy) @@ -30,7 +30,7 @@
# include <oln/morpho/reconstruction_by_dilation.hh> # include <oln/morpho/reconstruction_by_erosion.hh> -// # include <oln/morpho/reconstruction_selfdual.hh> +# include <oln/morpho/reconstruction_selfdual.hh>
namespace oln {
@@ -83,16 +83,16 @@
// self dual
-// template <typename I1, typename I2> -// oln_type_of(I1, concrete) -// reconstruction_selfdual(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()); + template <typename I1, typename I2> + oln_type_of(I1, concrete) + reconstruction_selfdual(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(marker, mask, tag::selfdual(), tag::none()); -// } + return reconstruction(marker, mask, tag::selfdual(), tag::none()); + }
// by dilation
Index: oln/morpho/reconstruction_selfdual.hh --- oln/morpho/reconstruction_selfdual.hh (revision 262) +++ oln/morpho/reconstruction_selfdual.hh (working copy) @@ -30,6 +30,8 @@
# include <oln/canvas/reconstruction.hh> # include <oln/morpho/tags.hh> +# include <oln/morpho/local.hh> +# include <oln/funobj/arith.hh>
//FIXME: Adapt ... @@ -44,12 +46,12 @@
template<typename I1, typename I2> struct reconstruction <I1, I2, tag::selfdual_type, tag::none_type> - : public canvas::hybrid_reconstruction<I1, I2, + : public canvas::reconstruction<I1, I2, tag::hybrid_type, reconstruction<I1, I2, tag::selfdual_type, tag::none_type> > { typedef reconstruction<I1, I2, tag::selfdual_type, tag::none_type> self_type; - typedef canvas::hybrid_reconstruction<I1, I2, + typedef canvas::reconstruction<I1, I2, tag::hybrid_type, self_type> super_type;
reconstruction(const abstract::image_with_nbh<I1>& marker, @@ -60,65 +62,123 @@
using super_type::mask; using super_type::marker; - using super_type::work; using super_type::output; using super_type::fwd_p; using super_type::bkd_p; - using super_type::win_plus; - using super_type::win_minus; using super_type::p; - using super_type::q; + using super_type::n; using super_type::fifo;
+ /// Local image "or-value" for dilation on sets + /// (based on the point and its backward neighborhood). + + oln_type_of(I1, value) bkd_or() + { + if (output[bkd_p]) + return true; + p = bkd_p; + for_all_n_of_p(n, p) + if (p.bkd_less(n) and output.hold(n) and output[n]) + return true; + + return false; + } + + + /// Local image "or-value" for dilation on sets + /// (based on the point and its forward neighborhood). + + oln_type_of(I1, value) fwd_or() + { + if (output[fwd_p]) + return true; + p = fwd_p; + for_all_n_of_p(n, p) + if (p.fwd_less(n) and output.hold(n) and output[n]) + return true; + + return false; + } + + + + /// Local image "and-value" for erosion on sets + /// (based on the point and its backward neighborhood). + + oln_type_of(I1, value) bkd_and() + { + if (not output[bkd_p]) + return false; + p = bkd_p; + for_all_n_of_p(n, p) + if (p.bkd_less(n) and output.hold(n) and not output[n]) + return false; + + return true; + } + + + /// Local image "and-value" for erosion on sets + /// (based on the point and its forward neighborhood). + + oln_type_of(I1, value) fwd_and() + { + if (not output[fwd_p]) + return false; + p = fwd_p; + for_all_n_of_p(n, p) + if (p.fwd_less(n) and output.hold(n) and not output[n]) + return false; + + return true; + } + + void impl_bkd_loop_body() { // FIXME: Shouldn't be .value() ! - if (work[bkd_p] < mask[bkd_p]) - output[bkd_p] = ntg::min(local_max(work, bkd_p, win_minus), - mask[bkd_p].value()); + if (output[bkd_p] < mask[bkd_p]) + output[bkd_p] = f_min_alt(bkd_or(), mask[bkd_p].value()); else - output[bkd_p] = ntg::max(local_min(work, bkd_p, win_minus), - mask[bkd_p].value()); + output[bkd_p] = f_max_alt(bkd_and(), mask[bkd_p].value()); }
void impl_fwd_loop_body() { // FIXME: Shouldn't be .value() ! - if (work[fwd_p] < mask[fwd_p]) - output[fwd_p] = ntg::min(local_max(work, fwd_p, win_plus), - mask[fwd_p].value()); + if (output[fwd_p] < mask[fwd_p]) + output[fwd_p] = f_min_alt(fwd_or(), mask[fwd_p].value()); else - output[fwd_p] = ntg::max(local_min(work, fwd_p, win_plus), - mask[fwd_p].value()); + output[fwd_p] = f_max_alt(fwd_and(), mask[fwd_p].value()); }
void impl_fifo_loop_body() { - if (output[q] < mask[p]) + if (output[n] < mask[p]) { - if (output[q] < output[p] && mask[q] != output[q]) + if (output[n] < output[p] && mask[n] != output[n]) { - output[q] = ntg::min(output[p].value(), mask[q].value()); - fifo.push(q); + output[n] = f_min_alt(output[p].value(), mask[n].value()); + fifo.push(n); } } else - if (output[q] > output[p] && mask[q] != output[q]) + if (output[n] > output[p] && mask[n] != output[n]) { - output[q] = ntg::max(output[p].value(), mask[q].value()); - fifo.push(q); + output[n] = f_max_alt(output[p].value(), mask[n].value()); + fifo.push(n); } }
- bool impl_exist_init() + bool impl_test_fifo_push() { - return output.hold(q) && - ((output[q] < output[bkd_p] && output[q] < mask[q]) || - (output[q] > output[bkd_p] && output[q] > mask[q])); + return output.hold(n) && + ((output[n] < output[bkd_p] && output[n] < mask[n]) || + (output[n] > output[bkd_p] && output[n] > mask[n])); }
- void impl_preconditions() + void impl_preconditions() const { }
Index: tests/morpho/tests/reconstruction --- tests/morpho/tests/reconstruction (revision 262) +++ tests/morpho/tests/reconstruction (working copy) @@ -28,6 +28,8 @@ image_with_nbh<image2dntg::bin, neighborhood2d> res_ero_hyb; image_with_nbh<image2dntg::bin, neighborhood2d> res_ero_seq; image_with_nbh<image2dntg::bin, neighborhood2d> res_ero_par; + image_with_nbh<image2dntg::bin, neighborhood2d> res_selfdual; + image_with_nbh<image2dntg::bin, neighborhood2d> res_selfdual_invert;
utils::key::value_type data_key[16] = { 0xd1, 0x5c, 0x13, 0xd8, 0xe0, 0xa8, 0x58, 0x7d, @@ -73,6 +75,14 @@ morpho::tag::parallel(), morpho::tag::by_erosion());
+ res_selfdual = + morpho::reconstruction_selfdual(join(marker, neighb_c4()), + mask); + + res_selfdual_invert = + morpho::reconstruction_selfdual(join(marker_c, neighb_c4()), + level::invert(mask)); + if (utils::md5(res_dil_hyb) != key) return true;
@@ -81,12 +91,18 @@ return true; if (!level::is_equal(res_ero_hyb, res_ero_seq)) return true; - if (!level::is_equal(res_dil_hyb, level::invert(res_ero_seq))) - return true; if (!level::is_equal(res_dil_hyb, res_dil_par)) return true; if (!level::is_equal(res_ero_hyb, res_ero_par)) return true; + if (!level::is_equal(res_selfdual, level::invert(res_selfdual_invert))) + return true; + if (!level::is_equal(res_dil_hyb, level::invert(res_ero_seq))) + return true; + if (!level::is_equal(res_dil_hyb, res_selfdual)) + return true;
return false; } + +