LRE
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
List overview
Download
Olena-patches
October 2005
----- 2025 -----
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
olena-patches@lrde.epita.fr
3 participants
4 discussions
Start a n
N
ew thread
proto-1.0 277: Add grey level self-dual reconstruction and clean reconstruction classes.
by Damien Thivolle
https://svn/svn/oln/prototypes/proto-1.0/olena
Index: ChangeLog from Damien Thivolle <damien(a)lrde.epita.fr> Add grey level self-dual reconstruction and clean reconstruction classes. * tests/morpho/tests/reconstruction: Remove. Split into two files (binary and grey level). * tests/morpho/tests/reconstruction_binary: New. Test reconstruction algorithms on binary images. * tests/morpho/tests/reconstruction_greylevel: New. Test reconstruction algorithms on grey level images. * oln/funobj/invert.hh: Now use UCHAR_MAX. * oln/morpho/reconstruction_by_dilation.hh: Call exact() when passing input images to the upper class. * oln/morpho/reconstruction_by_erosion.hh: Likewise. * oln/morpho/reconstruction_selfdual.hh: Add grey level self-dual reconstruction class. * oln/canvas/reconstruction.hh: Remove useless image boxes. oln/canvas/reconstruction.hh | 62 +++----------- oln/funobj/invert.hh | 2 oln/morpho/reconstruction_by_dilation.hh | 21 ++-- oln/morpho/reconstruction_by_erosion.hh | 18 ++-- oln/morpho/reconstruction_selfdual.hh | 122 ++++++++++++++++++++++++++-- tests/morpho/tests/reconstruction_greylevel | 106 ++++++++++++++++++++++++ 6 files changed, 256 insertions(+), 75 deletions(-) Index: tests/morpho/tests/reconstruction_greylevel --- tests/morpho/tests/reconstruction_greylevel (revision 0) +++ tests/morpho/tests/reconstruction_greylevel (revision 0) @@ -0,0 +1,106 @@ +// -*- 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/level/compare.hh> +#include <oln/utils/md5.hh> +#include <oln/level/invert.hh> + +// FIXME: Debug. +#include <oln/io/write_image.hh> + +bool check() +{ + using namespace oln; + image2d<unsigned char> marker; + image2d<unsigned char> mask; + image_with_nbh<image2d<unsigned char>, neighborhood2d> res_dil_hyb; + image_with_nbh<image2d<unsigned char>, neighborhood2d> res_dil_seq; + image_with_nbh<image2d<unsigned char>, neighborhood2d> res_dil_par; + image_with_nbh<image2d<unsigned char>, neighborhood2d> res_ero_hyb; + image_with_nbh<image2d<unsigned char>, neighborhood2d> res_ero_seq; + image_with_nbh<image2d<unsigned char>, neighborhood2d> res_ero_par; + image_with_nbh<image2d<unsigned char>, neighborhood2d> res_selfdual; + image_with_nbh<image2d<unsigned char>, neighborhood2d> res_selfdual_invert; + + utils::key::value_type data_key[16] = + {0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x0, 0xb2, 0x4, + 0xe9, 0x80, 0x9, 0x98, 0xec, 0xf8, 0x42, 0x7e}; + utils::key key(data_key); + + marker = io::read(rdata("marker.pgm")); + mask = io::read(rdata("mask.pgm")); + + res_dil_hyb = + morpho::reconstruction(join(marker, neighb_c4()), + mask, + morpho::tag::hybrid(), + morpho::tag::by_dilation()); + res_dil_seq = + morpho::reconstruction(join(marker, neighb_c4()), + mask, + morpho::tag::sequential(), + morpho::tag::by_dilation()); + + res_dil_par = + morpho::reconstruction(join(marker, neighb_c4()), + mask, + morpho::tag::parallel(), + morpho::tag::by_dilation()); + + image2d<unsigned char> marker_c(level::invert(marker)); + + res_ero_hyb = + morpho::reconstruction(join(marker_c, neighb_c4()), + level::invert(mask), + morpho::tag::hybrid(), + morpho::tag::by_erosion()); + res_ero_seq = + morpho::reconstruction(join(marker_c, neighb_c4()), + level::invert(mask), + morpho::tag::sequential(), + morpho::tag::by_erosion()); + + res_ero_par = + morpho::reconstruction(join(marker_c, neighb_c4()), + level::invert(mask), + 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; + + + 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, 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; + + return false; +} + + Index: oln/funobj/invert.hh --- oln/funobj/invert.hh (revision 276) +++ oln/funobj/invert.hh (working copy) @@ -46,7 +46,7 @@ { unsigned char operator()(const unsigned char& v) const { - return 255 - v; + return UCHAR_MAX - v; } bool operator()(const bool& v) const Index: oln/morpho/reconstruction_by_dilation.hh --- oln/morpho/reconstruction_by_dilation.hh (revision 276) +++ oln/morpho/reconstruction_by_dilation.hh (working copy) @@ -53,9 +53,6 @@ using super_type::output; using super_type::bkd_p; using super_type::fwd_p; - using super_type::n; - using super_type::p; - void impl_bkd_loop_body() { @@ -71,7 +68,7 @@ binary_reconstruction_by_dilation(const abstract::binary_image<I1>& marker, const abstract::binary_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -123,7 +120,7 @@ binary_reconstruction(const abstract::binary_image<I1>& marker, const abstract::binary_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -155,7 +152,7 @@ binary_reconstruction(const abstract::binary_image<I1>& marker, const abstract::binary_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -199,7 +196,7 @@ binary_reconstruction(const abstract::binary_image<I1>& marker, const abstract::binary_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -244,7 +241,7 @@ greylevel_reconstruction_by_dilation(const abstract::greylevel_image<I1>& marker, const abstract::greylevel_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -294,7 +291,7 @@ greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, const abstract::greylevel_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -326,7 +323,7 @@ greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, const abstract::greylevel_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -360,7 +357,7 @@ { output[fwd_p] = f_max_alt(output[fwd_p].value(), - local_sup_value(join(output, marker.nbh_get()), fwd_p)); + local_sup_value(join(save, marker.nbh_get()), fwd_p)); } void impl_second_step() @@ -375,7 +372,7 @@ greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, const abstract::greylevel_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } Index: oln/morpho/reconstruction_selfdual.hh --- oln/morpho/reconstruction_selfdual.hh (revision 276) +++ oln/morpho/reconstruction_selfdual.hh (working copy) @@ -57,7 +57,7 @@ binary_reconstruction(const abstract::binary_image<I1>& marker, const abstract::binary_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -74,7 +74,8 @@ void impl_bkd_loop_body() { - if (output[bkd_p] < mask[bkd_p]) + // output[bkd_p] < mask[bkd_p] + if (not output[bkd_p] and mask[bkd_p]) output[bkd_p] = mask[bkd_p] and (output[bkd_p] or local_or_value_bkd(join(output, marker.nbh_get()), bkd_p)); else @@ -84,7 +85,8 @@ void impl_fwd_loop_body() { - if (output[fwd_p] < mask[fwd_p]) + // output[fwd_p] < mask[fwd_p] + if (not output[fwd_p] and mask[fwd_p]) output[fwd_p] = mask[fwd_p] and (output[fwd_p] or local_or_value_fwd(join(output, marker.nbh_get()), fwd_p)); else @@ -95,16 +97,120 @@ void impl_fifo_loop_body() { + // output[n] < mask[p] + if (not output[n] and mask[p]) + { + // output[n] < output[p] and mask[n] != output[n] + if (output[p] and mask[n] != output[n]) + { + output[n] = output[p] and mask[n]; + fifo.push(n); + } + } + else + // output[n] > output[p] && mask[n] != output[n] + if (output[n] and not output[p] and mask[n] != output[n]) + { + output[n] = output[p] or mask[n]; + fifo.push(n); + } + } + + bool impl_test_fifo_push() + { + // (output[n] < output[bkd_p] and output[n] < mask[n]) or + // (output[n] > output[bkd_p] and output[n] > mask[n]) + return output.hold(n) && + ((not output[n] and output[bkd_p] and mask[n]) || + (output[n] and not output[bkd_p] and not mask[n])); + } + + void impl_preconditions() const + { + } + + }; + + + + // GREY LEVEL + + template<typename I1, typename I2> + struct greylevel_reconstruction <I1, I2, tag::selfdual_type, tag::none_type> + : public canvas::reconstruction<I1, I2, tag::hybrid_type, + greylevel_reconstruction<I1, I2, tag::selfdual_type, tag::none_type> > + { + typedef greylevel_reconstruction<I1, I2, tag::selfdual_type, + tag::none_type> self_type; + typedef canvas::reconstruction<I1, I2, tag::hybrid_type, + self_type> super_type; + typedef oln_type_of(I1, value) value_type; + + greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) : + super_type(marker.exact(), mask.exact()) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + } + + using super_type::mask; + using super_type::marker; + using super_type::output; + using super_type::fwd_p; + using super_type::bkd_p; + using super_type::p; + using super_type::n; + using super_type::fifo; + + + void impl_bkd_loop_body() + { + if (output[bkd_p] < mask[bkd_p]) + { + value_type max = + f_max_alt(output[bkd_p].value(), + local_sup_value_bkd(join(output, marker.nbh_get()), bkd_p)); + output[bkd_p] = f_min_alt(mask[bkd_p].value(), max); + } + else + { + value_type min = + f_min_alt(output[bkd_p].value(), + local_inf_value_bkd(join(output, marker.nbh_get()), bkd_p)); + output[bkd_p] = f_max_alt(mask[bkd_p].value(), min); + } + } + + void impl_fwd_loop_body() + { + if (output[fwd_p] < mask[fwd_p]) + { + value_type max = + f_max_alt(output[fwd_p].value(), + local_sup_value_fwd(join(output, marker.nbh_get()), fwd_p)); + output[fwd_p] = f_min_alt(mask[fwd_p].value(), max); + } + else + { + value_type min = + f_min_alt(output[fwd_p].value(), + local_inf_value_fwd(join(output, marker.nbh_get()), fwd_p)); + output[fwd_p] = f_max_alt(mask[fwd_p].value(), min); + } + } + + void impl_fifo_loop_body() + { if (output[n] < mask[p]) { - if (output[n] < output[p] && mask[n] != output[n]) + if (output[n] < output[p] and mask[n] != output[n]) { output[n] = f_min_alt(output[p].value(), mask[n].value()); fifo.push(n); } } else - if (output[n] > output[p] && mask[n] != output[n]) + if (output[n] > output[p] and mask[n] != output[n]) { output[n] = f_max_alt(output[p].value(), mask[n].value()); fifo.push(n); @@ -113,9 +219,9 @@ bool impl_test_fifo_push() { - return output.hold(n) && - ((output[n] < output[bkd_p] && output[n] < mask[n]) || - (output[n] > output[bkd_p] && output[n] > mask[n])); + return output.hold(n) and + ((output[n] < output[bkd_p] and output[n] < mask[n]) or + (output[n] > output[bkd_p] and output[n] > mask[n])); } void impl_preconditions() const Index: oln/morpho/reconstruction_by_erosion.hh --- oln/morpho/reconstruction_by_erosion.hh (revision 276) +++ oln/morpho/reconstruction_by_erosion.hh (working copy) @@ -70,7 +70,7 @@ binary_reconstruction_by_erosion(const abstract::binary_image<I1>& marker, const abstract::binary_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -122,7 +122,7 @@ binary_reconstruction(const abstract::binary_image<I1>& marker, const abstract::binary_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -154,7 +154,7 @@ binary_reconstruction(const abstract::binary_image<I1>& marker, const abstract::binary_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -198,7 +198,7 @@ binary_reconstruction(const abstract::binary_image<I1>& marker, const abstract::binary_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -250,7 +250,7 @@ greylevel_reconstruction_by_erosion(const abstract::greylevel_image<I1>& marker, const abstract::greylevel_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -300,7 +300,7 @@ greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, const abstract::greylevel_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -332,7 +332,7 @@ greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, const abstract::greylevel_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } @@ -365,7 +365,7 @@ { output[fwd_p] = f_min_alt(output[fwd_p].value(), - local_inf_value(join(output, marker.nbh_get()), fwd_p)); + local_inf_value(join(save, marker.nbh_get()), fwd_p)); } void impl_second_step() @@ -380,7 +380,7 @@ greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, const abstract::greylevel_image<I2>& mask) : - super_type(marker, mask) + super_type(marker.exact(), mask.exact()) { mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } Index: oln/canvas/reconstruction.hh --- oln/canvas/reconstruction.hh (revision 276) +++ oln/canvas/reconstruction.hh (working copy) @@ -108,11 +108,7 @@ void init() { - // FIXME: We can't use `output = clone(marker)' directly here, - // because box's op=(const abstract::image<II>& rhs) would be - // called, which is empty (see oln/core/box.hh). - output_type output_tmp(clone(marker)); - output = output_tmp; + output = clone(marker); } void run() @@ -146,12 +142,12 @@ oln_type_of(I1, concrete) get_output() { - return output.unbox(); + return output; } protected: - reconstruction(const abstract::image<I1>& marker, + reconstruction(const abstract::image_with_nbh<I1>& marker, const abstract::image<I2>& mask) : marker(marker.exact()), mask(mask.exact()), @@ -180,7 +176,7 @@ oln_type_of(I1, point) p; oln_type_of(I1, niter) n; - box<oln_type_of(I1, concrete)> output; + oln_type_of(I1, concrete) output; std::queue<oln_type_of(I1, point) > fifo; @@ -203,17 +199,8 @@ void impl_init() { - // FIXME: We can't use `output = clone(marker)' directly here, - // because box's op=(const abstract::image<II>& rhs) would be - // called, which is empty (see oln/core/box.hh). - output_type output_tmp(clone(marker)); - output = output_tmp; - // FIXME: We can't use `save = clone(marker)' directly here, - // because box's op=(const abstract::image<II>& rhs) would be - // called, which is empty (see oln/core/box.hh). - output_type save_tmp(clone(marker)); - save = save_tmp; - + output = clone(marker); + save = clone(marker); } bool impl_is_stable() const @@ -223,31 +210,27 @@ void impl_re_loop() { - // FIXME: We can't use `save = clone(output)' directly here, - // because box's op=(const abstract::image<II>& rhs) would be - // called, which is empty (see oln/core/box.hh). - save.unbox() = clone(output); + save = clone(output); } oln_type_of(I1, concrete) get_output() { - return output.unbox(); + return output; } protected: - reconstruction(const abstract::image<I1>& marker, + reconstruction(const abstract::image_with_nbh<I1>& marker, const abstract::image<I2>& mask) : super_type(marker), marker(marker.exact()), mask(mask.exact()), n(marker) { - mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } - box<oln_type_of(I1, concrete)> save; - box<oln_type_of(I1, concrete)> output; + oln_type_of(I1, concrete) save; + oln_type_of(I1, concrete) output; box<const I1> marker; box<const I2> mask; oln_type_of(I1, point) p; @@ -293,16 +276,8 @@ void impl_init() { - // FIXME: We can't use `output = clone(marker)' directly here, - // because box's op=(const abstract::image<II>& rhs) would be - // called, which is empty (see oln/core/box.hh). - output_type output_tmp(clone(marker)); - output = output_tmp; - // FIXME: We can't use `save = clone(marker)' directly here, - // because box's op=(const abstract::image<II>& rhs) would be - // called, which is empty (see oln/core/box.hh). - output_type save_tmp(clone(marker)); - save = save_tmp; + output = clone(marker); + save = clone(marker); } bool impl_is_stable() const @@ -312,15 +287,12 @@ void impl_re_loop() { - // FIXME: We can't use `save = clone(output)' directly here, - // because box's op=(const abstract::image<II>& rhs) would be - // called, which is empty (see oln/core/box.hh). - save.unbox() = clone(output); + save = clone(output); } oln_type_of(I1, concrete) get_output() { - return output.unbox(); + return output; } protected: @@ -336,8 +308,8 @@ mlc_check_method_impl(E, void, second_step, , ); } - box<oln_type_of(I1, concrete)> save; - box<oln_type_of(I1, concrete)> output; + oln_type_of(I1, concrete) save; + oln_type_of(I1, concrete) output; box<const I1> marker; box<const I2> mask; oln_type_of(I1, fwd_piter) fwd_p;
19 years, 3 months
1
0
0
0
Re: [Olena-patches] proto-1.0 276: Rewrite reconstruction classes.
by Damien Thivolle
Roland Levillain <roland(a)lrde.epita.fr> writes: >>>>>> "Damien" == Damien Thivolle <damien(a)lrde.epita.fr> writes: > > Damien>
https://svn/svn/oln/prototypes/proto-1.0/olena
> >> Index: ChangeLog >> from Damien Thivolle <damien(a)lrde.epita.fr> > >> Rewrite reconstruction classes. > >> * tests/morpho/tests/reconstruction: Now use builtin types. >> * oln/funobj/invert.hh: Add bool and unsigned char inversion. >> * oln/core/abstract/image_typeness.hh: Add rules (unsigned char, char >> and ntg::real_value) for greylevel_image. >> * oln/morpho/reconstruction.hh: Now support grey level images. >> * oln/morpho/local.hh: Add new functions for handling neighborhood. >> * oln/morpho/reconstruction_by_dilation.hh: Add grey level >> specialization and use new functions from local.hh. >> * oln/morpho/reconstruction_selfdual.hh: Likewise. >> * oln/morpho/reconstruction_by_erosion.hh: Likewise. >> * oln/canvas/reconstruction.hh: Now use mlc::is_a to check if the input >> images have a neighborhood. A bit of cleaning. > > [...] > >> Index: oln/funobj/invert.hh >> --- oln/funobj/invert.hh (revision 275) >> +++ oln/funobj/invert.hh (working copy) >> @@ -44,6 +44,16 @@ >> // (not: either -x or 1/x or min<->max or?) >> struct invert >> { >> + unsigned char operator()(const unsigned char& v) const >> + { >> + return 255 - v; > > What about UCHAR_MAX? I know char's size is fixed, but nevertheless. > > Yeah, you're right :) -- Damien Thivolle
19 years, 3 months
1
0
0
0
proto-1.0 276: Rewrite reconstruction classes.
by Damien Thivolle
https://svn/svn/oln/prototypes/proto-1.0/olena
Index: ChangeLog from Damien Thivolle <damien(a)lrde.epita.fr> Rewrite reconstruction classes. * tests/morpho/tests/reconstruction: Now use builtin types. * oln/funobj/invert.hh: Add bool and unsigned char inversion. * oln/core/abstract/image_typeness.hh: Add rules (unsigned char, char and ntg::real_value) for greylevel_image. * oln/morpho/reconstruction.hh: Now support grey level images. * oln/morpho/local.hh: Add new functions for handling neighborhood. * oln/morpho/reconstruction_by_dilation.hh: Add grey level specialization and use new functions from local.hh. * oln/morpho/reconstruction_selfdual.hh: Likewise. * oln/morpho/reconstruction_by_erosion.hh: Likewise. * oln/canvas/reconstruction.hh: Now use mlc::is_a to check if the input images have a neighborhood. A bit of cleaning. oln/canvas/reconstruction.hh | 53 +++-- oln/core/abstract/image_typeness.hh | 6 oln/funobj/invert.hh | 10 + oln/morpho/local.hh | 178 ++++++++++++++++++ oln/morpho/reconstruction.hh | 41 +++- oln/morpho/reconstruction_by_dilation.hh | 271 +++++++++++++++++++++------- oln/morpho/reconstruction_by_erosion.hh | 296 +++++++++++++++++++++++-------- oln/morpho/reconstruction_selfdual.hh | 94 +-------- tests/morpho/tests/reconstruction | 22 +- 9 files changed, 733 insertions(+), 238 deletions(-) Index: tests/morpho/tests/reconstruction --- tests/morpho/tests/reconstruction (revision 275) +++ tests/morpho/tests/reconstruction (working copy) @@ -20,16 +20,16 @@ bool check() { using namespace oln; - image2d<ntg::bin> marker; - image2d<ntg::bin> mask; - image_with_nbh<image2d<ntg::bin>, neighborhood2d> res_dil_hyb; - image_with_nbh<image2d<ntg::bin>, neighborhood2d> res_dil_seq; - image_with_nbh<image2d<ntg::bin>, neighborhood2d> res_dil_par; - 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; + image2d<bool> marker; + image2d<bool> mask; + image_with_nbh<image2d<bool>, neighborhood2d> res_dil_hyb; + image_with_nbh<image2d<bool>, neighborhood2d> res_dil_seq; + image_with_nbh<image2d<bool>, neighborhood2d> res_dil_par; + image_with_nbh<image2d<bool>, neighborhood2d> res_ero_hyb; + image_with_nbh<image2d<bool>, neighborhood2d> res_ero_seq; + image_with_nbh<image2d<bool>, neighborhood2d> res_ero_par; + image_with_nbh<image2d<bool>, neighborhood2d> res_selfdual; + image_with_nbh<image2d<bool>, neighborhood2d> res_selfdual_invert; utils::key::value_type data_key[16] = { 0xd1, 0x5c, 0x13, 0xd8, 0xe0, 0xa8, 0x58, 0x7d, @@ -56,7 +56,7 @@ morpho::tag::parallel(), morpho::tag::by_dilation()); - image2d<ntg::bin> marker_c(level::invert(marker)); + image2d<bool> marker_c(level::invert(marker)); res_ero_hyb = morpho::reconstruction(join(marker_c, neighb_c4()), Index: oln/funobj/invert.hh --- oln/funobj/invert.hh (revision 275) +++ oln/funobj/invert.hh (working copy) @@ -44,6 +44,16 @@ // (not: either -x or 1/x or min<->max or?) struct invert { + unsigned char operator()(const unsigned char& v) const + { + return 255 - v; + } + + bool operator()(const bool& v) const + { + return !v; + } + template <typename V> V operator()(const ntg::vect_value<V>& v) const { Index: oln/core/abstract/image_typeness.hh --- oln/core/abstract/image_typeness.hh (revision 275) +++ oln/core/abstract/image_typeness.hh (working copy) @@ -112,6 +112,12 @@ template <typename E> static tag_is<_label_tag> selector(ntg::enum_value<E>*); + template <typename E> + static tag_is<_greylevel_tag> selector(ntg::real_value<E>*); + + static tag_is<_greylevel_tag> selector(char*); + static tag_is<_greylevel_tag> selector(unsigned char*); + static tag_is<_binary_tag> selector(bool*); static tag_is<_binary_tag> selector(ntg::bin*); template <class b> Index: oln/morpho/reconstruction.hh --- oln/morpho/reconstruction.hh (revision 275) +++ oln/morpho/reconstruction.hh (working copy) @@ -42,12 +42,47 @@ // Generic implementation of reconstruction (routine). +// template<typename I1, typename I2, typename A, typename Op> +// oln_type_of(I1, concrete) +// reconstruction_(const abstract::image<I1>& marker, +// const abstract::image<I2>& mask) +// { +// mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + +// reconstruction<I1, I2, A, Op> tmp(marker, mask); +// // tmp.entering(); FIXME: something like that ? + +// tmp.run(); + +// // tmp.exiting(); FIXME: something like that ? +// return tmp.get_output(); +// } + template<typename I1, typename I2, typename A, typename Op> oln_type_of(I1, concrete) - reconstruction_(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) + reconstruction_(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + + binary_reconstruction<I1, I2, A, Op> tmp(marker, mask); + // tmp.entering(); FIXME: something like that ? + + tmp.run(); + + // tmp.exiting(); FIXME: something like that ? + return tmp.get_output(); + } + + + template <typename I1, typename I2, typename A, typename Op> + oln_type_of(I1, concrete) + reconstruction_(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) { - reconstruction<I1, I2, A, Op> tmp(marker, mask); + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + + greylevel_reconstruction<I1, I2, A, Op> tmp(marker, mask); // tmp.entering(); FIXME: something like that ? tmp.run(); Index: oln/morpho/local.hh --- oln/morpho/local.hh (revision 275) +++ oln/morpho/local.hh (working copy) @@ -62,6 +62,54 @@ } + /// Local image "inf-value" for erosion on sets - based on the + /// neighborhood points that have already been processed when + /// performing a forward scan. + + template <typename I> + oln_type_of(I, value) local_inf_value_fwd(const abstract::image<I>& input, + const oln_type_of(I, point)& p) + { + mlc_is_a(I, abstract::image_with_nbh)::ensure(); + mlc_is_a(I, abstract::not_binary_image)::ensure(); + + typedef oln_type_of(I, value) value_type; + typedef f_::accum_with_init<f_::inf_<value_type>, value_type> accum_type; + accum_type val(ntg_sup_val(value_type)); + + oln_type_of(I, niter) n(input); + for_all_n_of_p(n, p) + if (input.hold(n) and p.fwd_less(n)) + val(input[n]); + + return val; + } + + + /// Local image "inf-value" for erosion on sets - based on the + /// neighborhood points that have already been processed when + /// performing a forward scan. + + template <typename I> + oln_type_of(I, value) local_inf_value_bkd(const abstract::image<I>& input, + const oln_type_of(I, point)& p) + { + mlc_is_a(I, abstract::image_with_nbh)::ensure(); + mlc_is_a(I, abstract::not_binary_image)::ensure(); + + typedef oln_type_of(I, value) value_type; + typedef f_::accum_with_init<f_::inf_<value_type>, value_type> accum_type; + accum_type val(ntg_sup_val(value_type)); + + oln_type_of(I, niter) n(input); + for_all_n_of_p(n, p) + if (input.hold(n) and p.bkd_less(n)) + val(input[n]); + + return val; + } + + /// Local image "sup-value" for dilation on functions (based on the neighborhood). template <typename I> @@ -84,6 +132,54 @@ } + /// Local image "sup-value" for erosion on sets - based on the + /// neighborhood points that have already been processed when + /// performing a forward scan. + + template <typename I> + oln_type_of(I, value) local_sup_value_fwd(const abstract::image<I>& input, + const oln_type_of(I, point)& p) + { + mlc_is_a(I, abstract::image_with_nbh)::ensure(); + mlc_is_a(I, abstract::not_binary_image)::ensure(); + + typedef oln_type_of(I, value) value_type; + typedef f_::accum_with_init<f_::sup_<value_type>, value_type> accum_type; + accum_type val(ntg_inf_val(value_type)); + + oln_type_of(I, niter) n(input); + for_all_n_of_p(n, p) + if (input.hold(n) and p.fwd_less(n)) + val(input[n]); + + return val; + } + + + /// Local image "sup-value" for erosion on sets - based on the + /// neighborhood points that have already been processed when + /// performing a forward scan. + + template <typename I> + oln_type_of(I, value) local_sup_value_bkd(const abstract::image<I>& input, + const oln_type_of(I, point)& p) + { + mlc_is_a(I, abstract::image_with_nbh)::ensure(); + mlc_is_a(I, abstract::not_binary_image)::ensure(); + + typedef oln_type_of(I, value) value_type; + typedef f_::accum_with_init<f_::sup_<value_type>, value_type> accum_type; + accum_type val(ntg_inf_val(value_type)); + + oln_type_of(I, niter) n(input); + for_all_n_of_p(n, p) + if (input.hold(n) and p.bkd_less(n)) + val(input[n]); + + return val; + } + + /// Local image "and-value" for erosion on sets (based on the neighborhood). template <typename I> @@ -102,6 +198,47 @@ } + /// Local image "and-value" for erosion on sets - based on the + /// neighborhood points that have already been processed when + /// performing a forward scan. + + template <typename I> + oln_type_of(I, value) local_and_value_fwd(const abstract::image<I>& input, + const oln_type_of(I, point)& p) + { + mlc_is_a(I, abstract::image_with_nbh)::ensure(); + mlc_is_a(I, abstract::binary_image)::ensure(); + + oln_type_of(I, niter) n(input); + for_all_n_of_p(n, p) + if (input.hold(n) and p.fwd_less(n) and not input[n]) + return false; + + return true; + } + + + /// Local image "and-value" for erosion on sets - based on the + /// neighborhood points that have already been processed when + /// performing a backward scan. + + template <typename I> + oln_type_of(I, value) local_and_value_bkd(const abstract::image<I>& input, + const oln_type_of(I, point)& p) + { + mlc_is_a(I, abstract::image_with_nbh)::ensure(); + mlc_is_a(I, abstract::binary_image)::ensure(); + + oln_type_of(I, niter) n(input); + for_all_n_of_p(n, p) + if (input.hold(n) and p.bkd_less(n) and not input[n]) + return false; + + return true; + } + + + /// Local image "or-value" for dilation on sets (based on the neighborhood). template <typename I> @@ -120,6 +257,46 @@ } + /// Local image "or-value" for erosion on sets - based on the + /// neighborhood points that have already been processed when + /// performing a forward scan. + + template <typename I> + oln_type_of(I, value) local_or_value_fwd(const abstract::image<I>& input, + const oln_type_of(I, point)& p) + { + mlc_is_a(I, abstract::image_with_nbh)::ensure(); + mlc_is_a(I, abstract::binary_image)::ensure(); + + oln_type_of(I, niter) n(input); + for_all_n_of_p(n, p) + if (input.hold(n) and p.fwd_less(n) and input[n]) + return true; + + return false; + } + + + /// Local image "or-value" for erosion on sets - based on the + /// neighborhood points that have already been processed when + /// performing a backward scan. + + template <typename I> + oln_type_of(I, value) local_or_value_bkd(const abstract::image<I>& input, + const oln_type_of(I, point)& p) + { + mlc_is_a(I, abstract::image_with_nbh)::ensure(); + mlc_is_a(I, abstract::binary_image)::ensure(); + + oln_type_of(I, niter) n(input); + for_all_n_of_p(n, p) + if (input.hold(n) and p.bkd_less(n) and input[n]) + return true; + + return false; + } + + /// Image "inf-value" in a window for erosion on functions. @@ -207,5 +384,4 @@ } // end of namespace oln - #endif // ! OLENA_MORPHO_LOCAL_HH Index: oln/morpho/reconstruction_by_dilation.hh --- oln/morpho/reconstruction_by_dilation.hh (revision 275) +++ oln/morpho/reconstruction_by_dilation.hh (working copy) @@ -40,8 +40,10 @@ namespace impl { + // BINARY + template <typename I1, typename I2, typename A, typename E> - struct reconstruction_by_dilation + struct binary_reconstruction_by_dilation : public canvas::reconstruction<I1, I2, A, E> { typedef canvas::reconstruction<I1, I2, A, E> super_type; @@ -55,55 +57,196 @@ using super_type::p; - /// Local image "or-value" for dilation on sets - /// (based on the point and its backward neighborhood). + void impl_bkd_loop_body() + { + output[bkd_p] = mask[bkd_p] and + (output[bkd_p] or local_or_value_bkd(join(output, marker.nbh_get()), bkd_p)); + } - oln_type_of(I1, value) bkd_or() + void impl_fwd_loop_body() { - 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; + output[fwd_p] = mask[fwd_p] and + (output[fwd_p] or local_or_value_fwd(join(output, marker.nbh_get()), fwd_p)); + } - return false; + binary_reconstruction_by_dilation(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) : + super_type(marker, mask) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } + }; + + // Hybrid version + + template<typename I1, typename I2> + struct binary_reconstruction <I1, I2, tag::hybrid_type, tag::by_dilation_type> + : public binary_reconstruction_by_dilation<I1, I2, tag::hybrid_type, + binary_reconstruction<I1, I2, tag::hybrid_type, tag::by_dilation_type> > + { + typedef binary_reconstruction<I1, I2, tag::hybrid_type, + tag::by_dilation_type> self_type; + typedef binary_reconstruction_by_dilation<I1, I2, tag::hybrid_type, + self_type> super_type; + + using super_type::mask; + using super_type::marker; + using super_type::output; + using super_type::bkd_p; + using super_type::n; + using super_type::p; + using super_type::fifo; - /// Local image "or-value" for dilation on sets - /// (based on the point and its forward neighborhood). - oln_type_of(I1, value) fwd_or() + void impl_preconditions() const { - 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; + precondition(level::is_greater_or_equal(mask, marker)); + } - return false; + void impl_fifo_loop_body() + { + // output[n] < output[p] doesn't make sense with binary types. + if ((output[n] == false and output[p] == true) and (mask[n] != output[n])) + { + output[n] = output[p] and mask[n]; + fifo.push(n); + } } + bool impl_test_fifo_push() + { + return (output[n] == false and output[bkd_p] == true) and + (output[n] == false and mask[n] == true); + } + + + binary_reconstruction(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) : + super_type(marker, mask) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + } + + }; + + + // Sequential version + + template<typename I1, typename I2> + struct binary_reconstruction <I1, I2, tag::sequential_type, tag::by_dilation_type> + : public binary_reconstruction_by_dilation<I1, I2, tag::sequential_type, + binary_reconstruction<I1, I2, tag::sequential_type, + tag::by_dilation_type> > + { + typedef binary_reconstruction<I1, I2, tag::sequential_type, + tag::by_dilation_type> self_type; + typedef binary_reconstruction_by_dilation<I1, I2, tag::sequential_type, + self_type> super_type; + + using super_type::mask; + using super_type::marker; + + void impl_preconditions() const + { + precondition(level::is_greater_or_equal(mask, marker)); + } + + + binary_reconstruction(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) : + super_type(marker, mask) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + } + + }; + + + // Parallel version + + template <typename I1, typename I2> + struct binary_reconstruction<I1, I2, tag::parallel_type, tag::by_dilation_type> + : public canvas::reconstruction<I1, I2, tag::parallel_type, + binary_reconstruction<I1, I2, tag::parallel_type, tag::by_dilation_type> > + { + typedef binary_reconstruction<I1, I2, tag::parallel_type, + tag::by_dilation_type> self_type; + typedef canvas::reconstruction<I1, I2, tag::parallel_type, + self_type> super_type; + + using super_type::mask; + using super_type::marker; + using super_type::save; + using super_type::output; + using super_type::fwd_p; + + void impl_first_step() + { + output[fwd_p] = save[fwd_p] or + local_or_value(join(save, marker.nbh_get()), fwd_p); + } + + void impl_second_step() + { + output[fwd_p] = mask[fwd_p] and output[fwd_p]; + } + + void impl_preconditions() const + { + precondition(level::is_greater_or_equal(mask, marker)); + } + + binary_reconstruction(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) : + super_type(marker, mask) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + } + + }; + + + + // GREYLEVEL + + template <typename I1, typename I2, typename A, typename E> + struct greylevel_reconstruction_by_dilation + : public canvas::reconstruction<I1, I2, A, E> + { + typedef canvas::reconstruction<I1, I2, A, E> super_type; + typedef oln_type_of(I1, value) value_type; + typedef f_::accum_with_init<f_::sup_<value_type>, value_type> accum_type; + + using super_type::mask; + using super_type::marker; + using super_type::output; + using super_type::bkd_p; + using super_type::fwd_p; + using super_type::n; + using super_type::p; + void impl_bkd_loop_body() { - // FIXME: The call to value_box<>::value is needed to have - // f_max_alt compile. Try to get rid of it. - output[bkd_p] = f_min_alt(mask[bkd_p].value(), bkd_or()); + value_type nbh_max = + f_max_alt(output[bkd_p].value(), + local_sup_value_bkd(join(output, marker.nbh_get()), bkd_p)); + output[bkd_p] = f_min_alt(mask[bkd_p].value(), nbh_max); } void impl_fwd_loop_body() { - // FIXME: The call to value_box<>::value is needed to have - // f_max_alt compile. Try to get rid of it. - output[fwd_p] = f_min_alt(mask[fwd_p].value(), fwd_or()); + value_type nbh_max = + f_max_alt(output[fwd_p].value(), + local_sup_value_fwd(join(output, marker.nbh_get()), fwd_p)); + output[fwd_p] = f_min_alt(mask[fwd_p].value(), nbh_max); } - reconstruction_by_dilation(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) : + greylevel_reconstruction_by_dilation(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) : super_type(marker, mask) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } }; @@ -111,13 +254,13 @@ // Hybrid version template<typename I1, typename I2> - struct reconstruction <I1, I2, tag::hybrid_type, tag::by_dilation_type> - : public reconstruction_by_dilation<I1, I2, tag::hybrid_type, - reconstruction<I1, I2, tag::hybrid_type, tag::by_dilation_type> > + struct greylevel_reconstruction <I1, I2, tag::hybrid_type, tag::by_dilation_type> + : public greylevel_reconstruction_by_dilation<I1, I2, tag::hybrid_type, + greylevel_reconstruction<I1, I2, tag::hybrid_type, tag::by_dilation_type> > { - typedef reconstruction<I1, I2, tag::hybrid_type, + typedef greylevel_reconstruction<I1, I2, tag::hybrid_type, tag::by_dilation_type> self_type; - typedef reconstruction_by_dilation<I1, I2, tag::hybrid_type, + typedef greylevel_reconstruction_by_dilation<I1, I2, tag::hybrid_type, self_type> super_type; using super_type::mask; @@ -138,23 +281,22 @@ { if ((output[n] < output[p]) and (mask[n] != output[n])) { - // FIXME: The calls to value_box<>::value are needed to - // have f_min_alt compile. Try to get rid of it. - output[n] = f_max_alt(output[p].value(), mask[n].value()); + output[n] = f_min_alt(output[p].value(), mask[n].value()); fifo.push(n); } } bool impl_test_fifo_push() { - return output[n] < output[bkd_p] and output[n] < mask[n]; + return (output[n] < output[bkd_p]) and (output[n] < mask[n]); } - reconstruction(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) : + greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) : super_type(marker, mask) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } }; @@ -163,14 +305,14 @@ // Sequential version template<typename I1, typename I2> - struct reconstruction <I1, I2, tag::sequential_type, tag::by_dilation_type> - : public reconstruction_by_dilation<I1, I2, tag::sequential_type, - reconstruction<I1, I2, tag::sequential_type, + struct greylevel_reconstruction <I1, I2, tag::sequential_type, tag::by_dilation_type> + : public greylevel_reconstruction_by_dilation<I1, I2, tag::sequential_type, + greylevel_reconstruction<I1, I2, tag::sequential_type, tag::by_dilation_type> > { - typedef reconstruction<I1, I2, tag::sequential_type, + typedef greylevel_reconstruction<I1, I2, tag::sequential_type, tag::by_dilation_type> self_type; - typedef reconstruction_by_dilation<I1, I2, tag::sequential_type, + typedef greylevel_reconstruction_by_dilation<I1, I2, tag::sequential_type, self_type> super_type; using super_type::mask; @@ -182,10 +324,11 @@ } - reconstruction(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) : + greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) : super_type(marker, mask) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } }; @@ -194,14 +337,17 @@ // Parallel version template <typename I1, typename I2> - struct reconstruction<I1, I2, tag::parallel_type, tag::by_dilation_type> + struct greylevel_reconstruction<I1, I2, tag::parallel_type, tag::by_dilation_type> : public canvas::reconstruction<I1, I2, tag::parallel_type, - reconstruction<I1, I2, tag::parallel_type, tag::by_dilation_type> > + greylevel_reconstruction<I1, I2, tag::parallel_type, tag::by_dilation_type> > { - typedef reconstruction<I1, I2, tag::parallel_type, + typedef greylevel_reconstruction<I1, I2, tag::parallel_type, tag::by_dilation_type> self_type; typedef canvas::reconstruction<I1, I2, tag::parallel_type, self_type> super_type; + typedef oln_type_of(I1, value) value_type; + typedef f_::accum_with_init<f_::sup_<value_type>, value_type> accum_type; + using super_type::mask; using super_type::marker; @@ -210,31 +356,32 @@ using super_type::fwd_p; - void impl_preconditions() const + void impl_first_step() { - precondition(level::is_greater_or_equal(mask, marker)); + output[fwd_p] = + f_max_alt(output[fwd_p].value(), + local_sup_value(join(output, marker.nbh_get()), fwd_p)); } - void impl_fwd_loop_body() + void impl_second_step() { - // dilation step - if (not output[fwd_p]) - output[fwd_p] = local_or_value(join(save, marker.nbh_get()), - fwd_p); + output[fwd_p] = f_min_alt(mask[fwd_p].value(), output[fwd_p].value()); + } - // minimum between mask and output - output[fwd_p] = f_min_alt(output[fwd_p].value(), mask[fwd_p].value()); + void impl_preconditions() const + { + precondition(level::is_greater_or_equal(mask, marker)); } - reconstruction(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) : + greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) : super_type(marker, mask) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } }; - } } Index: oln/morpho/reconstruction_selfdual.hh --- oln/morpho/reconstruction_selfdual.hh (revision 275) +++ oln/morpho/reconstruction_selfdual.hh (working copy) @@ -34,7 +34,6 @@ # include <oln/funobj/arith.hh> -//FIXME: Adapt ... namespace oln { @@ -44,20 +43,23 @@ namespace impl { + // BINARY + template<typename I1, typename I2> - struct reconstruction <I1, I2, tag::selfdual_type, tag::none_type> + struct binary_reconstruction <I1, I2, tag::selfdual_type, tag::none_type> : public canvas::reconstruction<I1, I2, tag::hybrid_type, - reconstruction<I1, I2, tag::selfdual_type, tag::none_type> > + binary_reconstruction<I1, I2, tag::selfdual_type, tag::none_type> > { - typedef reconstruction<I1, I2, tag::selfdual_type, + typedef binary_reconstruction<I1, I2, tag::selfdual_type, tag::none_type> self_type; typedef canvas::reconstruction<I1, I2, tag::hybrid_type, self_type> super_type; - reconstruction(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) : + binary_reconstruction(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) : super_type(marker, mask) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } using super_type::mask; @@ -70,87 +72,25 @@ 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 (output[bkd_p] < mask[bkd_p]) - output[bkd_p] = f_min_alt(bkd_or(), mask[bkd_p].value()); + output[bkd_p] = mask[bkd_p] and + (output[bkd_p] or local_or_value_bkd(join(output, marker.nbh_get()), bkd_p)); else - output[bkd_p] = f_max_alt(bkd_and(), mask[bkd_p].value()); + output[bkd_p] = mask[bkd_p] or + (output[bkd_p] and local_and_value_bkd(join(output, marker.nbh_get()), bkd_p)); } void impl_fwd_loop_body() { - // FIXME: Shouldn't be .value() ! if (output[fwd_p] < mask[fwd_p]) - output[fwd_p] = f_min_alt(fwd_or(), mask[fwd_p].value()); + output[fwd_p] = mask[fwd_p] and + (output[fwd_p] or local_or_value_fwd(join(output, marker.nbh_get()), fwd_p)); else - output[fwd_p] = f_max_alt(fwd_and(), mask[fwd_p].value()); + output[fwd_p] = mask[fwd_p] or + (output[fwd_p] and local_and_value_fwd(join(output, marker.nbh_get()), fwd_p)); + } void impl_fifo_loop_body() Index: oln/morpho/reconstruction_by_erosion.hh --- oln/morpho/reconstruction_by_erosion.hh (revision 275) +++ oln/morpho/reconstruction_by_erosion.hh (working copy) @@ -40,8 +40,10 @@ namespace impl { + // BINARY + template <typename I1, typename I2, typename A, typename E> - struct reconstruction_by_erosion + struct binary_reconstruction_by_erosion : public canvas::reconstruction<I1, I2, A, E> { typedef canvas::reconstruction<I1, I2, A, E> super_type; @@ -54,71 +56,217 @@ using super_type::n; using super_type::p; + void impl_bkd_loop_body() + { + output[bkd_p] = mask[bkd_p] or + (output[bkd_p] and local_and_value_bkd(join(output, marker.nbh_get()), bkd_p)); + } + + void impl_fwd_loop_body() + { + output[fwd_p] = mask[fwd_p] or + (output[fwd_p] and local_and_value_fwd(join(output, marker.nbh_get()), fwd_p)); + } + + binary_reconstruction_by_erosion(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) : + super_type(marker, mask) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + } - /// Local image "and-value" for erosion on sets - /// (based on the point and its backward neighborhood). + }; - oln_type_of(I1, value) bkd_and() + // Hybrid version + + template<typename I1, typename I2> + struct binary_reconstruction <I1, I2, tag::hybrid_type, tag::by_erosion_type> + : public binary_reconstruction_by_erosion<I1, I2, tag::hybrid_type, + binary_reconstruction<I1, I2, tag::hybrid_type, tag::by_erosion_type> > { - 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; + typedef binary_reconstruction<I1, I2, tag::hybrid_type, + tag::by_erosion_type> self_type; + typedef binary_reconstruction_by_erosion<I1, I2, tag::hybrid_type, + self_type> super_type; - return true; + using super_type::mask; + using super_type::marker; + using super_type::output; + using super_type::bkd_p; + using super_type::n; + using super_type::p; + using super_type::fifo; + + + void impl_preconditions() const + { + precondition(level::is_lower_or_equal(mask, marker)); } + void impl_fifo_loop_body() + { + // output[n] > output[p] doesn't make sense with binary types... + if ((output[n] == true and output[p] == false) and (mask[n] != output[n])) + { + output[n] = output[p] and mask[n]; + fifo.push(n); + } + } - /// Local image "and-value" for erosion on sets - /// (based on the point and its forward neighborhood). + bool impl_test_fifo_push() + { + return (output[n] == true and output[bkd_p] == false)and + (output[n] == true and mask[n] == false); + } + + + binary_reconstruction(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) : + super_type(marker, mask) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + } + + }; - oln_type_of(I1, value) fwd_and() + + // Sequential version + + template<typename I1, typename I2> + struct binary_reconstruction <I1, I2, tag::sequential_type, tag::by_erosion_type> + : public binary_reconstruction_by_erosion<I1, I2, tag::sequential_type, + binary_reconstruction<I1, I2, tag::sequential_type, + tag::by_erosion_type> > { - 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; + typedef binary_reconstruction<I1, I2, tag::sequential_type, + tag::by_erosion_type> self_type; + typedef binary_reconstruction_by_erosion<I1, I2, tag::sequential_type, + self_type> super_type; - return true; + using super_type::mask; + using super_type::marker; + + void impl_preconditions() const + { + precondition(level::is_lower_or_equal(mask, marker)); } + + binary_reconstruction(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) : + super_type(marker, mask) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + } + + }; + + + // Parallel version + + template <typename I1, typename I2> + struct binary_reconstruction<I1, I2, tag::parallel_type, tag::by_erosion_type> + : public canvas::reconstruction<I1, I2, tag::parallel_type, + binary_reconstruction<I1, I2, tag::parallel_type, tag::by_erosion_type> > + { + typedef binary_reconstruction<I1, I2, tag::parallel_type, + tag::by_erosion_type> self_type; + typedef canvas::reconstruction<I1, I2, tag::parallel_type, + self_type> super_type; + + using super_type::mask; + using super_type::marker; + using super_type::save; + using super_type::output; + using super_type::fwd_p; + + void impl_first_step() + { + output[fwd_p] = save[fwd_p] and + local_and_value(join(save, marker.nbh_get()), fwd_p); + } + + void impl_second_step() + { + output[fwd_p] = mask[fwd_p] or output[fwd_p]; + } + + void impl_preconditions() const + { + precondition(level::is_lower_or_equal(mask, marker)); + } + + binary_reconstruction(const abstract::binary_image<I1>& marker, + const abstract::binary_image<I2>& mask) : + super_type(marker, mask) + { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + } + + }; + + + + + + + // GREYLEVEL + + + + + template <typename I1, typename I2, typename A, typename E> + struct greylevel_reconstruction_by_erosion + : public canvas::reconstruction<I1, I2, A, E> + { + typedef canvas::reconstruction<I1, I2, A, E> super_type; + typedef oln_type_of(I1, value) value_type; + typedef f_::accum_with_init<f_::inf_<value_type>, value_type> accum_type; + + using super_type::mask; + using super_type::marker; + using super_type::output; + using super_type::bkd_p; + using super_type::fwd_p; + using super_type::n; + using super_type::p; + void impl_bkd_loop_body() { - // FIXME: The call to value_box<>::value is needed to have - // f_max_alt compile. Try to get rid of it. - output[bkd_p] = f_max_alt(mask[bkd_p].value(), bkd_and()); + value_type nbh_min = + f_min_alt(output[bkd_p].value(), + local_inf_value_bkd(join(output, marker.nbh_get()), bkd_p)); + output[bkd_p] = f_max_alt(mask[bkd_p].value(), nbh_min); } void impl_fwd_loop_body() { - // FIXME: The call to value_box<>::value is needed to have - // f_max_alt compile. Try to get rid of it. - output[fwd_p] = f_max_alt(mask[fwd_p].value(), fwd_and()); + value_type nbh_min = + f_min_alt(output[fwd_p].value(), + local_inf_value_fwd(join(output, marker.nbh_get()), fwd_p)); + output[fwd_p] = f_max_alt(mask[fwd_p].value(), nbh_min); } - reconstruction_by_erosion(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) : + + greylevel_reconstruction_by_erosion(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) : super_type(marker, mask) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } }; - // Hybrid version template<typename I1, typename I2> - struct reconstruction <I1, I2, tag::hybrid_type, tag::by_erosion_type> - : public reconstruction_by_erosion<I1, I2, tag::hybrid_type, - reconstruction<I1, I2, tag::hybrid_type, tag::by_erosion_type> > + struct greylevel_reconstruction <I1, I2, tag::hybrid_type, tag::by_erosion_type> + : public greylevel_reconstruction_by_erosion<I1, I2, tag::hybrid_type, + greylevel_reconstruction<I1, I2, tag::hybrid_type, tag::by_erosion_type> > { - typedef reconstruction<I1, I2, tag::hybrid_type, + typedef greylevel_reconstruction<I1, I2, tag::hybrid_type, tag::by_erosion_type> self_type; - typedef reconstruction_by_erosion<I1, I2, tag::hybrid_type, + typedef greylevel_reconstruction_by_erosion<I1, I2, tag::hybrid_type, self_type> super_type; using super_type::mask; @@ -130,31 +278,31 @@ using super_type::fifo; + void impl_preconditions() const + { + precondition(level::is_lower_or_equal(mask, marker)); + } + void impl_fifo_loop_body() { if ((output[n] > output[p]) and (mask[n] != output[n])) { - // FIXME: The calls to value_box<>::value are needed to - // have f_min_alt compile. Try to get rid of it. - output[n] = f_min_alt(output[p].value(), mask[n].value()); + output[n] = f_max_alt(output[p].value(), mask[n].value()); fifo.push(n); } } - void impl_preconditions() const - { - precondition(level::is_greater_or_equal(marker, mask)); - } - bool impl_test_fifo_push() { - return output[n] > output[bkd_p] and output[n] > mask[n]; + return (output[n] > output[bkd_p]) and (output[n] > mask[n]); } - reconstruction(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) : + + greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) : super_type(marker, mask) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } }; @@ -163,42 +311,49 @@ // Sequential version template<typename I1, typename I2> - struct reconstruction <I1, I2, tag::sequential_type, tag::by_erosion_type> - : public reconstruction_by_erosion<I1, I2, tag::sequential_type, - reconstruction<I1, I2, tag::sequential_type, + struct greylevel_reconstruction <I1, I2, tag::sequential_type, tag::by_erosion_type> + : public greylevel_reconstruction_by_erosion<I1, I2, tag::sequential_type, + greylevel_reconstruction<I1, I2, tag::sequential_type, tag::by_erosion_type> > { - typedef reconstruction<I1, I2, tag::sequential_type, + typedef greylevel_reconstruction<I1, I2, tag::sequential_type, tag::by_erosion_type> self_type; - typedef reconstruction_by_erosion<I1, I2, tag::sequential_type, + typedef greylevel_reconstruction_by_erosion<I1, I2, tag::sequential_type, self_type> super_type; + using super_type::mask; using super_type::marker; void impl_preconditions() const { - precondition(level::is_greater_or_equal(marker, mask)); + precondition(level::is_lower_or_equal(mask, marker)); } - reconstruction(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) : + + greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) : super_type(marker, mask) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } + }; // Parallel version template <typename I1, typename I2> - struct reconstruction<I1, I2, tag::parallel_type, tag::by_erosion_type> + struct greylevel_reconstruction<I1, I2, tag::parallel_type, tag::by_erosion_type> : public canvas::reconstruction<I1, I2, tag::parallel_type, - reconstruction<I1, I2, tag::parallel_type, tag::by_erosion_type> > + greylevel_reconstruction<I1, I2, tag::parallel_type, tag::by_erosion_type> > { - typedef reconstruction<I1, I2, tag::parallel_type, + typedef greylevel_reconstruction<I1, I2, tag::parallel_type, tag::by_erosion_type> self_type; typedef canvas::reconstruction<I1, I2, tag::parallel_type, self_type> super_type; + typedef oln_type_of(I1, value) value_type; + typedef f_::accum_with_init<f_::inf_<value_type>, value_type> accum_type; + using super_type::mask; using super_type::marker; @@ -206,31 +361,34 @@ using super_type::output; using super_type::fwd_p; - - void impl_preconditions() const + void impl_first_step() { - precondition(level::is_greater_or_equal(marker, mask)); + output[fwd_p] = + f_min_alt(output[fwd_p].value(), + local_inf_value(join(output, marker.nbh_get()), fwd_p)); } - void impl_fwd_loop_body() + void impl_second_step() { - // erosion step - if (output[fwd_p]) - output[fwd_p] = local_and_value(join(save, marker.nbh_get()), - fwd_p); + output[fwd_p] = f_max_alt(mask[fwd_p].value(), output[fwd_p].value()); + } - // maximum between mask and output - output[fwd_p] = f_max_alt(output[fwd_p].value(), mask[fwd_p].value()); + void impl_preconditions() const + { + precondition(level::is_lower_or_equal(mask, marker)); } - reconstruction(const abstract::image_with_nbh<I1>& marker, - const abstract::image<I2>& mask) : + greylevel_reconstruction(const abstract::greylevel_image<I1>& marker, + const abstract::greylevel_image<I2>& mask) : super_type(marker, mask) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } }; + + } } Index: oln/canvas/reconstruction.hh --- oln/canvas/reconstruction.hh (revision 275) +++ oln/canvas/reconstruction.hh (working copy) @@ -43,7 +43,10 @@ namespace impl { template <typename T, typename A, typename I1, typename I2> - struct reconstruction {}; + struct binary_reconstruction {}; + + template <typename T, typename A, typename I1, typename I2> + struct greylevel_reconstruction {}; } @@ -56,6 +59,8 @@ template <typename I1, typename I2, typename A, typename E> struct reconstruction; + + // HYBRID template <typename I1, typename I2, typename E> struct reconstruction<I1, I2, morpho::tag::hybrid_type, E> : public mlc::any<E> @@ -146,7 +151,7 @@ protected: - reconstruction(const abstract::image_with_nbh<I1>& marker, + reconstruction(const abstract::image<I1>& marker, const abstract::image<I2>& mask) : marker(marker.exact()), mask(mask.exact()), @@ -158,6 +163,7 @@ ~reconstruction() { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); mlc_check_method_impl(E, bool, test_fifo_push, , ); mlc_check_method_impl(E, void, preconditions, , const); mlc_check_method_impl(E, void, bkd_loop_body, , ); @@ -182,6 +188,8 @@ + + // SEQUENTIAL template <typename I1, typename I2, typename E> struct reconstruction<I1, I2, morpho::tag::sequential_type, E> : public back_and_forth_until_convergence<I1, E> @@ -228,13 +236,14 @@ protected: - reconstruction(const abstract::image_with_nbh<I1>& marker, + reconstruction(const abstract::image<I1>& marker, const abstract::image<I2>& mask) : super_type(marker), marker(marker.exact()), mask(mask.exact()), n(marker) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); } box<oln_type_of(I1, concrete)> save; @@ -248,9 +257,10 @@ + // PARALLEL template <typename I1, typename I2, typename E> struct reconstruction<I1, I2, morpho::tag::parallel_type, E> : - public forth_until_convergence<I1, E> + public until_convergence<E> { typedef forth_until_convergence<I1, E> super_type; typedef oln_type_of(I1, neighb) nbh_type; @@ -259,9 +269,24 @@ // Abstract methods. - void fwd_loop_body() + void first_step() { - this->exact().impl_fwd_loop_body(); + this->exact().impl_first_step(); + } + + void second_step() + { + this->exact().impl_second_step(); + } + + + void impl_loop_body() + { + for_all_p(fwd_p) + first_step(); + + for_all_p(fwd_p) + second_step(); } // Concrete methods. @@ -278,10 +303,8 @@ // called, which is empty (see oln/core/box.hh). output_type save_tmp(clone(marker)); save = save_tmp; - } - bool impl_is_stable() const { return level::is_equal(save, output); @@ -302,26 +325,26 @@ protected: - reconstruction(const abstract::image_with_nbh<I1>& marker, + reconstruction(const abstract::image<I1>& marker, const abstract::image<I2>& mask) : - super_type(marker), marker(marker.exact()), - mask(mask.exact()) + mask(mask.exact()), + fwd_p(marker.size()) { + mlc_is_a(I1, abstract::image_with_nbh)::ensure(); + mlc_check_method_impl(E, void, first_step, , ); + mlc_check_method_impl(E, void, second_step, , ); } box<oln_type_of(I1, concrete)> save; box<oln_type_of(I1, concrete)> output; box<const I1> marker; box<const I2> mask; - + oln_type_of(I1, fwd_piter) fwd_p; }; - } - } - #endif // ! OLENA_CANVAS_RECONSTRUCTION_HH
19 years, 3 months
2
1
0
0
proto-1.0 275: Update the Vcs extension to Vcs 0.4.
by Nicolas Pouillard
https://svn.lrde.epita.fr/svn/oln/prototypes/proto-1.0
Index: ChangeLog from Nicolas Pouillard <ertai(a)lrde.epita.fr> Update the Vcs extension to Vcs 0.4. * vcs/oln.rb: Add the protocol version and the default commit. oln.rb | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-) Index: vcs/oln.rb --- vcs/oln.rb (revision 274) +++ vcs/oln.rb (working copy) @@ -1,12 +1,17 @@ class Vcs + # See
http://rubyforge.org/projects/vcs
+ # and
http://vcs.rubyforge.org
- def oln_commit! ( *args ) + protocol_version '0.1' + + def olena_commit! ( *args ) common_commit!("proto-1.0 <%= rev %>: <%= title %>", *args) do |subject| mail!(:to => ['olena-patches(a)lrde.epita.fr'], :subject => subject) end end - alias_command :olnci, :oln_commit + alias_command :olnci, :olena_commit + default_commit :olena_commit end # class Vcs
19 years, 3 months
1
0
0
0
← Newer
1
Older →
Jump to page:
1
Results per page:
10
25
50
100
200