URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-07-24 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Fixes about IZ method.
* edwin/exec/zi.cc: Some tries...
* edwin/exec/zi.hh: Real distance between components.
---
zi.cc | 106 +++++++++++++++++++++++++++++++++++----------
zi.hh | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 236 insertions(+), 23 deletions(-)
Index: trunk/milena/sandbox/edwin/exec/zi.hh
===================================================================
--- trunk/milena/sandbox/edwin/exec/zi.hh (revision 0)
+++ trunk/milena/sandbox/edwin/exec/zi.hh (revision 4329)
@@ -0,0 +1,153 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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 ZI_HH
+# define ZI_HH
+
+
+// From mln/canvas/distance_geodesic.hh
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/routine/duplicate.hh>
+# include <mln/core/site_set/p_queue_fast.hh>
+# include <queue>
+# include <mln/data/fill.hh>
+# include <mln/extension/adjust_fill.hh>
+
+
+// Local.
+
+#include <map>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pbm/load.hh>
+#include <mln/labeling/blobs.hh>
+#include <mln/debug/println.hh>
+
+
+
+
+namespace mln
+{
+
+ // Theo's code
+
+ // From mln/canvas/distance_geodesic.hh
+ // and mln/transform/internal/influence_zone_functor.hh
+ // and mln/transform/influence_zone_geodesic.hh
+
+
+ template <typename I, typename N>
+ std::map< std::pair<mln_value(I),mln_value(I)>, unsigned >
+ distances(// in:
+ const I& input, const N& nbh,
+ // out:
+ mln_ch_value(I, unsigned)& dmap,
+ mln_concrete(I)& iz)
+ {
+ trace::entering("canvas::impl::generic::distance_geodesic");
+
+ typedef mln_value(I) L;
+ std::map< std::pair<L,L>, unsigned > dist; // NEW
+
+ const unsigned max = mln_max(unsigned);
+ typedef mln_site(I) P;
+ p_queue_fast<P> q;
+
+ // Initialization.
+ {
+ iz = duplicate(input); // <-- init
+
+ data::fill(dmap, max);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if (input(p) != 0) // <-- inqueue_p_wrt_input_p
+ {
+ ; // <-- init_p
+ dmap(p) = 0;
+ for_all(n)
+ if (input.domain().has(n) &&
+ input(n) == 0) // <-- inqueue_p_wrt_input_n
+ {
+ q.push(p);
+ break;
+ }
+ }
+ }
+
+ // Propagation.
+ {
+ P p;
+ mln_niter(N) n(nbh, p);
+ while (! q.is_empty())
+ {
+ p = q.pop_front();
+ if (dmap(p) == max)
+ {
+ // Saturation so stop.
+ q.clear();
+ break;
+ }
+ for_all(n)
+ {
+ if (! input.domain().has(n))
+ continue;
+ if (dmap(n) == max)
+ {
+ dmap(n) = dmap(p) + 1;
+ iz(n) = iz(p); // <- process
+ q.push(n);
+ }
+ else
+ {
+ if (iz(n) != iz(p))
+ {
+ L l1 = iz(n), l2 = iz(p);
+ if (l1 > l2)
+ std::swap(l1, l2);
+ unsigned& d_ = dist[std::make_pair(l1,l2)];
+ unsigned d12 = dmap(p) + dmap(n) + 1;
+ if (d_ == 0 || d12 < d_)
+ d_ = d12;
+ }
+ }
+ }
+ }
+ }
+
+ return dist;
+ }
+
+} // mln
+
+# ifndef MLN_INCLUDE_ONLY
+
+# endif // ! MLN_INCLUDE_ONLY
+
+#endif // ! ZI_HH
Index: trunk/milena/sandbox/edwin/exec/zi.cc
===================================================================
--- trunk/milena/sandbox/edwin/exec/zi.cc (revision 4328)
+++ trunk/milena/sandbox/edwin/exec/zi.cc (revision 4329)
@@ -33,6 +33,7 @@
#include <mln/value/int_u8.hh>
#include <mln/value/label_16.hh>
#include <mln/value/label_8.hh>
+#include <mln/data/convert.hh>
#include <mln/util/graph.hh>
#include <mln/io/pbm/load.hh>
@@ -50,10 +51,13 @@
#include <mln/make/edge_image.hh>
#include <mln/make/vertex_image.hh>
+#include <mln/morpho/closing/height.hh>
+
#include <mln/math/max.hh>
#include <mln/norm/l1.hh>
#include "color_distance.hh"
+#include "zi.hh"
#include <iostream>
namespace mln
@@ -94,6 +98,7 @@
}
+ // distance entre les centres de masses.
template <typename P>
inline
value::int_u8
@@ -103,6 +108,7 @@
}
+ // distance entre les boites englobantes.
inline
value::int_u8
distance_box(const box<point2d>& b1, const box<point2d>& b2)
@@ -125,6 +131,35 @@
return math::max(math::max(w_dist, h_dist), 0);
}
+
+ // distance geodesic entre les composantes.
+ template <typename G, typename L>
+ struct distance_t : Function_v2v< distance_t<G, L> >
+ {
+ typedef unsigned result;
+ typedef util::vertex_id_t V;
+ typedef util::edge_id_t E;
+
+ distance_t(const std::map< std::pair<L, L>, unsigned >& d_,
+ const G& graph)
+ : d(d_),
+ g(graph)
+ {
+ }
+
+ unsigned
+ operator () (const E& e_id) const
+ {
+ typename G::edge_t e = g.edge(e_id);
+ std::pair<L, L> p((value::label_8)e.v1(), (value::label_8)e.v2());
+ return d.find(p)->second;
+ }
+
+ private:
+ const std::map< std::pair<L, L>, unsigned >& d;
+ const G& g;
+ };
+
}
@@ -147,12 +182,13 @@
using namespace mln;
using value::int_u8;
- if (argc < 3)
+ if (argc < 4)
usage(argv);
const char* finput = argv[1];
const char* fsource = argv[2];
- const char* foutput = argc > 3 ? argv[3] : "zi.pgm";
+ const unsigned lambda = atoi(argv[3]);
+ const char* foutput = argc > 4 ? argv[4] : "zi.pgm";
// Image loadin'
image2d<bool> input;
@@ -167,11 +203,17 @@
typedef image2d<L> I;
I labels, iz, out;
+ image2d<unsigned> dmap;
L nlabel;
+ typedef std::map< std::pair<L,L>, unsigned > map_t;
labels = labeling::blobs(input, c4(), nlabel);
- iz = transform::influence_zone_geodesic(labels, c4());
+ initialize(iz, input);
+ initialize(dmap, input);
+
+ map_t d = distances(labels, c4(), dmap, iz);
+ io::pgm::save(data::convert(int_u8(), dmap), "dmap.pgm");
io::pgm::save(iz, foutput);
// I.Z Graph
@@ -179,29 +221,33 @@
// Valuation of color distance
- // util::array<value::rgb8> mean_colors;
- // convert::from_to(labeling::compute(accu::stat::mean<value::rgb8>(), source,
labels, nlabel),
- // mean_colors);
+ /*
+ util::array<value::rgb8> mean_colors;
+ convert::from_to(labeling::compute(accu::stat::mean<value::rgb8>(), source,
labels, nlabel),
+ mean_colors);
- // typedef vertex_image<void, value::rgb8, util::graph> V;
- // V v_ima = make::vertex_image(izg, mean_colors);
-
- // typedef edge_image<void, value::int_u8, util::graph> E;
- // E e_ima = make::edge_image(v_ima, convert::tofun(dist_mean));
+ typedef vertex_image<void, value::rgb8, util::graph> V;
+ V v_ima = make::vertex_image(izg, mean_colors);
+ typedef edge_image<void, value::int_u8, util::graph> E;
+ E e_ima = make::edge_image(v_ima, convert::tofun(dist_mean));
+ */
// Valuation of geometric distance
- // util::array<mln_psite_(I)> mass_centers;
-// convert::from_to(labeling::compute(accu::center<mln_psite_(I)>(), labels,
nlabel),
-// mass_centers);
+ /*
+ util::array<mln_psite_(I)> mass_centers;
+ convert::from_to(labeling::compute(accu::center<mln_psite_(I)>(), labels,
nlabel),
+ mass_centers);
-// typedef vertex_image<void, mln_psite_(I), util::graph> V;
-// V v_ima = make::vertex_image(izg, mass_centers);
+ typedef vertex_image<void, mln_psite_(I), util::graph> V;
+ V v_ima = make::vertex_image(izg, mass_centers);
-// typedef edge_image<void, value::int_u8, util::graph> E;
-// E e_ima = make::edge_image(v_ima, convert::tofun(distance<mln_psite_(I)>));
+ typedef edge_image<void, value::int_u8, util::graph> E;
+ E e_ima = make::edge_image(v_ima, convert::tofun(distance<mln_psite_(I)>));
+ */
// Valuation of distance between bounding boxes
+ /*
util::array< box<mln_psite_(I)> > bboxes;
convert::from_to(labeling::compute(accu::shape::bbox<mln_psite_(I)>(), labels,
nlabel),
bboxes);
@@ -211,15 +257,23 @@
typedef edge_image<void, value::int_u8, util::graph> E;
E e_ima = make::edge_image(v_ima, convert::tofun(distance_box));
+ */
+
+ // Valuation of components geodesic distance.
+ typedef edge_image<void, unsigned, util::graph> E;
+ E e_ima = make::edge_image(izg, distance_t<util::graph, value::label_8>(d,
izg));
+ // Closing
+ e_ima = morpho::closing::height(e_ima, E::nbh_t (), lambda);
+
// WST.
- typedef mln_ch_value_(V, L) v_ima_labels_t;
- v_ima_labels_t v_ima_labels;
- initialize(v_ima_labels, v_ima);
+ typedef vertex_image<void, L, util::graph> V;
+ p_vertices<util::graph> pv(izg);
+ V v_ima_labels(pv);
- typedef mln_ch_value_(E, L) e_ima_wst_t;
+ typedef edge_image<void, L, util::graph> e_ima_wst_t;
L nbasins;
e_ima_wst_t e_ima_wst =
morpho::watershed::flooding(e_ima, E::nbh_t (), nbasins);
@@ -240,13 +294,19 @@
// Relabeling
util::array<L> tr(nlabel);
- mln_piter_(V) v(v_ima.domain());
+ mln_piter_(V) v(v_ima_labels.domain());
for_all(v)
{
std::cout << v.id() << " : " << v_ima_labels(v) <<
std::endl;
tr[v.id()] = v_ima_labels(v);
}
+ //print distance
+ for (map_t::const_iterator it = d.begin(); it != d.end(); ++it)
+ std::cout << it->first.first << ", "
+ << it->first.second << " -> "
+ << it->second << std::endl;
+
labeling::relabel_inplace(iz, nlabel, tr);
io::pgm::save(iz, "zi_wst.pgm");