Index: ChangeLog
from Damien Thivolle <damien(a)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<image2d<ntg::bin>, neighborhood2d> res_ero_hyb;
image_with_nbh<image2d<ntg::bin>, neighborhood2d> res_ero_seq;
image_with_nbh<image2d<ntg::bin>, neighborhood2d> res_ero_par;
+ image_with_nbh<image2d<ntg::bin>, neighborhood2d> res_selfdual;
+ image_with_nbh<image2d<ntg::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;
}
+
+