¡Hola!
J'ai voulu ajouter les gradients morphologiques à Olena, mais comme
ceux-ci sont basés sur une différence entre deux images, on a des
problèmes de conversion dès que l'on utilise des types d'Integre :
une différence entre deux image2d<int_u8> donne une image2d<int_s9>
(normal).
Dans Olena 0.10, ce problème était réglé en utilisant des foncteurs de
conversion (convert::force<>), mais cela a un impact sur les
opérateurs arithmétiques sur les images. En clair, il faudrait équiper
oln/level/arith.hh pour qu'il sache utiliser
convert::abstract::conversion<>.
Je peux intégrer ces outils de oln::convert depuis Olena 0.10 et
modifier oln/level/arith.hh, ou bien y a-t-il une meilleure façon de
faire ?
Roland Levillain wrote:
> Je propose donc d'inverser les valeurs de retour de tous les
> tests. Qu'en dites-vous ?
Completement d'accord
--
Christophe Berger
Ça fait longtemps que je le dis (sans rien faire pour que ça change,
mea culpa), mais comme je suis en plein dedans, je pense qu'il est
grand temps de le dire : les tests d'Olena sont contre-intuitifs (si,
si !). Actuellement, il s'agit de bouts de code contenant une
fonction check() renvoyant `false' si le test est correct, `true'
sinon (sic).
Bien sûr, tous les gens qui développent Olena sont habituées à cette
bizarrerie, mais des gens extérieures risquent d'être déroutées, comme
l'est toute personne qui ouvre un test olénoïde pour la première fois.
Je propose donc d'inverser les valeurs de retour de tous les
tests. Qu'en dites-vous ?
Ce code est sans doute redondant avec ce qu'offriront les canevas sur
l'Union-Find, mais :
1. je vais en avoir besoin pour écrire des variantes du watershed ;
2. je ne voulais pas marcher sur les plates-bandes de Christophe et
Nicolas ;
d'où l'idée d'écrire les calculs des extrema locaux avec une variante
à base de FIFO. (C'est très certainement (très) sub-optimal.)
https://svn.lrde.epita.fr/svn/oln/prototypes/proto-1.0
ChangeLog | 13 +++
oln/level/extrema_components.hh | 124 +++++++++++++++++++++++++++++++++++
oln/level/level_components.hh | 83 +++++++++++++++++++++++
oln/morpho/lower_completion.hh | 5 -
tests/level/tests/extrema_components | 42 +++++++++++
tests/morpho/tests/lower_completion | 1
6 files changed, 265 insertions(+), 3 deletions(-)
Index: olena/ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add (queue-based) level and extrema components computation.
* oln/level/level_components.hh, oln/level/extrema_components.hh:
New files.
* tests/level/tests/extrema_components: New test.
* oln/morpho/lower_completion.hh: Check that the input is a scalar
image.
* tests/morpho/tests/lower_completion: Don't include useless
headers.
Index: olena/tests/morpho/tests/lower_completion
--- olena/tests/morpho/tests/lower_completion (revision 195)
+++ olena/tests/morpho/tests/lower_completion (working copy)
@@ -4,7 +4,6 @@
#include "oln/core/2d/image2d.hh"
#include "oln/core/gen/image_with_nbh.hh"
#include "oln/io/read_image.hh"
-#include "oln/io/write_image.hh"
#include "oln/morpho/lower_completion.hh"
#include "oln/ops/cmp.hh"
Index: olena/tests/level/tests/extrema_components
--- olena/tests/level/tests/extrema_components (revision 0)
+++ olena/tests/level/tests/extrema_components (revision 0)
@@ -0,0 +1,42 @@
+ // -*- C++ -*-
+#include "data.hh"
+#include "ntg/int.hh"
+#include "oln/core/2d/image2d.hh"
+#include "oln/core/gen/image_with_nbh.hh"
+#include "oln/io/read_image.hh"
+#include "oln/io/write_image.hh"
+#include "oln/level/extrema_components.hh"
+#include "oln/ops/cmp.hh"
+#include "oln/utils/md5.hh"
+
+using namespace oln;
+
+bool check()
+{
+ image2d<ntg::int_u8> raw_input;
+ raw_input = io::read(rdata("16x16.pgm"));
+ typedef image_with_nbh<image2d<ntg::int_u8>, neighborhood2d> image_type;
+ image_type input = join(raw_input, neighb_c4());
+
+ // MD5 sum of the minima.
+ utils::key::value_type minima_data_key[16] =
+ { 0x72, 0xad, 0x21, 0xcc, 0xd9, 0x6a, 0x6a, 0x82,
+ 0xb8, 0xea, 0x60, 0x1f, 0xcf, 0x76, 0x45, 0x13 };
+ utils::key minima_key(minima_data_key);
+
+ image_type minima = level::minima_components<ntg::int_u8>(input);
+ if (utils::md5(minima) != minima_key)
+ return true;
+
+ // MD5 sum of the maxima.
+ utils::key::value_type maxima_data_key[16] =
+ { 0x6e, 0x71, 0x74, 0x7c, 0xf8, 0xb, 0xfe, 0xa,
+ 0xa9, 0xd2, 0x84, 0x26, 0xa5, 0x3e, 0xfd, 0xba };
+ utils::key maxima_key(maxima_data_key);
+
+ image_type maxima = level::maxima_components<ntg::int_u8>(input);
+ if (utils::md5(maxima) != maxima_key)
+ return true;
+
+ return false;
+}
Index: olena/oln/morpho/lower_completion.hh
--- olena/oln/morpho/lower_completion.hh (revision 195)
+++ olena/oln/morpho/lower_completion.hh (working copy)
@@ -36,11 +36,12 @@
namespace morpho {
- // FIXME: INPUT should be a scalar image.
template <typename DestValue, typename I>
typename ch_value_type<I, DestValue>::ret
lower_completion(const abstract::image_with_nbh<I>& input)
{
+ mlc_is_a(I, abstract::scalar_valued_image)::ensure();
+
typedef oln_type_of(I, point) point_type;
/*------------------------------------------.
@@ -55,7 +56,7 @@
typename ch_value_type<I, unsigned>::ret distance(input.size());
unsigned cur_dist = 1;
- oln_type_of(I, fwd_piter) p(input.size());
+ oln_type_of(I, piter) p(input.size());
for_all_p (p)
{
distance[p] = 0;
Index: olena/oln/level/extrema_components.hh
--- olena/oln/level/extrema_components.hh (revision 0)
+++ olena/oln/level/extrema_components.hh (revision 0)
@@ -0,0 +1,124 @@
+// Copyright (C) 2005 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef OLENA_MORPHO_EXTREMA_COMPONENTS_HH
+# define OLENA_MORPHO_EXTREMA_COMPONENTS_HH
+
+# include <map>
+# include <queue>
+# include <functional>
+
+# include "oln/level/level_components.hh"
+
+namespace oln {
+
+ namespace level {
+
+ namespace internal {
+
+ /// Find the extrema level components of \a input, using \param
+ /// Cmp as comparison function.
+ template <typename DestValue, typename Cmp, typename I>
+ typename ch_value_type<I, DestValue>::ret
+ extrema_components(const abstract::image_with_nbh<I>& input)
+ {
+ mlc_is_a(I, abstract::scalar_valued_image)::ensure();
+ Cmp cmp;
+
+ // Compute level components.
+ typename ch_value_type<I, DestValue>::ret comps =
+ level_components<DestValue>(input);
+ std::set<DestValue> extrema;
+ std::set<DestValue> non_extrema;
+
+ // Search extrema components.
+ oln_type_of(I, piter) p(input.size());
+ for_all_p (p)
+ {
+ DestValue comp = comps[p];
+ if (non_extrema.find(comp) == non_extrema.end ())
+ {
+ // A new level is a (potential) extrema by default.
+ extrema.insert(comp);
+
+ oln_type_of(I, niter) n(input);
+ for_all_n_of_p (n, p)
+ if (input.hold(n) && cmp(input[n], input[p]))
+ {
+ extrema.erase(comp);
+ non_extrema.insert(comp);
+ }
+ }
+ }
+
+ // Re-label the extrema. label_map hold the assigned labels.
+ std::map<DestValue, DestValue> label_map;
+ {
+ DestValue cur_label = ntg_min_val(DestValue) + 1;
+ for (typename std::set<DestValue>::const_iterator i =
+ extrema.begin(); i != extrema.end(); ++i, ++cur_label)
+ label_map[*i] = cur_label;
+ }
+ typename ch_value_type<I, DestValue>::ret output (input.size());
+ level::fill (output, ntg_min_val(DestValue));
+ for_all_p (p)
+ {
+ DestValue comp = comps[p];
+ if (label_map.find(comp) != label_map.end())
+ output[p] = label_map[comp];
+ }
+ return output;
+ }
+
+ } // end of namespace oln::level::internal.
+
+
+ /// Find the minima level components of \a input.
+ template <typename DestValue, typename I>
+ typename ch_value_type<I, DestValue>::ret
+ minima_components(const abstract::image_with_nbh<I>& input)
+ {
+ mlc_is_a(I, abstract::scalar_valued_image)::ensure();
+ return internal::extrema_components< DestValue,
+ std::less<DestValue> >(input);
+ }
+
+ /// Find the maxima level components of \a input.
+ template <typename DestValue, typename I>
+ typename ch_value_type<I, DestValue>::ret
+ maxima_components(const abstract::image_with_nbh<I>& input)
+ {
+ mlc_is_a(I, abstract::scalar_valued_image)::ensure();
+ return internal::extrema_components< DestValue,
+ std::greater<DestValue> >(input);
+ }
+
+ } // end of namespace oln::level.
+
+} // end of namespace oln.
+
+#endif // ! OLENA_MORPHO_EXTREMA_COMPONENTS_HH
Index: olena/oln/level/level_components.hh
--- olena/oln/level/level_components.hh (revision 0)
+++ olena/oln/level/level_components.hh (revision 0)
@@ -0,0 +1,83 @@
+// Copyright (C) 2005 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef OLENA_MORPHO_LEVEL_COMPONENTS_HH
+# define OLENA_MORPHO_LEVEL_COMPONENTS_HH
+
+# include <queue>
+
+# include "oln/level/fill.hh"
+
+namespace oln {
+
+ namespace level {
+
+ /// Compute the level components of \a input.
+ template <typename DestValue, typename I>
+ typename ch_value_type<I, DestValue>::ret
+ level_components(const abstract::image_with_nbh<I>& input)
+ {
+ mlc_is_a(I, abstract::scalar_valued_image)::ensure();
+
+ typename ch_value_type<I, DestValue>::ret labels(input.size());
+ typename ch_value_type<I, bool>::ret processed(input.size());
+ level::fill (processed, false);
+
+ DestValue cur_label = ntg_min_val(DestValue);
+
+ typedef oln_type_of(I, point) point_type;
+ std::queue<point_type> q;
+
+ oln_type_of(I, piter) p(input.size());
+ for_all_p (p)
+ if (!processed[p])
+ {
+ labels[p] = cur_label;
+ q.push(p);
+ while (!q.empty())
+ {
+ point_type s = q.front();
+ q.pop();
+ oln_type_of(I, niter) n(input);
+ for_all_n_of_p (n, s)
+ if (input.hold(n) && input[n] == input[s] && !processed[n])
+ {
+ labels[n] = cur_label;
+ processed[n] = true;
+ q.push(n);
+ }
+ }
+ ++cur_label;
+ }
+ return labels;
+ }
+
+ } // end of namespace oln::level
+
+} // end of namespace oln
+
+#endif // ! OLENA_MORPHO_LEVEL_COMPONENTS_HH