
Je ne suis pas sûr des définitions de hit_or_miss_closing et de hit_or_miss_opening_bg (Soille est assez laconique là-dessus). ChangeLog | 11 ++ oln/morpho/hit_or_miss.hh | 168 ++++++++++++++++++++++++++++++++- tests/morpho/tests/hit_or_miss_closing | 43 ++++++++ tests/morpho/tests/hit_or_miss_opening | 43 ++++++++ 4 files changed, 264 insertions(+), 1 deletion(-) Index: olena/ChangeLog from Roland Levillain <roland@lrde.epita.fr> Add hit-or-miss opening/closing and hit-or-miss opening/closing of the background. * oln/morpho/hit_or_miss.hh: More documentation. (hit_or_miss_opening, hit_or_miss_opening_bg) (hit_or_miss_closing, hit_or_miss_closing_bg): New. * tests/morpho/tests/hit_or_miss_opening, * tests/morpho/tests/hit_or_miss_closing: New tests. 2005-07-08 Roland Levillain <roland@lrde.epita.fr> Index: olena/tests/morpho/tests/hit_or_miss_closing --- olena/tests/morpho/tests/hit_or_miss_closing (révision 0) +++ olena/tests/morpho/tests/hit_or_miss_closing (révision 0) @@ -0,0 +1,43 @@ + // -*- C++ -*- +#include "data.hh" +#include <oln/utils/md5.hh> + +#include <ntg/bin.hh> +#include <oln/io/read_image.hh> +#include <oln/basics2d.hh> +#include <oln/morpho/hit_or_miss.hh> + +using namespace oln; + +bool check() +{ + utils::key::value_type data_key_hom_closing[16] = + { 0x9d, 0x9d, 0xbb, 0xd7, 0x6b, 0x5, 0x38, 0x29, + 0x69, 0x6e, 0x30, 0xd4, 0x30, 0x99, 0x13, 0x29 }; + utils::key key_hom_closing(data_key_hom_closing); + + utils::key::value_type data_key_hom_closing_bg[16] = + { 0xfa, 0x7, 0x26, 0x34, 0x16, 0x36, 0xc, 0xf4, + 0x5e, 0x19, 0x53, 0xa2, 0x89, 0x1e, 0xdb, 0xae }; + utils::key key_hom_closing_bg(data_key_hom_closing_bg); + + image2d<ntg::bin> ima; + ima = io::read(rdata("object.pbm")); + + oln::window2d win1; + win1 + .add(-3,-2).add(-3,-1).add(-3,0).add(-3,1).add(-3,2) + .add(-2,-1).add(-2,0).add(-2,1) + .add(-1,0); + oln::window2d win2 = -win1; + + if (utils::md5(morpho::hit_or_miss_closing(ima, win1, win2)) != + key_hom_closing) + return true; + + if (utils::md5(morpho::hit_or_miss_closing_bg(ima, win1, win2)) != + key_hom_closing_bg) + return true; + + return false; +} Index: olena/tests/morpho/tests/hit_or_miss_opening --- olena/tests/morpho/tests/hit_or_miss_opening (révision 0) +++ olena/tests/morpho/tests/hit_or_miss_opening (révision 0) @@ -0,0 +1,43 @@ + // -*- C++ -*- +#include "data.hh" +#include <oln/utils/md5.hh> + +#include <ntg/bin.hh> +#include <oln/io/read_image.hh> +#include <oln/basics2d.hh> +#include <oln/morpho/hit_or_miss.hh> + +using namespace oln; + +bool check() +{ + utils::key::value_type data_key_hom_opening[16] = + { 0x90, 0xda, 0x98, 0x5a, 0xef, 0x2e, 0x8d, 0x54, + 0xa5, 0x6, 0xd, 0x7a, 0x6f, 0x63, 0x55, 0x7 }; + utils::key key_hom_opening(data_key_hom_opening); + + utils::key::value_type data_key_hom_opening_bg[16] = + { 0xd6, 0x45, 0x11, 0xed, 0xdd, 0xf, 0x42, 0x59, + 0x95, 0x57, 0x4, 0x66, 0x59, 0x97, 0x6c, 0x8d }; + utils::key key_hom_opening_bg(data_key_hom_opening_bg); + + image2d<ntg::bin> ima; + ima = io::read(rdata("object.pbm")); + + oln::window2d win1; + win1 + .add(-3,-2).add(-3,-1).add(-3,0).add(-3,1).add(-3,2) + .add(-2,-1).add(-2,0).add(-2,1) + .add(-1,0); + oln::window2d win2 = -win1; + + if (utils::md5(morpho::hit_or_miss_opening(ima, win1, win2)) != + key_hom_opening) + return true; + + if (utils::md5(morpho::hit_or_miss_opening_bg(ima, win1, win2)) != + key_hom_opening_bg) + return true; + + return false; +} Index: olena/oln/morpho/hit_or_miss.hh --- olena/oln/morpho/hit_or_miss.hh (révision 237) +++ olena/oln/morpho/hit_or_miss.hh (copie de travail) @@ -32,9 +32,12 @@ # include <oln/utils/record.hh> # include <oln/morpho/erosion.hh> +# include <oln/morpho/dilation.hh> # include <oln/level/arith.hh> # include <oln/level/invert.hh> +// FIXME: More documentation (in particular, code snippets). See Olena +// 0.10's doc. namespace oln { @@ -83,7 +86,17 @@ } // end of namespace oln::morpho::impl - /// Generic hit-or-miss transform (facade). + /*! \brief Preform a hit-or-miss transform (generic facade) + + REF: Soille, 2nd ed., p.140. + + \arg \c I exact type of the input image. + \arg \c W1 exact type of the first structuring element. + \arg \c W2 exact type of the second structuring element. + + \param input image to process. + \param win1 first structuring element. + \param win2 second structuring element. */ template<class I, class W1, class W2> oln_type_of(I, concrete) hit_or_miss(const abstract::image<I>& input, @@ -101,6 +114,159 @@ return output; } + + /*! \brief Perform an hit-or-miss opening. + + Compute the hit-or-miss opening of input by the composite + structuring element (win1, win2). + + REF: Soille, 2nd ed., p.149. + + By definition \a win1 and \a win2 must have the same origin, + and need to be disjoint. This algorithm has been extended to + every data types (althought it is not increasing). Beware the + result depends upon the image data type if it is not binary. + + \arg \c I Exact type of the input image. + \arg \c W1 Exact type of the first structuring element. + \arg \c W2 Exact type of the second structuring element. + + \param input image to process. + \param win1 first structuring element. + \param win2 second structuring element. */ + template<class I, class W1, class W2> + oln_type_of(I, concrete) + hit_or_miss_opening(const abstract::image<I>& input, + const abstract::window<W1>& win1, + const abstract::window<W2>& win2) + { + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W1, grid)>::ensure(); + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W2, grid)>::ensure(); + entering("morpho::hit_or_miss_opening"); + + oln_type_of(I, concrete) output("output"); + output = dilation(hit_or_miss(input, win1, win2), -win1); + + exiting("morpho::hit_or_miss_opening"); + return output; + } + + /*! \brief Perform an hit-or-miss opening of background. + + Compute the hit-or-miss opening of the background of input by + the composite structuring element (win1, win2). + + REF: Soille, 2nd ed., p.149. + + By definition win1 and win2 must have the same origin, and + need to be disjoint. This algorithm has been extended to + every data types (although it is not increasing). Beware the + result depends upon the image data type if it is not bin. + + \arg \c I exact type of the input image. + \arg \c W1 exact type of the first structuring element. + \arg \c W2 exact type of the second structuring element. + + \param input image to process. + \param win1 first structuring element. + \param win2 second structuring element. */ + template<class I, class W1, class W2> + oln_type_of(I, concrete) + hit_or_miss_opening_bg(const abstract::image<I>& input, + const abstract::window<W1>& win1, + const abstract::window<W2>& win2) + { + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W1, grid)>::ensure(); + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W2, grid)>::ensure(); + entering("morpho::hit_or_miss_opening_bg"); + + oln_type_of(I, concrete) output("output"); + output = dilation(hit_or_miss(input, win1, win2), -win2); + + exiting("morpho::hit_or_miss_opening_bg"); + return output; + } + + /*! \brief Perform an hit-or-miss closing. + + Compute the hit-or-miss closing of input by the composite + structuring element (win1, win2). This is the dual + transformation of hit-or-miss opening with respect to set + complementation. + + REF: Soille, 2nd ed., p.149. + + By definition \a win1 and \a win2 must have the same origin, + and need to be disjoint. This algorithm has been extended to + every data types (althought it is not increasing). Beware the + result depends upon the image data type if it is not binary. + + \arg \c I Exact type of the input image. + \arg \c W1 Exact type of the first structuring element. + \arg \c W2 Exact type of the second structuring element. + + \param input image to process. + \param win1 first structuring element. + \param win2 second structuring element. */ + template<class I, class W1, class W2> + oln_type_of(I, concrete) + hit_or_miss_closing(const abstract::image<I>& input, + const abstract::window<W1>& win1, + const abstract::window<W2>& win2) + { + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W1, grid)>::ensure(); + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W2, grid)>::ensure(); + entering("morpho::hit_or_miss_closing"); + + oln_type_of(I, concrete) output("output"); + // FIXME: Is this correct? Soille doesn't detail the definition + // of the hit-or-miss closing in his book. + output = hit_or_miss_opening(level::invert(input), win1, win2); + + exiting("morpho::hit_or_miss_closing"); + return output; + } + + /*! \brief Perform an hit-or-miss closing of the background. + + Compute the hit-or-miss closing of the background of input by + the composite structuring element (win1, win2). This is the + dual transformation of hit-or-miss opening of the background + with respect to set complementation. + + REF: Soille, 2nd ed., p.149. + + By definition \a win1 and \a win2 must have the same origin, + and need to be disjoint. This algorithm has been extended to + every data types (althought it is not increasing). Beware the + result depends upon the image data type if it is not binary. + + \arg \c I Exact type of the input image. + \arg \c W1 Exact type of the first structuring element. + \arg \c W2 Exact type of the second structuring element. + + \param input image to process. + \param win1 first structuring element. + \param win2 second structuring element. */ + template<class I, class W1, class W2> + oln_type_of(I, concrete) + hit_or_miss_closing_bg(const abstract::image<I>& input, + const abstract::window<W1>& win1, + const abstract::window<W2>& win2) + { + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W1, grid)>::ensure(); + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W2, grid)>::ensure(); + entering("morpho::hit_or_miss_closing_bg"); + + oln_type_of(I, concrete) output("output"); + // FIXME: Is this correct? Soille doesn't detail the definition + // of the hit-or-miss closing of the background in his book. + output = hit_or_miss_opening_bg(level::invert(input), win1, win2); + + exiting("morpho::hit_or_miss_closing_bg"); + return output; + } + } // end of namespace oln::morpho } // end of namespace oln