Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 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
- 9625 discussions
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Alexandre Abraham <abraham(a)lrde.epita.fr>
Fix for two ways functions.
* mln/value/shell.hh: Little fix for v2w_w2v functions.
shell.hh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Index: mln/value/shell.hh
--- mln/value/shell.hh (revision 3154)
+++ mln/value/shell.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008, 2009 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
@@ -162,7 +162,7 @@
template <typename F, typename I>
mln_value(I) shell_<F, I, Function_v2w_w2v<void> >::set_ (I &ima, const mln_site(I) &s, const typename F::result &v)
{
- ima(s) = F().f_1(ima(s), v);
+ ima(s) = F().f_1(v, ima(s));
return ima(s);
}
1
0
14 Jan '09
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Alexandre Abraham <abraham(a)lrde.epita.fr>
Make the topological Watershed a standalon function.
* abraham/tests/morpho/test_watershed_topo.cc: Updated.
* abraham/tests/morpho/levelings.cc: Updated.
* abraham/tests/morpho/Makefile: Add dependencies.
* abraham/tests/fun/meta/red.cc: Updated.
* abraham/mln/morpho/vector_median.hh: Add 2009 year.
* abraham/mln/morpho/topo_wst.hh: Extract watershed method
from the big structure.
mln/morpho/topo_wst.hh | 419 +++++++++++++++++-------------------
mln/morpho/vector_median.hh | 2
tests/fun/meta/red.cc | 3
tests/morpho/Makefile | 4
tests/morpho/levelings.cc | 41 +--
tests/morpho/test_watershed_topo.cc | 7
6 files changed, 229 insertions(+), 247 deletions(-)
Index: abraham/tests/morpho/test_watershed_topo.cc
--- abraham/tests/morpho/test_watershed_topo.cc (revision 3153)
+++ abraham/tests/morpho/test_watershed_topo.cc (working copy)
@@ -25,9 +25,7 @@
return 1;
}
- for (int i = 1; i < argc; ++i)
- {
-
+ for (int i = 1; i < argc; ++i) {
image2dint ima;
io::pgm::load(ima, argv[i]);
@@ -38,8 +36,7 @@
std::string name(argv[i]);
name.erase(name.length() - 4);
- io::pgm::save(n.pima, name.append("_wsd.pgm"));
-
+ io::pgm::save(morpho::topo_watershed(n), name.append("_wsd.pgm"));
}
return 0;
}
Index: abraham/tests/morpho/levelings.cc
--- abraham/tests/morpho/levelings.cc (revision 3153)
+++ abraham/tests/morpho/levelings.cc (working copy)
@@ -3,6 +3,7 @@
#include <mln/io/ppm/load.hh>
#include <mln/value/int_u8.hh>
#include <mln/morpho/vector_median.hh>
+#include <mln/morpho/vmt.hh>
#include <mln/morpho/autarkical_leveling.hh>
#include <mln/fun/meta/red.hh>
#include <mln/value/rgb8.hh>
@@ -10,31 +11,6 @@
#include <mln/core/image/fun_image.hh>
#include <mln/core/image/violent_cast_image.hh>
-namespace mln
-{
- struct red_only
- {
- template <unsigned n>
- value::rgb<n> max_() const
- {
- return value::rgb<n>(mln_max(typename value::rgb<n>::red_t), 0, 0);
- }
-
- value::rgb8 max () const
- {
- return value::rgb8(255, 0, 0);
- }
-
- template <unsigned n>
- bool less(const value::rgb<n>& a, const value::rgb<n>& b)
- {
- return a.red() < b.red();
- }
- };
-
-}
-
-
int main (int argc, const char * argv[])
{
using namespace mln;
@@ -45,8 +21,6 @@
return 1;
}
- typedef value::mixin<value::rgb8,red_only> Rgb;
-
for (int i = 1; i < argc; ++i)
{
border::thickness = 2;
@@ -57,9 +31,18 @@
std::string name(argv[i]);
name.erase(name.length() - 4);
- win::rectangle2d rect(8, 8);
+ win::rectangle2d smallrect(13, 13);
+ win::rectangle2d bigrect(25, 25);
+
+ image2d<rgb8> ima_vm = morpho::vector_median(ima, bigrect);
+
+ io::ppm::save(ima_vm, name.append("_vector_medianed.ppm"));
+
+ name = argv[i];
+ name.erase(name.length() - 4);
+
- io::ppm::save(morpho::autarkical_leveling(ima, morpho::vector_median(ima, rect), rect), name.append("_autarkical_leveled.ppm"));
+ io::ppm::save(morpho::autarkical_leveling(ima, ima_vm, smallrect), name.append("_autarkical_leveled.ppm"));
}
return 0;
Index: abraham/tests/morpho/Makefile
--- abraham/tests/morpho/Makefile (revision 3153)
+++ abraham/tests/morpho/Makefile (working copy)
@@ -16,6 +16,7 @@
.PHONY: clean distclean
## Depedencies
-test_watershed_topo.cc: ../../mln/morpho/basic_najman.hh
+test_watershed_topo_new.cc: ../../mln/morpho/topo_wst_new.hh
+test_watershed_topo.cc: ../../mln/morpho/topo_wst.hh
test_watershed.cc: ../../mln/morpho/basic_najman.hh
-test_componenet_tree.cc: ../../mln/morpho/basic_najman.hh
\ No newline at end of file
+test_component_tree.cc: ../../mln/morpho/basic_najman.hh
Index: abraham/tests/fun/meta/red.cc
--- abraham/tests/fun/meta/red.cc (revision 3153)
+++ abraham/tests/fun/meta/red.cc (working copy)
@@ -57,7 +57,10 @@
mln_piter_(mln::image2d<C>) p(i.domain());
for_all (p)
+ {
+ out(p) = 2;
std::cout << out(p) << std::endl;
+ }
}
Index: abraham/mln/morpho/vector_median.hh
--- abraham/mln/morpho/vector_median.hh (revision 3153)
+++ abraham/mln/morpho/vector_median.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
// (LRDE)
//
// This file is part of the Olena Library. This library is free
Index: abraham/mln/morpho/topo_wst.hh
--- abraham/mln/morpho/topo_wst.hh (revision 3153)
+++ abraham/mln/morpho/topo_wst.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -52,6 +52,42 @@
namespace morpho
{
+ template <class I>
+ mln_site(I) min (const Image<I> &ima_, p_set<mln_site(I)>& components)
+ {
+ const I& ima = exact(ima_);
+
+ if (components.nsites() == 0)
+ return mln_site(I)(-1, -1); // FIXME
+
+ typename p_set<mln_site(I)>::fwd_piter it(components);
+ mln_site(I) min = components[0];
+
+ for_all(it)
+ if (ima(it) < ima(min))
+ min = it;
+
+ return min;
+ }
+
+ template <class I>
+ mln_site(I) max (p_set<mln_site(I)>& components)
+ {
+ if (components.nsites() == 0)
+ return mln_site(I)(-1, -1); // FIXME
+
+ typename p_set<mln_site(I)>::fwd_piter it(components);
+ mln_site(I) max = components[0];
+
+ for_all(it)
+ if (ima(it) > ima(max))
+ max = it;
+
+ return max;
+ }
+
+
+
template <class I, class N>
struct topo_wst
{
@@ -59,6 +95,8 @@
// Typedefs
// --------
typedef mln_site(I) site;
+ typedef I image_t;
+ typedef N neighborhood_t;
// Component tree management
// -------------------------
@@ -88,14 +126,10 @@
// children.append(n);
children.push_back(p);
}
-
- mln_value(I) min() { return mln_min(mln_value(I)); }
- mln_value(I) max() { return mln_max(mln_value(I)); }
- void revert () { level = max() - level + min(); }
-
}; // struct node
- const mln_exact(N)& nbh;
+ public:
+
mln_ch_value(I, site) Par_node;
mln_ch_value(I, site) Par_tree;
@@ -105,10 +139,11 @@
mln_ch_value(I, node) nodes;
site Root;
+ private:
+
void MakeSet_tree(site x);
void MakeSet_node(site x);
site Find_tree(site x);
- void swap(site& x, site& y);
site Find_node(site x);
void BuildComponentTree();
site MergeNode(site& node1, site& node2);
@@ -116,10 +151,6 @@
site Link_node(site x, site y);
node MakeNode(int level);
-
- // Watershed algorithm
- // -------------------
-
private:
mln_ch_value(I, bool) isproc;
@@ -128,10 +159,9 @@
topo_wst(const Image<I>& i,
const Neighborhood<N>& n);
-
- // Result
public:
- mln_exact(I) pima;
+ const I &ima;
+ const N &nbh;
public:
void go();
@@ -141,12 +171,12 @@
site max (p_set<site>& components);
bool highest_fork (p_set<site>& components);
bool highest_fork (p_set<site>& components, site &r);
- bool w_constructible(site p, site &r);
- bool w_constructible(site p);
- void topo_watershed();
-
// Optimized LCA Algorithm
+
+ public:
+ site lca (site a, site b);
+
private:
int *euler;
int *depth;
@@ -161,7 +191,6 @@
void build_euler_tour_rec(site p, int &position, int d);
void build_euler_tour();
void build_minim ();
- site lca (site a, site b);
void removeOneSonNodes(site *p, mln_ch_value(I, site) &newPar_node);
void compressTree();
}; // struct topo_wst
@@ -172,15 +201,15 @@
template <class I, class N>
topo_wst<I, N>::topo_wst(const Image<I>& i,
const Neighborhood<N>& n)
- : nbh(exact(n)),
- Par_node(exact(i).domain(), exact(i).border()),
+ : Par_node(exact(i).domain(), exact(i).border()),
Par_tree(exact(i).domain(), exact(i).border()),
Rnk_tree(exact(i).domain(), exact(i).border()),
Rnk_node(exact(i).domain(), exact(i).border()),
subtreeRoot(exact(i).domain(), exact(i).border()),
nodes(exact(i).domain(), exact(i).border()),
isproc(exact(i).domain(), exact(i).border()),
- pima(exact(i))
+ ima(exact(i)),
+ nbh(exact(n))
{
}
@@ -207,14 +236,6 @@
}
template <class I, class N>
- void topo_wst<I, N>::swap(site& x, site& y)
- {
- site memo = x;
- x = y;
- y = memo;
- }
-
- template <class I, class N>
typename topo_wst<I, N>::site topo_wst<I, N>::Find_node(site x)
{
if (Par_node(x) != x)
@@ -227,16 +248,9 @@
{
BuildComponentTree();
compressTree();
- arith::revert_inplace(pima);
- // arith::revert_inplace(nodes);
- mln_piter(image2d<node>) p (nodes.domain());
- for_all(p)
- nodes(p).revert();
build_euler_tour();
build_minim();
- topo_watershed();
- arith::revert_inplace(pima);
}
template <class I, class N>
@@ -246,7 +260,7 @@
// Sort the sites in increasing order
p_array<mln_site(I)> S;
- S = level::sort_psites_increasing(pima);
+ S = level::sort_psites_increasing(ima);
// Clear the marker map
data::fill(isproc, false);
@@ -258,7 +272,7 @@
// if (subtreeRoot.hold(p))
subtreeRoot(p) = p;
// if (nodes.hold(p))
- nodes(p) = MakeNode(pima(p));
+ nodes(p) = MakeNode(ima(p));
}
@@ -273,7 +287,7 @@
mln_niter(N) q(nbh, ip);
for_all(q)
- if (pima.has(q) and isproc(q) and pima(q) <= pima(p))
+ if (ima.has(q) and isproc(q) and ima(q) <= ima(p))
{
site adjCanonicalElt = Find_tree(q);
site adjNode = Find_node(subtreeRoot(adjCanonicalElt));
@@ -333,7 +347,7 @@
typename topo_wst<I, N>::site topo_wst<I, N>::Link_tree(site x, site y)
{
if (Rnk_tree(x) > Rnk_tree(y))
- swap(x, y);
+ std::swap(x, y);
else
if (Rnk_tree(x) == Rnk_tree(y))
Rnk_tree(y) += 1;
@@ -345,7 +359,7 @@
typename topo_wst<I, N>::site topo_wst<I, N>::Link_node(site x, site y)
{
if (Rnk_node(x) > Rnk_node(y))
- swap(x, y);
+ std::swap(x, y);
else
if (Rnk_node(x) == Rnk_node(y))
Rnk_node(y) += 1;
@@ -363,38 +377,6 @@
return n;
}
- template <class I, class N>
- typename topo_wst<I, N>::site topo_wst<I, N>::min (p_set<site>& components)
- {
- if (components.nsites() == 0)
- return site(-1, -1);
-
- typename p_set<site>::fwd_piter it(components);
- site min = components[0];
-
- for_all(it)
- if (pima(it.to_site()) < pima(min))
- min = it.to_site();
-
- return min;
- }
-
- template <class I, class N>
- typename topo_wst<I, N>::site topo_wst<I, N>::max (p_set<site>& components)
- {
- if (components.nsites() == 0)
- return site(-1, -1);
-
- typename p_set<site>::fwd_piter it(components);
- site max = components[0];
-
- for_all(it)
- if (pima(it.to_site()) > pima(max))
- max = it.to_site();
-
- return max;
- }
-
template <class I, class N>
bool topo_wst<I, N>::highest_fork (p_set<site>& components, site &r)
@@ -435,140 +417,6 @@
}
template <class I, class N>
- bool topo_wst<I, N>::w_constructible(site p) {
- site i;
- return w_constructible(p, i);
- }
-
- template <class I, class N>
- bool topo_wst<I, N>::w_constructible(site p, site &r)
- {
- mln_niter(N) q(nbh, p);
- p_set<site> v;
-
- for_all(q)
- if (pima.has(q) && pima(q) > pima(p))
- v.insert(Par_node(q));
-
- if (v.nsites() == 0)
- return false;
-
- if (v.nsites() == 1) {
- r = v[0];
- return true;
- }
-
- site
- c = max(v),
- cmax = c;
-
- typename p_set<site>::fwd_piter it(v);
- for_all(it)
- {
- // Can't remove the site from the set
- if (it.to_site() == cmax)
- continue;
-
- site c1 = lca(c, it.to_site());
-
- if (c1 != it.to_site())
- c = c1;
- }
-
- if (nodes(c).level <= pima(p))
- return false;
-
- r = c;
- return true;
- }
-
-
- template <class I, class N>
- void topo_wst<I, N>::topo_watershed()
- {
- // Maxima components
- mln_ch_value(I, bool) cmax(pima.domain(), pima.border());
-
- // Mark enqueued sites
- mln_ch_value(I, bool) enqueued(pima.domain(), pima.border());
-
- p_priority< mln_value(I), p_queue_fast<site> > l;
- // p_queue < site > m;
- std::queue<site> m;
- mln_value(I) max = mln_max(mln_value(I));
-
- std::cout << "Init" << std::endl;
-
- // Flag C-maxima
- data::fill(cmax, false);
- data::fill(enqueued, false);
-
- mln_piter(I) it(Par_node.domain());
- for_all(it)
- // if (nodes(Par_node(it.to_site())).children.nsites() == 0)
- if (nodes(Par_node(it.to_site())).children.size() == 0)
- {
- cmax(it.to_site()) = true;
- m.push(it.to_site());
- }
-
- while (!m.empty())
- {
- mln_niter(N) q(nbh, m.front());
- for_all(q)
- if (cmax.has(q) && !cmax(q) && !enqueued(q))
- {
- enqueued(q) = true;
- l.push(pima(q), q);
- }
- m.pop();
- }
-
-
- std::cout << "end" << std::endl;
-
- // Main loop
- while (!l.is_empty())
- {
- site x = l.front();
- l.pop();
- enqueued(x) = false;
-
- site c;
- bool is_w = w_constructible(x, c);
-
- if (is_w)
- {
- pima(x) = nodes(c).level;
- Par_node(x) = c;
-
- // if (nodes(c).children.nsites() == 0)
- if (nodes(c).children.size() == 0)
- cmax(x) = true;
- else
- // if (nodes(c).children.nsites() > 1)
- if (nodes(c).children.size() == 1)
- std::cerr << "ERREUR COMPOSANTE BRANCHE " << nodes(c).children.size() << std::endl;
-
-
- mln_niter(N) q(nbh, x);
- for_all(q)
- if (pima.has(q) && !cmax(q) && !enqueued(q))
- {
- enqueued(q) = true;
-
- l.push(pima(q), q);
- }
- } // if (c != site(-1, -1))
- } // while(!l.empty())
-
- for_all(it)
- pima(it.to_site()) = nodes(Par_node(it.to_site())).level;
- }
-
-
-
- template <class I, class N>
void topo_wst<I, N>::compute_ctree_size (site p)
{
ctree_size += 1;
@@ -739,6 +587,157 @@
Par_node(p) = newPar_node(Par_node(p));
}
+ template <class T>
+ bool w_constructible(T &tree, typename T::site p, typename T::site &r)
+ {
+
+ typedef typename T::image_t I;
+ typedef typename T::neighborhood_t N;
+
+ const I &ima = exact(tree.ima);
+ const N &nbh = exact(tree.nbh);
+
+ mln_niter(N) q(nbh, p);
+ p_set<mln_site(I)> v;
+
+ for_all(q)
+ if (ima.domain().has(q) && ima(q) < ima(p))
+ v.insert(tree.Par_node(q));
+
+ if (v.nsites() == 0)
+ return false;
+
+ if (v.nsites() == 1) {
+ r = v[0];
+ return true;
+ }
+
+ mln_site(I)
+ c = min(ima, v),
+ cmin = c;
+
+ typename p_set<mln_site(I)>::fwd_piter it(v);
+ for_all(it)
+ {
+ // Can't remove the site from the set
+ if (it.to_site() == cmin)
+ continue;
+
+ mln_site(I) c1 = tree.lca(c, it);
+
+ if (c1 != it)
+ c = c1;
+ }
+
+ if (tree.nodes(c).level >= ima(p))
+ return false;
+
+ r = c;
+ return true;
+ }
+
+ template <class T>
+ bool w_constructible(T &tree, typename T::site p) {
+ typename T::site r;
+ return w_constructible(tree, p, r);
+ }
+
+
+
+ template <class T>
+ typename T::image_t topo_watershed(T &tree)
+ {
+
+ typedef typename T::image_t I;
+ typedef typename T::neighborhood_t N;
+
+ I ima = exact(tree.ima);
+ const N &nbh = exact(tree.nbh);
+
+ // Maxima components
+ mln_ch_value(I, bool) cmax(ima.domain(), ima.border());
+
+ // Mark enqueued sites
+ mln_ch_value(I, bool) enqueued(ima.domain(), ima.border());
+
+ p_priority< mln_value(I), p_queue_fast<mln_site(I)> > l;
+ // p_queue < site > m;
+ std::queue<mln_site(I)> m;
+ mln_value(I) min = mln_min(mln_value(I));
+
+ std::cout << "Init" << std::endl;
+
+ // Flag C-maxima
+ data::fill(cmax, false);
+ data::fill(enqueued, false);
+
+ mln_piter(I) it(tree.Par_node.domain());
+ for_all(it)
+ // if (nodes(Par_node(it.to_site())).children.nsites() == 0)
+ if (tree.nodes(tree.Par_node(it)).children.size() == 0)
+ {
+ cmax(it) = true;
+ m.push(it);
+ }
+
+ while (!m.empty())
+ {
+ mln_niter(N) q(nbh, m.front());
+ for_all(q)
+ if (cmax.domain().has(q) && !cmax(q) && !enqueued(q))
+ {
+ enqueued(q) = true;
+ l.push(mln_max(mln_value(I)) - ima(q), q);
+ }
+ m.pop();
+ }
+
+
+ std::cout << "end" << std::endl;
+
+ // Main loop
+ while (!l.is_empty())
+ {
+ mln_site(I) x = l.front();
+ l.pop();
+ enqueued(x) = false;
+
+ mln_site(I) c;
+ bool is_w = w_constructible(tree, x, c);
+
+ if (is_w)
+ {
+ ima(x) = tree.nodes(c).level;
+ tree.Par_node(x) = c;
+
+ // if (nodes(c).children.nsites() == 0)
+ if (tree.nodes(c).children.size() == 0)
+ cmax(x) = true;
+ else
+ // if (nodes(c).children.nsites() > 1)
+ if (tree.nodes(c).children.size() == 1)
+ std::cerr << "ERREUR COMPOSANTE BRANCHE " << tree.nodes(c).children.size() << std::endl;
+
+
+ mln_niter(N) q(nbh, x);
+ for_all(q)
+ if (ima.domain().has(q) && !cmax(q) && !enqueued(q))
+ {
+ enqueued(q) = true;
+ l.push(mln_max(mln_value(I)) - ima(q), q); // FIXME : just invert the priority
+ }
+ }
+ } // while(!l.empty())
+
+ for_all(it)
+ ima(it) = tree.nodes(tree.Par_node(it)).level;
+
+ return ima;
+ }
+
+
+
+
# endif // MLN_INCLUDE_ONLY
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Alexandre Abraham <abraham(a)lrde.epita.fr>
Move some files to trunk.
* abraham/mln/morpho/autarkical_leveling.hh: Update.
* abraham/mln/morpho/vmt.hh: New
For test purpose.
* abraham/mln/morpho/vector_median.hh: Update.
* abraham/mln/core/concept/meta_fun.hh: Move to trunk.
* abraham/mln/math/cos.hh: Move to trunk.
* abraham/mln/math/acos.hh: Move to trunk.
* abraham/mln/value/shell.hh: Move to trunk.
core/concept/meta_fun.hh | 79 -----------------
math/acos.hh | 65 --------------
math/cos.hh | 65 --------------
morpho/autarkical_leveling.hh | 67 ++++++++------
morpho/vector_median.hh | 2
morpho/vmt.hh | 126 +++++++++++++++++++++++++++
value/shell.hh | 190 ------------------------------------------
7 files changed, 166 insertions(+), 428 deletions(-)
Index: abraham/mln/morpho/autarkical_leveling.hh
--- abraham/mln/morpho/autarkical_leveling.hh (revision 3055)
+++ abraham/mln/morpho/autarkical_leveling.hh (working copy)
@@ -37,11 +37,8 @@
# include <mln/morpho/includes.hh>
# include <mln/morpho/general.hh>
-# include <mln/accu/land.hh>
-# include <mln/accu/land_basic.hh>
-# include <mln/accu/min.hh>
-# include <mln/accu/min_h.hh>
# include <mln/norm/l2.hh>
+# include <mln/level/paste.hh>
namespace mln
{
@@ -74,23 +71,27 @@
const W& win = exact(win_);
O output;
+ O ref;
output = clone(input);
-
- bool modification = true;
+ ref = clone(input);
mln_piter(I) p(input.domain());
mln_qiter(W) q(win, p);
mln_qiter(W) r(win, p);
+ bool stable = false;
+ while (!stable)
+ {
+ stable = true;
for_all(p)
{
mln_psite(W) v;
double min_dist = std::numeric_limits<double>::infinity();
bool same_side = true;
- for_all(q) if (input.domain().has(q))
+ for_all(q) if (ref.domain().has(q))
{
- for_all(r) if (input.domain().has(r) && q!=r)
- if ((marker(q) - input(p)) * (marker(r) - input(p)) < 0)
+ for_all(r) if (ref.domain().has(r) && q!=r)
+ if ((marker(q) - ref(p)) * (marker(r) - ref(p)) < 0)
{
same_side = false;
break;
@@ -99,7 +100,7 @@
if (!same_side)
break;
- double dist = norm::l2(input(p) - marker(q));
+ double dist = norm::l2(ref(p) - marker(q));
if (dist < min_dist)
{
min_dist = dist;
@@ -107,9 +108,19 @@
}
}
if (same_side)
+ {
+ if (output(p) != marker(v))
+ stable = false;
output(p) = marker(v);
+ }
else
- output(p) = input(p);
+ {
+ if (output(p) != ref(p))
+ stable = false;
+ output(p) = ref(p);
+ }
+ }
+ level::paste(output, ref);
}
trace::exiting("morpho::impl::general_on_set_centered__autarkical_leveling");
Index: abraham/mln/morpho/vmt.hh
--- abraham/mln/morpho/vmt.hh (revision 0)
+++ abraham/mln/morpho/vmt.hh (revision 0)
@@ -0,0 +1,126 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// 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, 51 Franklin Street, Fifth Floor,
+// 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 MLN_MORPHO_VMT_HH
+# define MLN_MORPHO_VMT_HH
+
+/// \file mln/morpho/vector_median.hh
+///
+/// Morphological vector median filter.
+///
+/// \todo The overloads are hidden and I don't know why!
+
+# include <mln/morpho/includes.hh>
+# include <mln/morpho/general.hh>
+# include <mln/accu/land.hh>
+# include <mln/accu/land_basic.hh>
+# include <mln/accu/min.hh>
+# include <mln/accu/min_h.hh>
+# include <mln/norm/l2.hh>
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ /// Morphological vector_median.
+ template <typename I, typename W>
+ mln_concrete(I)
+ vmt(const Image<I>& input, const Window<W>& win);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ // On set with centered window (overloads).
+
+ template <typename I, typename W>
+ mln_concrete(I)
+ vmt(const Image<I>& input_, const Window<W>& win_)
+ {
+ trace::entering("morpho::impl::general_on_set_centered__vector_median");
+
+ typedef mln_concrete(I) O;
+ const I& input = exact(input_);
+ const W& win = exact(win_);
+
+ O output;
+ output = clone(input);
+
+ mln_piter(I) p(input.domain());
+ mln_qiter(W) q(win, p);
+ for_all(p)
+ {
+ mln_psite(W) v;
+ double min_dist = std::numeric_limits<double>::infinity();
+ for_all(q) if (input.domain().has(q))
+ {
+ double dist = norm::l2(input(p) - input(q));
+ if (dist < min_dist)
+ {
+ min_dist = dist;
+ v = q;
+ }
+ }
+ output(p) = input(v);
+ }
+
+ trace::exiting("morpho::impl::general_on_set_centered__vector_median");
+ return output;
+ }
+
+
+ } // end of namespace morpho::impl
+
+
+ template <typename I, typename W>
+ inline
+ mln_concrete(I)
+ vmt(const Image<I>& input, const Window<W>& win)
+ {
+ trace::entering("morpho::vector_median");
+ mln_precondition(exact(input).has_data());
+ mln_precondition(! exact(win).is_empty());
+
+ mln_concrete(I) output = impl::vector_median(input, win);
+
+ trace::exiting("morpho::vector_median");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_VMT_HH
Index: abraham/mln/morpho/vector_median.hh
--- abraham/mln/morpho/vector_median.hh (revision 3055)
+++ abraham/mln/morpho/vector_median.hh (working copy)
@@ -84,7 +84,7 @@
double min_dist = std::numeric_limits<double>::infinity();
for_all(q) if (input.domain().has(q))
{
- double dist = 0;
+ double dist = norm::l2(input(p) - input(q));
for_all(r) if (input.domain().has(r) && q!=r)
dist += norm::l2(input(r) - input(q));
if (dist < min_dist)
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Alexandre Abraham <abraham(a)lrde.epita.fr>
Add functors and HSL color space.
* mln/core/image/violent_cast_image.hh: New
Add capacity to cast value passing by void *.
* mln/core/concept/meta_fun.hh: New
Meta function concept.
* mln/math/cos.hh: New
Cosinus operation.
* mln/math/acos.hh: New
Arc cosinus operation.
* mln/math/all.hh:
Add cosinus and arcosinus headers.
* mln/value/mixin.hh: New
Allow operator addition to values.
* mln/value/hsl.hh: New
New color space.
* mln/value/shell.hh: New
Value allowing to set values when using bijective functions.
* mln/fun/meta/hue.hh:
Functor allowing direct access to hue.
* mln/fun/meta/inty.hh:
Functor allowing direct access to intensity.
* mln/fun/meta/sat.hh:
Functor allowing direct access to saturation.
* mln/fun/meta/to_enc.hh:
Functor allowing direct access to encoding.
* mln/fun/meta/red.hh:
Fix trailing ;.
* mln/fun/v2v/rgb_to_hsl.hh: New
Conversion form rgb to hsl and vice versa.
topo_wst.hh | 419 +++++++++++++++++++++++++++++-------------------------------
1 file changed, 209 insertions(+), 210 deletions(-)
Index: sandbox/abraham/mln/morpho/topo_wst.hh
--- sandbox/abraham/mln/morpho/topo_wst.hh (revision 3153)
+++ sandbox/abraham/mln/morpho/topo_wst.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -52,6 +52,42 @@
namespace morpho
{
+ template <class I>
+ mln_site(I) min (const Image<I> &ima_, p_set<mln_site(I)>& components)
+ {
+ const I& ima = exact(ima_);
+
+ if (components.nsites() == 0)
+ return mln_site(I)(-1, -1); // FIXME
+
+ typename p_set<mln_site(I)>::fwd_piter it(components);
+ mln_site(I) min = components[0];
+
+ for_all(it)
+ if (ima(it) < ima(min))
+ min = it;
+
+ return min;
+ }
+
+ template <class I>
+ mln_site(I) max (p_set<mln_site(I)>& components)
+ {
+ if (components.nsites() == 0)
+ return mln_site(I)(-1, -1); // FIXME
+
+ typename p_set<mln_site(I)>::fwd_piter it(components);
+ mln_site(I) max = components[0];
+
+ for_all(it)
+ if (ima(it) > ima(max))
+ max = it;
+
+ return max;
+ }
+
+
+
template <class I, class N>
struct topo_wst
{
@@ -59,6 +95,8 @@
// Typedefs
// --------
typedef mln_site(I) site;
+ typedef I image_t;
+ typedef N neighborhood_t;
// Component tree management
// -------------------------
@@ -88,14 +126,10 @@
// children.append(n);
children.push_back(p);
}
-
- mln_value(I) min() { return mln_min(mln_value(I)); }
- mln_value(I) max() { return mln_max(mln_value(I)); }
- void revert () { level = max() - level + min(); }
-
}; // struct node
- const mln_exact(N)& nbh;
+ public:
+
mln_ch_value(I, site) Par_node;
mln_ch_value(I, site) Par_tree;
@@ -105,10 +139,11 @@
mln_ch_value(I, node) nodes;
site Root;
+ private:
+
void MakeSet_tree(site x);
void MakeSet_node(site x);
site Find_tree(site x);
- void swap(site& x, site& y);
site Find_node(site x);
void BuildComponentTree();
site MergeNode(site& node1, site& node2);
@@ -116,10 +151,6 @@
site Link_node(site x, site y);
node MakeNode(int level);
-
- // Watershed algorithm
- // -------------------
-
private:
mln_ch_value(I, bool) isproc;
@@ -128,10 +159,9 @@
topo_wst(const Image<I>& i,
const Neighborhood<N>& n);
-
- // Result
public:
- mln_exact(I) pima;
+ const I &ima;
+ const N &nbh;
public:
void go();
@@ -141,12 +171,12 @@
site max (p_set<site>& components);
bool highest_fork (p_set<site>& components);
bool highest_fork (p_set<site>& components, site &r);
- bool w_constructible(site p, site &r);
- bool w_constructible(site p);
- void topo_watershed();
-
// Optimized LCA Algorithm
+
+ public:
+ site lca (site a, site b);
+
private:
int *euler;
int *depth;
@@ -161,7 +191,6 @@
void build_euler_tour_rec(site p, int &position, int d);
void build_euler_tour();
void build_minim ();
- site lca (site a, site b);
void removeOneSonNodes(site *p, mln_ch_value(I, site) &newPar_node);
void compressTree();
}; // struct topo_wst
@@ -172,15 +201,15 @@
template <class I, class N>
topo_wst<I, N>::topo_wst(const Image<I>& i,
const Neighborhood<N>& n)
- : nbh(exact(n)),
- Par_node(exact(i).domain(), exact(i).border()),
+ : Par_node(exact(i).domain(), exact(i).border()),
Par_tree(exact(i).domain(), exact(i).border()),
Rnk_tree(exact(i).domain(), exact(i).border()),
Rnk_node(exact(i).domain(), exact(i).border()),
subtreeRoot(exact(i).domain(), exact(i).border()),
nodes(exact(i).domain(), exact(i).border()),
isproc(exact(i).domain(), exact(i).border()),
- pima(exact(i))
+ ima(exact(i)),
+ nbh(exact(n))
{
}
@@ -207,14 +236,6 @@
}
template <class I, class N>
- void topo_wst<I, N>::swap(site& x, site& y)
- {
- site memo = x;
- x = y;
- y = memo;
- }
-
- template <class I, class N>
typename topo_wst<I, N>::site topo_wst<I, N>::Find_node(site x)
{
if (Par_node(x) != x)
@@ -227,16 +248,9 @@
{
BuildComponentTree();
compressTree();
- arith::revert_inplace(pima);
- // arith::revert_inplace(nodes);
- mln_piter(image2d<node>) p (nodes.domain());
- for_all(p)
- nodes(p).revert();
build_euler_tour();
build_minim();
- topo_watershed();
- arith::revert_inplace(pima);
}
template <class I, class N>
@@ -246,7 +260,7 @@
// Sort the sites in increasing order
p_array<mln_site(I)> S;
- S = level::sort_psites_increasing(pima);
+ S = level::sort_psites_increasing(ima);
// Clear the marker map
data::fill(isproc, false);
@@ -258,7 +272,7 @@
// if (subtreeRoot.hold(p))
subtreeRoot(p) = p;
// if (nodes.hold(p))
- nodes(p) = MakeNode(pima(p));
+ nodes(p) = MakeNode(ima(p));
}
@@ -273,7 +287,7 @@
mln_niter(N) q(nbh, ip);
for_all(q)
- if (pima.has(q) and isproc(q) and pima(q) <= pima(p))
+ if (ima.has(q) and isproc(q) and ima(q) <= ima(p))
{
site adjCanonicalElt = Find_tree(q);
site adjNode = Find_node(subtreeRoot(adjCanonicalElt));
@@ -333,7 +347,7 @@
typename topo_wst<I, N>::site topo_wst<I, N>::Link_tree(site x, site y)
{
if (Rnk_tree(x) > Rnk_tree(y))
- swap(x, y);
+ std::swap(x, y);
else
if (Rnk_tree(x) == Rnk_tree(y))
Rnk_tree(y) += 1;
@@ -345,7 +359,7 @@
typename topo_wst<I, N>::site topo_wst<I, N>::Link_node(site x, site y)
{
if (Rnk_node(x) > Rnk_node(y))
- swap(x, y);
+ std::swap(x, y);
else
if (Rnk_node(x) == Rnk_node(y))
Rnk_node(y) += 1;
@@ -363,38 +377,6 @@
return n;
}
- template <class I, class N>
- typename topo_wst<I, N>::site topo_wst<I, N>::min (p_set<site>& components)
- {
- if (components.nsites() == 0)
- return site(-1, -1);
-
- typename p_set<site>::fwd_piter it(components);
- site min = components[0];
-
- for_all(it)
- if (pima(it.to_site()) < pima(min))
- min = it.to_site();
-
- return min;
- }
-
- template <class I, class N>
- typename topo_wst<I, N>::site topo_wst<I, N>::max (p_set<site>& components)
- {
- if (components.nsites() == 0)
- return site(-1, -1);
-
- typename p_set<site>::fwd_piter it(components);
- site max = components[0];
-
- for_all(it)
- if (pima(it.to_site()) > pima(max))
- max = it.to_site();
-
- return max;
- }
-
template <class I, class N>
bool topo_wst<I, N>::highest_fork (p_set<site>& components, site &r)
@@ -435,140 +417,6 @@
}
template <class I, class N>
- bool topo_wst<I, N>::w_constructible(site p) {
- site i;
- return w_constructible(p, i);
- }
-
- template <class I, class N>
- bool topo_wst<I, N>::w_constructible(site p, site &r)
- {
- mln_niter(N) q(nbh, p);
- p_set<site> v;
-
- for_all(q)
- if (pima.has(q) && pima(q) > pima(p))
- v.insert(Par_node(q));
-
- if (v.nsites() == 0)
- return false;
-
- if (v.nsites() == 1) {
- r = v[0];
- return true;
- }
-
- site
- c = max(v),
- cmax = c;
-
- typename p_set<site>::fwd_piter it(v);
- for_all(it)
- {
- // Can't remove the site from the set
- if (it.to_site() == cmax)
- continue;
-
- site c1 = lca(c, it.to_site());
-
- if (c1 != it.to_site())
- c = c1;
- }
-
- if (nodes(c).level <= pima(p))
- return false;
-
- r = c;
- return true;
- }
-
-
- template <class I, class N>
- void topo_wst<I, N>::topo_watershed()
- {
- // Maxima components
- mln_ch_value(I, bool) cmax(pima.domain(), pima.border());
-
- // Mark enqueued sites
- mln_ch_value(I, bool) enqueued(pima.domain(), pima.border());
-
- p_priority< mln_value(I), p_queue_fast<site> > l;
- // p_queue < site > m;
- std::queue<site> m;
- mln_value(I) max = mln_max(mln_value(I));
-
- std::cout << "Init" << std::endl;
-
- // Flag C-maxima
- data::fill(cmax, false);
- data::fill(enqueued, false);
-
- mln_piter(I) it(Par_node.domain());
- for_all(it)
- // if (nodes(Par_node(it.to_site())).children.nsites() == 0)
- if (nodes(Par_node(it.to_site())).children.size() == 0)
- {
- cmax(it.to_site()) = true;
- m.push(it.to_site());
- }
-
- while (!m.empty())
- {
- mln_niter(N) q(nbh, m.front());
- for_all(q)
- if (cmax.has(q) && !cmax(q) && !enqueued(q))
- {
- enqueued(q) = true;
- l.push(pima(q), q);
- }
- m.pop();
- }
-
-
- std::cout << "end" << std::endl;
-
- // Main loop
- while (!l.is_empty())
- {
- site x = l.front();
- l.pop();
- enqueued(x) = false;
-
- site c;
- bool is_w = w_constructible(x, c);
-
- if (is_w)
- {
- pima(x) = nodes(c).level;
- Par_node(x) = c;
-
- // if (nodes(c).children.nsites() == 0)
- if (nodes(c).children.size() == 0)
- cmax(x) = true;
- else
- // if (nodes(c).children.nsites() > 1)
- if (nodes(c).children.size() == 1)
- std::cerr << "ERREUR COMPOSANTE BRANCHE " << nodes(c).children.size() << std::endl;
-
-
- mln_niter(N) q(nbh, x);
- for_all(q)
- if (pima.has(q) && !cmax(q) && !enqueued(q))
- {
- enqueued(q) = true;
-
- l.push(pima(q), q);
- }
- } // if (c != site(-1, -1))
- } // while(!l.empty())
-
- for_all(it)
- pima(it.to_site()) = nodes(Par_node(it.to_site())).level;
- }
-
-
-
- template <class I, class N>
void topo_wst<I, N>::compute_ctree_size (site p)
{
ctree_size += 1;
@@ -739,6 +587,157 @@
Par_node(p) = newPar_node(Par_node(p));
}
+ template <class T>
+ bool w_constructible(T &tree, typename T::site p, typename T::site &r)
+ {
+
+ typedef typename T::image_t I;
+ typedef typename T::neighborhood_t N;
+
+ const I &ima = exact(tree.ima);
+ const N &nbh = exact(tree.nbh);
+
+ mln_niter(N) q(nbh, p);
+ p_set<mln_site(I)> v;
+
+ for_all(q)
+ if (ima.domain().has(q) && ima(q) < ima(p))
+ v.insert(tree.Par_node(q));
+
+ if (v.nsites() == 0)
+ return false;
+
+ if (v.nsites() == 1) {
+ r = v[0];
+ return true;
+ }
+
+ mln_site(I)
+ c = min(ima, v),
+ cmin = c;
+
+ typename p_set<mln_site(I)>::fwd_piter it(v);
+ for_all(it)
+ {
+ // Can't remove the site from the set
+ if (it.to_site() == cmin)
+ continue;
+
+ mln_site(I) c1 = tree.lca(c, it);
+
+ if (c1 != it)
+ c = c1;
+ }
+
+ if (tree.nodes(c).level >= ima(p))
+ return false;
+
+ r = c;
+ return true;
+ }
+
+ template <class T>
+ bool w_constructible(T &tree, typename T::site p) {
+ typename T::site r;
+ return w_constructible(tree, p, r);
+ }
+
+
+
+ template <class T>
+ typename T::image_t topo_watershed(T &tree)
+ {
+
+ typedef typename T::image_t I;
+ typedef typename T::neighborhood_t N;
+
+ I ima = exact(tree.ima);
+ const N &nbh = exact(tree.nbh);
+
+ // Maxima components
+ mln_ch_value(I, bool) cmax(ima.domain(), ima.border());
+
+ // Mark enqueued sites
+ mln_ch_value(I, bool) enqueued(ima.domain(), ima.border());
+
+ p_priority< mln_value(I), p_queue_fast<mln_site(I)> > l;
+ // p_queue < site > m;
+ std::queue<mln_site(I)> m;
+ mln_value(I) min = mln_min(mln_value(I));
+
+ std::cout << "Init" << std::endl;
+
+ // Flag C-maxima
+ data::fill(cmax, false);
+ data::fill(enqueued, false);
+
+ mln_piter(I) it(tree.Par_node.domain());
+ for_all(it)
+ // if (nodes(Par_node(it.to_site())).children.nsites() == 0)
+ if (tree.nodes(tree.Par_node(it)).children.size() == 0)
+ {
+ cmax(it) = true;
+ m.push(it);
+ }
+
+ while (!m.empty())
+ {
+ mln_niter(N) q(nbh, m.front());
+ for_all(q)
+ if (cmax.domain().has(q) && !cmax(q) && !enqueued(q))
+ {
+ enqueued(q) = true;
+ l.push(mln_max(mln_value(I)) - ima(q), q);
+ }
+ m.pop();
+ }
+
+
+ std::cout << "end" << std::endl;
+
+ // Main loop
+ while (!l.is_empty())
+ {
+ mln_site(I) x = l.front();
+ l.pop();
+ enqueued(x) = false;
+
+ mln_site(I) c;
+ bool is_w = w_constructible(tree, x, c);
+
+ if (is_w)
+ {
+ ima(x) = tree.nodes(c).level;
+ tree.Par_node(x) = c;
+
+ // if (nodes(c).children.nsites() == 0)
+ if (tree.nodes(c).children.size() == 0)
+ cmax(x) = true;
+ else
+ // if (nodes(c).children.nsites() > 1)
+ if (tree.nodes(c).children.size() == 1)
+ std::cerr << "ERREUR COMPOSANTE BRANCHE " << tree.nodes(c).children.size() << std::endl;
+
+
+ mln_niter(N) q(nbh, x);
+ for_all(q)
+ if (ima.domain().has(q) && !cmax(q) && !enqueued(q))
+ {
+ enqueued(q) = true;
+ l.push(mln_max(mln_value(I)) - ima(q), q); // FIXME : just invert the priority
+ }
+ }
+ } // while(!l.empty())
+
+ for_all(it)
+ ima(it) = tree.nodes(tree.Par_node(it)).level;
+
+ return ima;
+ }
+
+
+
+
# endif // MLN_INCLUDE_ONLY
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Start Laurent's ISMM 2009 code.
* laurent/ismm2009.cc: New.
ismm2009.cc | 582 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 582 insertions(+)
Index: laurent/ismm2009.cc
--- laurent/ismm2009.cc (revision 0)
+++ laurent/ismm2009.cc (revision 0)
@@ -0,0 +1,582 @@
+#include <vector>
+#include <algorithm>
+
+#include <mln/core/var.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/make/double_neighb2d.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_8.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/util/ord_pair.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/routine/extend.hh>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/paste.hh>
+
+#include <mln/labeling/regional_minima.hh>
+#include <mln/labeling/compute.hh>
+
+#include <mln/accu/count.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+
+
+namespace mln
+{
+
+ // Functions.
+
+ inline
+ bool is_row_odd(const point2d& p)
+ {
+ return p.row() % 2;
+ }
+
+ inline
+ bool is_edge(const point2d& p)
+ {
+ return p.row() % 2 + p.col() % 2 == 1;
+ }
+
+ inline
+ bool is_pixel(const point2d& p)
+ {
+ return p.row() % 2 == 0 && p.col() % 2 == 0;
+ }
+
+ inline
+ bool is_point(const point2d& p)
+ {
+ return p.row() % 2 && p.col() % 2;
+ }
+
+
+ // Neighborhoods.
+
+ typedef neighb< win::multiple<window2d, bool(*)(const point2d&)> > dbl_neighb2d;
+
+ const dbl_neighb2d& e2p() // Edge (1D face) to neighboring original pixels (2D faces).
+ {
+ static bool e2p_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ static bool e2p_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+ static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2p_h, e2p_v);
+ return nbh;
+ }
+
+ const dbl_neighb2d& e2e() // Edge to neighboring edges.
+ {
+ static bool e2e_h[] = { 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0 };
+ static bool e2e_v[] = { 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0 };
+ static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2e_h, e2e_v);
+ return nbh;
+ }
+
+
+ inline
+ point2d p1_from_e(const point2d& e)
+ {
+ return e + (is_row_odd(e) ? up : left);
+ }
+
+ inline
+ point2d p2_from_e(const point2d& e)
+ {
+ return e + (is_row_odd(e) ? down : right);
+ }
+
+
+ // Transform to make room for edges.
+
+ template <typename T>
+ image2d<T>
+ add_edges(const image2d<T>& input)
+ {
+ image2d<T> output(2 * input.nrows() - 1,
+ 2 * input.ncols() - 1);
+ data::fill(output, 0); // Useless but for display!
+ for (int row = 0; row < input.nrows(); ++row)
+ for (int col = 0; col < input.ncols(); ++col)
+ opt::at(output, 2 * row, 2 * col) = opt::at(input, row, col);
+ return output;
+ }
+
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ magnitude(const I& input, const N& nbh)
+ {
+ mln_concrete(I) output;
+ initialize(output, input);
+ data::fill(output, 0);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ n.start();
+ mln_value(I) v1 = input(n);
+ n.next();
+ mln_value(I) v2 = input(n);
+ output(p) = v2 > v1 ? v2 - v1 : v1 - v2;
+ }
+
+ return output;
+ }
+
+
+ template <typename I, typename N>
+ mln_ch_value(I, util::ord_pair<mln_value(I)>)
+ adjacency(const I& input, const N& nbh)
+ {
+ typedef mln_value(I) L;
+ typedef util::ord_pair<L> LL;
+
+ mln_ch_value(I, LL) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ if (input(p) == 0) // Watershed edge.
+ {
+ L l1 = 0, l2 = 0;
+ for_all(n)
+ if (input.has(n) && input(n) != 0)
+ {
+ if (l1 == 0) // First label to be stored.
+ l1 = input(n);
+ else
+ if (input(n) != l1 && l2 == 0) // Second label to be stored.
+ l2 = input(n);
+ else
+ mln_invariant(input(n) == l1 || input(n) == l2);
+ }
+ mln_invariant(l1 != 0 && l2 != 0);
+ output(p) = LL(l1, l2);
+ }
+ else
+ {
+ L l = input(p);
+ output(p) = LL(l, l);
+ // Tests:
+ for_all(n)
+ if (input.has(n))
+ mln_invariant(input(n) == 0 || input(n) == l);
+ }
+ }
+
+ return output;
+ }
+
+
+
+
+ // Get the smallest edge out of a basin.
+ //
+ // Version with the watershed extended to all faces.
+
+ template <typename W, typename N, typename G>
+ std::vector<mln_site(W)> // FIXME: Use p_array!
+ smallest_edges(const W& wst, unsigned nlabels,
+ const N& nbh, // edge (1D-face) -> pixels (2D-faces)
+ const G& g)
+ {
+ typedef mln_value(W) L;
+ std::vector<mln_site(W)> edge(nlabels + 1);
+ std::vector<L> g_min(nlabels + 1);
+ std::fill(g_min.begin(), g_min.end(), mln_max(mln_value(G)));
+ mln_piter(W) e(wst.domain());
+ mln_niter(N) n(nbh, e);
+ for_all(e)
+ {
+ mln_invariant(wst(e) == 0); // Watershed line only.
+ n.start();
+ L l1 = wst(n);
+ n.next();
+ L l2 = wst(n);
+ if (g(e) < g_min[l1])
+ {
+ g_min[l1] = g(e);
+ edge[l1] = e;
+ }
+ if (g(e) < g_min[l2])
+ {
+ g_min[l2] = g(e);
+ edge[l2] = e;
+ }
+ }
+ return edge;
+ }
+
+
+
+ // Get the smallest edge out of a basin.
+ //
+ // Version with the watershed on edges only (not extended to other faces).
+ // This is an ALTERNATE version (just to test that we get the same result
+ // as the "regular" version given above).
+
+ template <typename W, typename N, typename G>
+ std::vector<mln_site(W)>
+ smallest_edges_alt(const W& wst, unsigned nlabels,
+ const N& nbh, // edge -> edges
+ const G& g)
+ {
+ typedef mln_value(W) L;
+ std::vector<mln_site(W)> edge(nlabels + 1);
+ std::vector<L> g_min(nlabels + 1);
+ std::fill(g_min.begin(), g_min.end(), mln_max(mln_value(G)));
+ mln_piter(W) e(wst.domain());
+ mln_niter(N) n(nbh, e);
+ for_all(e) if (wst(e) == 0) // Watershed edge.
+ {
+ L l1 = 0, l2 = 0;
+ for_all(n)
+ if (wst.has(n) && wst(n) != 0)
+ {
+ if (l1 == 0) // First label.
+ l1 = wst(n);
+ else
+ if (wst(n) != l1 && l2 == 0) // Second label.
+ l2 = wst(n);
+ else
+ mln_invariant(wst(n) == l1 || wst(n) == l2);
+ }
+ mln_invariant(l1 != 0 && l2 != 0);
+ if (g(e) < g_min[l1])
+ {
+ g_min[l1] = g(e);
+ edge[l1] = e;
+ }
+ if (g(e) < g_min[l2])
+ {
+ g_min[l2] = g(e);
+ edge[l2] = e;
+ }
+ }
+ return edge;
+ }
+
+
+
+ // Sort attributes.
+
+ template <typename A, typename L>
+ std::vector< std::pair<A,L> >
+ sort_attributes(const util::array<A>& a, L n_basins)
+ {
+ typedef std::pair<A,L> pair_t;
+ std::vector<pair_t> v(n_basins.next());
+
+ v[0] = pair_t(mln_min(A), 0); // First elt, even after sorting.
+
+ for (L l = 1; l <= n_basins; ++l)
+ v[l] = pair_t(a[l], l);
+
+ std::sort(v.begin(), v.end());
+
+ return v;
+ }
+
+
+ // Find root.
+
+ template <typename L>
+ inline
+ L find_root(std::vector<L>& par, L l)
+ {
+ if (par[l] == l)
+ return l;
+ else
+ return par[l] = find_root(par, par[l]);
+ }
+
+
+
+ // Display.
+
+ template <typename I>
+ I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+ data::fill(output, bg);
+ mln_VAR( edge, ima | is_edge );
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ opt::at(output, row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ opt::at(output, row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+
+} // end of namespace mln
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm" << std::endl;
+ std::cerr << "Laurent ISMM 2009 scheme." << std::endl;
+ abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::label_8;
+
+ if (argc != 2)
+ usage(argv);
+
+ image2d<int_u8> raw_f;
+ io::pgm::load(raw_f, argv[1]);
+ debug::println("raw_f:", raw_f);
+
+ image2d<int_u8> f_ = add_edges(raw_f);
+ debug::println("f_:", f_);
+
+ mln_VAR(f, f_ | is_pixel);
+ debug::println("f:", f);
+
+ mln_VAR(g, f_ | is_edge);
+ data::fill(g, magnitude(extend(f_ | is_edge, pw::value(f_)),
+ e2p()));
+ debug::println("g:", g);
+
+ // surprise:
+ debug::println("g without the 'edge' predicate:", g.unmorph_());
+
+
+ typedef label_8 L; // Type of labels.
+
+
+ L n_regmins;
+ mln_VAR( regmin_g,
+ labeling::regional_minima(g, e2e(), n_regmins) );
+ debug::println("regmin(g):", regmin_g);
+
+ L n_basins;
+ mln_VAR( wst_g,
+ morpho::meyer_wst(g, e2e(), n_basins) );
+ mln_invariant(n_basins == n_regmins);
+ debug::println("wst(g):", wst_g);
+
+
+ // Just to see things.
+ mln_VAR(adj, adjacency(wst_g, e2e()));
+ debug::println("adjacency:", adj | (pw::value(wst_g) == pw::cst(0)));
+
+
+ /* // Délire!
+ {
+ box2d b = make::box2d(1,1, n_basins, n_basins);
+ point2d null(0, 0);
+ image2d<point2d> adj_edge(b);
+ data::fill(adj_edge, null);
+
+ mln_piter_(adj_t) e(adj.domain());
+ for_all(e)
+ if (adj(e).first() != adj(e).second())
+ adj_edge.at_(adj(e).first(), adj(e).second()) = e;
+
+ debug::println(adj_edge);
+ }
+ */
+
+
+ image2d<L> wst_g_full = wst_g.unmorph_();
+ {
+ // edges (1D-faces) -> pixels (2D-faces)
+ mln_VAR(w_pixels, wst_g_full | is_pixel);
+ data::paste(morpho::dilation(extend(w_pixels, pw::value(wst_g_full)),
+ c4().win()),
+ wst_g_full);
+ // edges (1D-faces) -> points (0D-faces)
+ mln_VAR(w_points, wst_g_full | is_point);
+ data::paste(morpho::erosion(extend(w_points, pw::value(wst_g_full)),
+ c4().win()),
+ wst_g_full);
+ }
+ debug::println("wst(g) fully valuated:", wst_g_full);
+
+
+ // Depict the watershed line.
+ mln_VAR(is_line, pw::value(wst_g_full) == pw::cst(0));
+ debug::println("wst(g) line:", wst_g | is_line);
+
+
+
+ // Get the smallest esge out of every basin.
+
+ std::vector<point2d> edge = smallest_edges(extend(wst_g | is_line, wst_g_full),
+ n_basins, e2p(), g);
+ for (L l = 1; l <= n_basins; ++l)
+ std::cout << int(l) << ": " << edge[l] << std::endl;
+
+
+// {
+// // Test the result with an alternate code.
+// std::vector<point2d> edge_alt = smallest_edges_alt(wst_g, n_basins, e2e(), g);
+// for (L l = 1; l <= n_basins; ++l)
+// mln_invariant(edge_alt[l] == edge[l]);
+// }
+
+
+
+ // Compute an attribute per region.
+
+ typedef unsigned A;
+ util::array<A> a = labeling::compute(accu::meta::count(),
+ g,
+ wst_g,
+ n_basins);
+
+ typedef std::pair<A,L> pair_t;
+ std::vector<pair_t> v = sort_attributes(a, n_basins); // Sort regions.
+
+
+ std::cout << "attributes = ";
+ for (unsigned i = 1; i <= n_basins; ++i)
+ std::cout << v[i].first // Attribute (increasing).
+ << ':'
+ << v[i].second // Region label.
+ << " - ";
+ std::cout << std::endl;
+
+
+ std::vector<L> lpar(n_basins.next());
+ for (L l = 1; l <= n_basins; ++l)
+ lpar[l] = l; // Make-set.
+
+
+ util::array<A> a_merged = a;
+ for (unsigned i = 1; i <= n_basins; ++i)
+ {
+ L l = v[i].second, // Region label.
+ lr = find_root(lpar, l);
+
+ point2d e = edge[l]; // FIXME: Use the heap!
+
+ mln_invariant(wst_g_full(p1_from_e(e)) == l ||
+ wst_g_full(p2_from_e(e)) == l);
+ L l2 = ( wst_g_full(p1_from_e(e)) == l ?
+ wst_g_full(p2_from_e(e)) :
+ wst_g_full(p1_from_e(e)) ),
+ l2r = find_root(lpar, l2);
+
+ if (lr == l2r)
+ continue; // Already merged.
+ if (l2r < lr)
+ std::swap(lr, l2r);
+ mln_invariant(l2r > lr);
+ lpar[lr] = l2r;
+ a_merged[l2r] += lr; // FIXME: We want accumulators here!
+ }
+
+ for (unsigned i = 1; i <= n_basins; ++i)
+ {
+ L l = v[i].second;
+ std::cout << l << " -> " << lpar[l] << std::endl;
+ }
+
+
+} // end of main
+
+
+
+
+/*
+
+
+for (i=0; i<V; i++) // Initialiser les heaps de fibonacci
+{
+ fh_setcmp(G->hp[i], cmp); // Chaque region a une heap de ses edges
+}
+
+forall edges z that separates two regions v and w
+{
+ fh_insert(G->hp[v], (void *)(z)); // Ajouter les edges dans les heaps
+ fh_insert(G->hp[w], (void *)(z));
+}
+
+UFinit(G->V); // Initialiser l'union-find
+
+// Parcourir les regions par attribut croissant
+for (j=0; j<V-1; j++)
+{
+ i = find(j);
+
+ do
+ { // trouver l'edge minimum qui sorte de la region
+ e = fh_extractmin(G->hp[i]);
+ }
+ while ((UFfind(e->v, e->w)) && (e !=NULL));
+
+ if (e != NULL)
+ { // Normalement, e != NULL, sinon c'est un BIG pb!!!
+ int ui, uj, uk;
+ ui = find(e->v);
+ uj = find(e->w);
+ uk = UFunion(e->v,e->w); // Merger les regions
+ if (uk == ui)
+ { // et merger les edges
+ G->hp[ui] = fh_union(G->hp[ui], G->hp[uj]);
+ }
+ else
+ {
+ G->hp[uj] = fh_union(G->hp[uj], G->hp[ui]);
+ }
+ mst[k] = *e; // Garder l'arete
+ SaliencyWeight[k] = attribut[ui];// Poids dans la nouvelle hierarchie
+ OldWeight[k] = e->weight; // Poids dans l'ancienne hierarchie (inutile)
+ k++;
+ }
+
+ // Calcul de la sortie
+ Pour toutes les edges separantes z=(x,y)
+ {
+ S[z] = max {SaliencyWeight[k] | sur le chemin reliant x a y dans mst}
+ }
+}
+
+
+ */
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Rename theo's sandbox.
* geraud: Rename as...
* theo: ...this.
* geraud/skel.cc,
* geraud/fllt.cc,
* geraud/test_attribute.cc,
* geraud/fllt.svg.6.cc,
* geraud/p_runs__with_dedicated_piter.hh,
* geraud/win_fun.cc,
* geraud/browsing,
* geraud/browsing/fwd.cc,
* geraud/browsing/fwd.hh,
* geraud/cs2d,
* geraud/cs2d/cs2d.cc,
* geraud/cs2d/tuto.cc,
* geraud/cs2d/kruskal.cc,
* geraud/cs2d/cs2d_utils.hh,
* geraud/cs2d/cs2d.hh,
* geraud/cs2d/dbl_neighb.hh,
* geraud/cs2d/cs2d_morpho.hh,
* geraud/dead,
* geraud/dead/inplace.hh,
* geraud/dead/instant.hh,
* geraud/fllt,
* geraud/fllt/fllt.hh,
* geraud/fllt/simple_tests.cc,
* geraud/fllt/compute_fllt.cc,
* geraud/fllt/fllt.svg.1.cc,
* geraud/fllt/fllt.svg.7.hh,
* geraud/fllt/fllt_tree_to_image.hh,
* geraud/fllt/fllt.svg.2.cc,
* geraud/fllt/fllt.svg.3.cc,
* geraud/fllt/fllt.svg.4.cc,
* geraud/fllt/fllt.svg.5.cc,
* geraud/fllt/fllt.svg.6.cc,
* geraud/fllt/connected_filters,
* geraud/fllt/connected_filters/area_filter.cc,
* geraud/fllt/connected_filters/canonize_tree.hh,
* geraud/fllt/connected_filters/pseudo_flat_zones.cc,
* geraud/fllt/connected_filters/area_filter.hh,
* geraud/fllt/fllt_test.hh,
* geraud/fllt.svg.7.hh,
* geraud/win_fun.hh,
* geraud/Rd,
* geraud/Rd/hybrid.hh,
* geraud/Rd/queue_based.hh,
* geraud/Rd/parallel.cc,
* geraud/Rd/parallel_wo.cc,
* geraud/Rd/union_find.hh,
* geraud/Rd/parallel.hh,
* geraud/Rd/diff.cc,
* geraud/Rd/sequential_bench.cc,
* geraud/Rd/sequential.cc,
* geraud/Rd/deco.cc,
* geraud/Rd/utils.hh,
* geraud/Rd/diff_pgm.cc,
* geraud/Rd/hybrid.cc,
* geraud/Rd/queue_based.cc,
* geraud/Rd/sequential_bench.hh,
* geraud/Rd/min.cc,
* geraud/Rd/sequential.hh,
* geraud/Rd/debase.union_find.hh,
* geraud/Rd/union_find.cc,
* geraud/Rd/svg.queue_based.hh,
* geraud/dmap.cc,
* geraud/compute_parent_more.hh,
* geraud/tufa_2008,
* geraud/tufa_2008/steps.0.cc,
* geraud/tufa_2008/steps.1.cc,
* geraud/tufa_2008/gradient.cc,
* geraud/tufa_2008/closing.cc,
* geraud/tufa_2008/steps.2.cc,
* geraud/tufa_2008/opening.cc,
* geraud/tufa_2008/steps.3.cc,
* geraud/tufa_2008/steps.2b.cc,
* geraud/tufa_2008/filter_n.cc,
* geraud/tufa_2008/wst_f_equal_wst_a.cc,
* geraud/tufa_2008/compute_a.cc,
* geraud/tufa_2008/wst.cc,
* geraud/tufa_2008/experiment.cc,
* geraud/tufa_2008/n_cmpt.cc,
* geraud/tufa_2008/filter.cc,
* geraud/tufa_2008/closed_gradient.cc,
* geraud/tufa_2008/fz_count.cc,
* geraud/tufa_2008/regmin_count.cc,
* geraud/estimate.hh,
* geraud/laurent,
* geraud/laurent/wst_edge.cc,
* geraud/laurent/wst2d.cc,
* geraud/laurent/classif.cc,
* geraud/laurent/wst3d.cc,
* geraud/laurent/segmentation.hh,
* geraud/irm.cc,
* geraud/color,
* geraud/color/sum_pix.hh,
* geraud/color/segment.cc,
* geraud/color/blen_pix.hh: Move into...
* theo: ...this new directory.
* laurent: New directory.
Rd/debase.union_find.hh | 165 ----
Rd/deco.cc | 71 -
Rd/diff.cc | 28
Rd/diff_pgm.cc | 43 -
Rd/hybrid.cc | 53 -
Rd/hybrid.hh | 117 --
Rd/min.cc | 42 -
Rd/parallel.cc | 54 -
Rd/parallel.hh | 85 --
Rd/parallel_wo.cc | 46 -
Rd/queue_based.cc | 51 -
Rd/queue_based.hh | 124 ---
Rd/sequential.cc | 50 -
Rd/sequential.hh | 87 --
Rd/sequential_bench.cc | 51 -
Rd/sequential_bench.hh | 100 --
Rd/svg.queue_based.hh | 118 --
Rd/union_find.cc | 52 -
Rd/union_find.hh | 166 ----
Rd/utils.hh | 269 ------
browsing/fwd.cc | 515 ------------
browsing/fwd.hh | 88 --
color/blen_pix.hh | 174 ----
color/segment.cc | 639 ---------------
color/sum_pix.hh | 162 ---
compute_parent_more.hh | 191 ----
cs2d/cs2d.cc | 110 --
cs2d/cs2d.hh | 172 ----
cs2d/cs2d_morpho.hh | 372 ---------
cs2d/cs2d_utils.hh | 251 ------
cs2d/dbl_neighb.hh | 167 ----
cs2d/kruskal.cc | 357 --------
cs2d/tuto.cc | 145 ---
dead/inplace.hh | 66 -
dead/instant.hh | 168 ----
dmap.cc | 131 ---
estimate.hh | 90 --
fllt.svg.6.cc | 1139 ----------------------------
fllt.svg.7.hh | 838 --------------------
fllt/compute_fllt.cc | 19
fllt/connected_filters/area_filter.cc | 26
fllt/connected_filters/area_filter.hh | 69 -
fllt/connected_filters/canonize_tree.hh | 51 -
fllt/connected_filters/pseudo_flat_zones.cc | 44 -
fllt/fllt.hh | 1017 -------------------------
fllt/fllt.svg.1.cc | 222 -----
fllt/fllt.svg.2.cc | 304 -------
fllt/fllt.svg.3.cc | 313 -------
fllt/fllt.svg.4.cc | 352 --------
fllt/fllt.svg.5.cc | 353 --------
fllt/fllt.svg.6.cc | 1136 ---------------------------
fllt/fllt.svg.7.hh | 913 ----------------------
fllt/fllt_test.hh | 874 ---------------------
fllt/fllt_tree_to_image.hh | 30
fllt/simple_tests.cc | 84 --
irm.cc | 178 ----
laurent/classif.cc | 419 ----------
laurent/segmentation.hh | 14
laurent/wst2d.cc | 154 ---
laurent/wst3d.cc | 79 -
laurent/wst_edge.cc | 409 ----------
p_runs__with_dedicated_piter.hh | 758 ------------------
skel.cc | 106 --
test_attribute.cc | 122 --
tufa_2008/closed_gradient.cc | 64 -
tufa_2008/closing.cc | 64 -
tufa_2008/compute_a.cc | 412 ----------
tufa_2008/experiment.cc | 138 ---
tufa_2008/filter.cc | 169 ----
tufa_2008/filter_n.cc | 341 --------
tufa_2008/fz_count.cc | 160 ---
tufa_2008/gradient.cc | 60 -
tufa_2008/n_cmpt.cc | 263 ------
tufa_2008/opening.cc | 63 -
tufa_2008/regmin_count.cc | 175 ----
tufa_2008/steps.0.cc | 171 ----
tufa_2008/steps.1.cc | 274 ------
tufa_2008/steps.2.cc | 259 ------
tufa_2008/steps.2b.cc | 185 ----
tufa_2008/steps.3.cc | 186 ----
tufa_2008/wst.cc | 69 -
tufa_2008/wst_f_equal_wst_a.cc | 140 ---
win_fun.cc | 160 ---
win_fun.hh | 160 ---
84 files changed, 19106 deletions(-)
Index: geraud/skel.cc
--- geraud/skel.cc (revision 3151)
+++ geraud/skel.cc (working copy)
@@ -1,106 +0,0 @@
-# include <mln/core/var.hh>
-
-# include <mln/core/image/image2d.hh>
-# include <mln/core/alias/neighb2d.hh>
-# include <mln/core/site_set/p_queue_fast.hh>
-
-# include <mln/io/pbm/load.hh>
-# include <mln/io/pgm/save.hh>
-# include <mln/value/int_u8.hh>
-
-# include <mln/data/fill.hh>
-
-# include <mln/debug/println.hh>
-
-namespace mln
-{
-
- template <typename D, typename I, typename N>
- mln_ch_value(I, D)
- distance(D, const I& input, const N& nbh)
- {
- const D M = mln_max(D);
- mln_ch_value(I, D) output;
- initialize(output, input);
-
- mln_ch_value(I, bool) deja_vu;
- initialize(deja_vu, input);
- data::fill(deja_vu, input);
-
- typedef mln_site(I) P;
- p_queue_fast<P> q;
-
- // Initialization.
- {
- data::fill(output, M);
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- if (input(p) == true) // p in object
- {
- output(p) = 0;
- for_all(n)
- if (input.domain().has(n) && input(n) == false) // n in background
- {
- q.push(p);
- break;
- }
- }
- }
-
- // Propagation.
- {
- P p;
- mln_niter(N) n(nbh, p);
- while (! q.is_empty())
- {
- p = q.pop_front();
- for_all(n)
- if (input.domain().has(n) && output(n) == M)
- {
- output(n) = output(p) + 1;
- if (output(n) == M)
- {
- // Saturation so stop.
- q.clear();
- break;
- }
- q.push(n);
- deja_vu(n) = true;
- }
- }
- }
-
- return output;
- }
-
-*/
-
-
-
-} // mln
-
-
-
- void usage(char* argv[])
- {
- std::cerr << "usage: " << argv[0] << " input.pbm output.pgm" << std::endl;
- abort();
- }
-
-
-
- int main(int argc, char* argv[])
- {
- using namespace mln;
- using value::int_u8;
-
- if (argc != 3)
- usage(argv);
-
- image2d<bool> input;
- io::pbm::load(input, argv[1]);
-
- image2d<int_u8> output = distance(int_u8(), input, c4());
- io::pgm::save(output, argv[2]);
- }
Index: geraud/fllt.cc
Index: geraud/test_attribute.cc
--- geraud/test_attribute.cc (revision 3151)
+++ geraud/test_attribute.cc (working copy)
@@ -1,122 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file tests/morpho/tree/compute_attribute_image.cc
-///
-/// Tests on mln::morpho::tree::compute_attribute_image.
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/level/transform.hh>
-
-#include <mln/debug/println.hh>
-#include <mln/core/var.hh>
-#include <mln/value/int_u8.hh>
-
-#include <mln/morpho/tree/data.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-
-#include <mln/morpho/closing_area.hh>
-#include <mln/morpho/opening_area.hh>
-
-#include <mln/accu/count.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/pbm/save.hh>
-
-#include <mln/arith/min.hh>
-#include <mln/arith/diff_abs.hh>
-
-
-struct sat_t : mln::Function_v2v<sat_t>
-{
- typedef mln::value::int_u8 result;
- result operator()(unsigned u) const
- {
- return u > 255 ? 255 : u;
- }
-}
- sat;
-
-
-
-int main()
-{
- using namespace mln;
- using value::int_u8;
-
- typedef image2d<int_u8> I;
- typedef p_array<point2d> S;
- typedef util::pix<I> Px;
-
-
- I f;
- io::pgm::load(f, "../../../img/tiny.pgm");
-
-
- image2d<unsigned> area_inc, area_dec;
- {
- S s = level::sort_psites_increasing(f);
- morpho::tree::data<I,S> t(f, s, c4());
- accu::count<Px> a;
- area_inc = morpho::tree::compute_attribute_image(a, t);
- debug::println("area_inc =", area_inc);
- }
- {
- S s = level::sort_psites_decreasing(f);
- morpho::tree::data<I,S> t(f, s, c4());
- accu::count<Px> a;
- area_dec = morpho::tree::compute_attribute_image(a, t);
- debug::println("area_dec =", area_dec);
- }
-
- io::pgm::save(level::transform(area_inc, sat), "inc.pgm");
- io::pgm::save(level::transform(area_dec, sat), "dec.pgm");
-
- image2d<unsigned> area = arith::min(area_inc, area_dec);
- io::pgm::save(level::transform(area, sat), "min.pgm");
-
- unsigned lambda = 20;
-
- {
- I clo = morpho::closing_area(f, c4(), lambda);
- io::pgm::save(clo, "clo.pgm");
-
- I ope(clo.domain());
- morpho::opening_area(f, c4(), lambda, ope);
- io::pgm::save(ope, "ope.pgm");
-
- I d_clo = arith::diff_abs(f, clo);
- io::pgm::save(d_clo, "d_clo.pgm");
-
- I d_ope = arith::diff_abs(f, ope);
- io::pgm::save(d_ope, "d_ope.pgm");
- }
-
-}
Index: geraud/fllt.svg.6.cc
--- geraud/fllt.svg.6.cc (revision 3151)
+++ geraud/fllt.svg.6.cc (working copy)
@@ -1,1139 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <iomanip>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-#include <mln/core/image/sub_image.hh>
-#include <mln/core/site_set/p_queue_fast.hh>
-#include <mln/core/image/cast_image.hh>
-
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/level/compare.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/labeling/regional_maxima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-#include <mln/pw/all.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/util/tree.hh>
-#include <mln/util/branch_iter_ind.hh>
-#include <mln/util/branch_iter.hh>
-
-#include <mln/opt/at.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
- namespace my
- {
-
-# define fllt_tree(P, V) mln::util::tree< fllt_node_elt<P, V> >
-# define fllt_node(P, V) mln::util::tree_node< fllt_node_elt<P, V> >
-# define fllt_tree_ptr(P, V) mln::util::tree< fllt_node_elt<P, V>* >
-# define fllt_node_ptr(P, V) mln::util::tree_node< fllt_node_elt<P, V>* >
-# define fllt_branch(P, V) mln::util::branch< fllt_node_elt<P, V> >
-# define fllt_branch_iter_ind(P, V) mln::util::branch_iter_ind< fllt_node_elt<P, V> >
-# define fllt_branch_iter(P, V) mln::util::branch_iter< fllt_node_elt<P, V> >
-
-# define stl_to_mln_iter(T) stl_iterator< T >
-
- //Fwd declarations.
- template <typename V> struct lower;
- template <typename V> struct upper;
-
- template <typename P, typename V>
- struct fllt_node_elt
- {
- V value;
- p_array<P> points;
- p_array<P> holes;
- std::vector<fllt_node(P, V)*> hole_shapes;
- /// Tell if his parent if brighter or not. Nb : if the parent
- /// if brighter, the node come from the lower level set
- bool brighter;
- unsigned nsites;
- bool tagged;
- bool set_id;
-
- fllt_node_elt(bool set_id) : nsites(0), tagged(false), set_id(set_id) {}
- };
-
-
- template <typename C>
- class stl_iterator
- {
- public:
- stl_iterator(C& c) : container_(c) {}
- void start(){ it_ = container_.begin(); }
- void next() { it_++; }
- bool is_valid() const{ return it_ != container_.end(); }
- typename C::value_type& operator*() { return *it_; }
-
- private:
- C& container_;
- typename C::iterator it_;
- };
-
- template <typename N_t, typename G, typename Set>
- void update_gN(const N_t& N, G& gN);
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, lower<V>)
- {
- for (unsigned g = 0; g < 256; ++g)
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, upper<V>)
- {
- for (int g = 255; g >= 0; --g)
- {
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- }
- // if N is empty, gN is the min value.
- gN = 0;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- {
- if (N[i]->nsites() == 0)
- continue;
- std::cout << i << ": " << *N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- N[i]->clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- mln::opt::at(output, row, col) =
- mln::opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- void save_u(const image2d<value::int_u8>& u,
- const image2d<int>& is,
- box2d R_box,
- int in_R,
- int in_N)
- {
- static int id = 0;
- std::stringstream filename;
- filename << "fllt_trace_" << std::setw(5) << std::setfill('0')
- << std::right << id++ << ".ppm";
-
- image2d<value::int_u8> out = duplicate(cast_image<value::int_u8>(is));
-
- mln_assertion(R_box.nsites() > 0);
- mln_piter_(box2d) p(R_box);
- for_all(p)
- if (is(p) == in_R)
- out(p) = 255;
- else if (is(p) == in_N)
- out(p) = 127;
- // else if (is(p) == in_N)
- // out(p) = literal::green;
-
- io::pgm::save(out, filename.str());
- //io::pgm::save(out, filename.str());
- }
-
- template <typename I>
- void save(const I& is, unsigned in_N, unsigned in_R, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- if (is(p) == in_R)
- temp(p) = literal::red;
- else if (is(p) == in_N) // N
- temp(p) = literal::green;
- else if (is(p) < in_N)
- temp(p) = literal::blue;
- else
- temp(p) = literal::white;
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(my::enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
-
- template <typename I, typename P, typename V, typename Set>
- void blob(const Set&,
- const I& is,
- p_array<mln_point(I)>* N[256],
- unsigned in_N,
- const box2d& N_box,
- fllt_node(P, V)* current_cc)
- {
- typedef p_array<mln_point(I)> arr_t;
-
-// std::cout << ">>>>>>>enter blob. " << current_cc << std::endl;
- bool flower = true;
- unsigned ncc = 0;
- static image2d<unsigned> is_labeled(is.domain());
- static unsigned label = 0;
-
- if (label == 0)
- {
- data::fill(is_labeled, 0);
- label++;
- }
-
- P cur;
- mln_niter(neighb2d) n(Set::bdr_nbh()/*c8()*/, cur);
- p_queue_fast<P> qu;
- p_array<P>& holes = current_cc->elt().holes;
-
- mln_piter(I) p(N_box);
- for_all(p)
- if (is(p) == in_N)
- break;
-
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
-
-
-
- for (unsigned i = 0; i < 256; ++i)
- //for (int i = 255; i >= 0; --i)
- {
- mln_piter(arr_t) p(*N[i]);
- for_all(p)
- {
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
- }
- }
-
- ++label;
-
- // if (holes.size() == 2)
- // std::cout << holes[0] << holes[1] << std::endl;
- // std::cout << " <<<<<<<exiting blob." << std::endl;
- }
-
-// template <typename I, typename V>
-// void blob(const I& is,
-// p_array<mln_point(I)>* N[256],
-// unsigned in_N,
-// const box2d& N_box,
-// fllt_node(mln_point(I), V)* current_cc)
-// {
-// typedef p_array<mln_point(I)> arr_t;
-
-// // std::cout << ">>>>>>>enter blob. " << current_cc << std::endl;
-// bool flower = true;
-// unsigned ncc = 0;
-// static image2d<unsigned> is_labeled(is.domain());
-// static unsigned label = 0;
-
-// if (label == 0)
-// {
-// data::fill(is_labeled, 0);
-// label++;
-// }
-
-// typedef mln_psite(I) P;
-// P cur;
-// mln_niter(neighb2d) n(c8(), cur);
-// p_queue_fast<P> qu;
-// p_array<P>& holes = current_cc->elt().holes;
-
-// mln_piter(I) p(N_box);
-// for_all(p)
-// if (is(p) == in_N)
-// break;
-
-// mln_assertion(is(p) == in_N);
-// if (is_labeled(p) != label)
-// {
-// if (flower == false)
-// holes.append(p);
-// else
-// flower = false;
-// qu.push(p);
-// is_labeled(p) = label;
-// do
-// {
-// cur = qu.front();
-// qu.pop();
-// for_all(n) if (is.has(n))
-// if (is(n) == in_N && is_labeled(n) != label)
-// {
-// qu.push(n);
-// is_labeled(n) = label;
-// }
-// }
-// while (! qu.is_empty());
-// }
-
-
-
-// for (unsigned i = 0; i < 256; ++i)
-// //for (int i = 255; i >= 0; --i)
-// {
-// mln_piter(arr_t) p(*N[i]);
-// for_all(p)
-// {
-// mln_assertion(is(p) == in_N);
-// if (is_labeled(p) != label)
-// {
-// if (flower == false)
-// holes.append(p);
-// else
-// flower = false;
-// qu.push(p);
-// is_labeled(p) = label;
-// do
-// {
-// cur = qu.front();
-// qu.pop();
-// for_all(n) if (is.has(n))
-// if (is(n) == in_N && is_labeled(n) != label)
-// {
-// qu.push(n);
-// is_labeled(n) = label;
-// }
-// }
-// while (! qu.is_empty());
-// }
-// }
-// }
-
-// ++label;
-
-// // if (holes.size() == 2)
-// // std::cout << holes[0] << holes[1] << std::endl;
-// // std::cout << " <<<<<<<exiting blob." << std::endl;
-// }
-
- template <typename P, typename V>
- void
- move_A_to_R(p_array<P>& A,
- image2d<int>& deja_vu,
- fllt_node(P, V)* current_cc,
- image2d< fllt_node(P, V)* >& smallest_shapes,
- int in_R,
- int in_N,
- const V& g,
- unsigned& n_comps)
- {
- typedef p_array<P> arr_t;
-
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- mln_invariant(deja_vu(a) == in_N);
- mln_invariant(smallest_shapes(a) != current_cc);
-
- deja_vu(a) = in_R;
- current_cc->elt().nsites++;
- if (!smallest_shapes(a))
- {
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- if (!smallest_shapes(a)->parent())
- if (smallest_shapes(a)->elt().value == g)
- {
- fllt_node(P, V)* to_delete = smallest_shapes(a);
-
- mln_piter(arr_t) p(smallest_shapes(a)->elt().points);
- // Todo optimization here.
- for_all(p)
- smallest_shapes(p) = 0;
-
- while(!to_delete->children().empty())
- current_cc->add_child(*to_delete->children().begin());
- delete to_delete;
- n_comps--;
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- smallest_shapes(a)->set_parent(current_cc);
- // N_box is not re-computed so that we save time;
- // N_box is always growing while looping from step 3.
- }
- }
-
- // LOWER LEVEL SET : region = c4, border = c8
- template <typename V>
- struct lower
- {
- typedef upper<V> opposite;
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- {
- return u < v;
- }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- {
- return labeling::regional_minima(input, nbh, nlabels);
- }
-
- static const bool parent_is_brighter = true;
- static const bool id = false;
-
- static const neighb2d& bdr_nbh() { return c8(); }
- static const neighb2d& reg_nbh() { return c4(); }
- };
-
-
- // UPPER LEVEL SET : region = c8, border = c4
- template <typename V>
- struct upper
- {
- typedef lower<V> opposite;
-
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- { return u > v; }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- { return labeling::regional_maxima(input, nbh, nlabels); }
-
- static const bool parent_is_brighter = false;
- static const bool id = true;
-
- static const neighb2d& bdr_nbh() { return c4(); }
- static const neighb2d& reg_nbh() { return c8(); }
- };
-
- template <typename I, typename Set>
- fllt_tree(mln_point(I), mln_value(I))&
- level_set(const Image<I>& input_,
- image2d< fllt_node(mln_point(I), mln_value(I))* >& smallest_shapes)
- {
-
- typedef mln_point(I) P;
- typedef mln_value(I) V;
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
-
- const I& input = exact(input_);
-
- mln_assertion(input.domain() == smallest_shapes.domain());
-
- unsigned l = 0, l_max = 0;
- mln_ch_value(I, unsigned) reg_min = Set::regional_extremum(input, Set::reg_nbh(), l_max);
- std::vector<bool> tag(l_max + 1, false);
- tag[0] = true;
-
- // Variables.
- I u = mln::duplicate(input);
- P x0;
- V g, gN;
- mln_fwd_piter(I) p(input.domain());
- p.start();
- data::fill(smallest_shapes, 0);
- node_type* current_cc;
-
- unsigned in_N = 1, in_R = 2;
-
- image2d<int> deja_vu(input.domain().to_larger(1));
- data::fill(deja_vu, 0);
-
- typedef p_array<P> arr_t;
- arr_t* A = new arr_t();
- arr_t* N[256];
- for (unsigned i = 0; i < 256; ++i)
- N[i] = new arr_t();
- accu::bbox<P> N_box;
-
- bool touch_border_of_image = false;
- unsigned n_step_1 = 0, n_step_3 = 0, n_comps = 0, n_holes = 0;
-
- // Step 1.
- step_1:
- {
- while (tag[reg_min(p)] && p.is_valid())
- p.next();
- if (p.is_valid())
- tag[reg_min(p)] = true; // To be processed.
- else
- goto the_end;
-
- ++n_step_1;
- x0 = p;
- g = input(x0);
- ++n_comps;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- touch_border_of_image = false;
-
- }
-
- // Step 2.
- step_2:
- {
- in_N += 2;
- in_R = in_N + 1;
- // R <- 0 and N <- 0
- clear_N(N);
- N_box.init();
-
- // A <- { x0 }
- A->clear();
- A->append(x0);
- N_box.take(x0);
-
- deja_vu(x0) = in_R;
- smallest_shapes(x0) = current_cc;
- current_cc->elt().points.append(x0);
- current_cc->elt().nsites++;
-
- }
-
- // Step 3.
- step_3:
- {
-// save_u(u, deja_vu, N_box, in_R, in_N);
- ++n_step_3;
-
- mln_piter(arr_t) a(*A);
- mln_niter(neighb2d) x(Set::reg_nbh(), a);
-
-
- // R <- R U A
- if (A->nsites() == 0)
- goto the_end;
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- {
- if (deja_vu.has(x) && deja_vu(x) < in_N)
- {
- if (u.has(x))
- {
- N[u(x)]->append(x);
- N_box.take(x);
- }
- else
- touch_border_of_image = true;
- deja_vu(x) = in_N;
- }
- }
- // gN = min u(x) for all x in N
- update_gN(N, gN, Set());
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (Set::compare(g, gN))
- {
- g = gN;
-
- ++n_comps;
-
- if (touch_border_of_image)
- blob(Set(), deja_vu, N, in_N, N_box.to_result().to_larger(1), current_cc);
- else
- blob(Set(), deja_vu, N, in_N, N_box, current_cc);
-
- n_holes += current_cc->elt().holes.nsites();
-
- node_type* child = current_cc;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- child->set_parent(current_cc);
-
-
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // c)
- else
- {
- // FIXME: IDEA: this change might be performed while R is constructed(?)
- mln_piter(I) r(N_box);
- for_all(r)
- if (deja_vu(r) == in_R)
- u(r) = g;
-
- goto step_1;
- }
- }
-
- the_end:
- std::cout << "l_max " << l_max << " " << n_step_1 << ' ' << n_step_3 << std::endl;
- std::cout << "n comps = " << n_comps << " n holes = " << n_holes << std::endl;
-
- return *new tree_type(current_cc);
- }
-
- // F is the set in which we get the node.
- template <typename P, typename V, typename F>
- fllt_node(P, V)*
- find_hole(fllt_node(P, V)& node,
- const P p,
- const image2d<fllt_node(P, V)*>& other_reg)
- {
- fllt_node(P, V)* s = other_reg(p);
- mln_assertion(s);
- while (s->parent() && F::compare(s->parent()->elt().value, node.elt().value))
- {
- mln_assertion(s);
- s = s->parent();
- mln_assertion(s);
- }
-// std::cout << " [Find the hole] of " << p
-// << " from " << &node
-// << " return " << s
-// << std::endl;
- return s;
- }
-
- template <typename P, typename V>
- bool shape_is_included(fllt_node(P, V)* A,
- fllt_node(P, V)* B)
- {
- return A->parent() == B || A == B;
- }
-
- template <typename P, typename V>
- void find_all_holes(fllt_tree(P, V)& lower_tree,
- fllt_tree(P, V)& upper_tree,
- const image2d<fllt_node(P, V)*>& low_reg,
- const image2d<fllt_node(P, V)*>& upp_reg)
- {
- typedef p_array<P> arr_t;
- typedef fllt_node(P, V) node_type;
-
- {
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,upper<V> >(node, P(hole), upp_reg));
- }
- }
-
- {
- fllt_branch_iter_ind(P, V) node_(upper_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,lower<V> >(node, P(hole), low_reg));
- }
- }
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- merge_trees(fllt_tree(mln_point(I), mln_value(I))& lower_tree,
- fllt_tree(mln_point(I), mln_value(I))& upper_tree,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& low_reg,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& upp_reg,
- const Image<I>& input_)
- {
-
- const I& input = exact(input_);
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
- typedef p_array<P> arr_t;
-
-
- find_all_holes(lower_tree, upper_tree, low_reg, upp_reg);
- std::vector<node_type*> to_fill;
-
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != lower<V>::id)
- continue;
-
- // std::cout << "Fill " << &node << std::endl;
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- // std::cout << "hole : " << hole << " " << hole->elt().points << " " << std::endl;
- // std::cout << "child hole : " << child_hole << " " << child_hole->elt().points << std::endl;
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
- if (!child_has_bigger_hole)
- {
- // // std::cout << "move " << hole << " as child of " << &node << std::endl;
- node.add_child(hole);
- to_fill.push_back(hole);
- }
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- for(typename std::vector<node_type*>::iterator node_ = to_fill.begin();
- node_ != to_fill.end();
- node_++)
- {
- node_type& node = **node_;
-
- fllt_branch_iter_ind(P, V) node_(fllt_branch(P, V)(upper_tree, node));
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != upper<V>::id)
- continue;
-
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- //if (hole->elt().points <= child_hole->elt().points)
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
-
- if (!child_has_bigger_hole)
- node.add_child(hole);
-
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- }
-
- return lower_tree;
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- fllt(const Image<I>& input_)
- {
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- const I& input = exact(input_);
-
- fllt_tree(P, V) upper_tree;
- fllt_tree(P, V) lower_tree;
- image2d<fllt_node(P, V)*> low_reg(input.domain());
- image2d<fllt_node(P, V)*> upp_reg(input.domain());
-
- std::cout << "1/ Compute the lower level set.----------------------------------------" << std::endl;
- lower_tree = level_set<I, lower<V> >(input, low_reg);
- //draw_tree(input, lower_tree);
-
- std::cout << "2/ Compute the upper level set.----------------------------------------" << std::endl;
- upper_tree = level_set<I, upper<V> >(input, upp_reg);
- //draw_tree(input, upper_tree);
-
- std::cout << "3/ Merge.---------------------------------------------------------------" << std::endl;
- fllt_tree(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, input);
-
- return result_tree;
- }
-
- template <typename P, typename V>
- void
- draw_tree(const image2d<V>& ima,
- fllt_tree(P, V)& tree)
- {
- p_array<P> tmp;
-
- fllt_branch_iter_ind(P, V) p(tree.main_branch());
- for_all(p)
- {
- std::cout << "region mere : " << (*p).parent() << std::endl;
- std::cout << " ^" << std::endl;
- std::cout << " |" << std::endl;
- std::cout << "region : " << &*p
- << " value = " << (*p).elt().value << std::endl
- << " from " << ((*p).elt().set_id == lower<V>::id ? "lower" : "upper") << " level set." << std::endl
- << " nsites = " << (*p).elt().nsites << std::endl
- << " holes = " << (*p).elt().holes << std::endl;
-
- std::cout << std::endl;
-
- tmp.append((*p).elt().points);
-
- fllt_branch_iter_ind(P, V) n(fllt_branch(P, V)(tree, *p));
- for_all(n)
- tmp.append((*n).elt().points);
-
- if ((*p).elt().points.nsites() > 0)
- debug::println(ima | tmp);
- tmp.clear();
-
- std::cout << std::endl;
- }
- }
-
-
- template <typename P, typename V, typename I>
- unsigned
- compute_area_rec(fllt_node(P, V)* node, I& ima)
- {
-
- if (!node)
- return 0;
-
- int area = 0;
-
- for (int i = 0; i < node->children().size();i++)
- area += compute_area_rec(node->children()[i], ima);
-
- mln_piter(p_array<P>) p(node->elt().points);
- for_all(p)
- if (!ima(P(p)))
- {
- ++area;
- ima(p) = true;
- }
-
- node->elt().nsites = area;
- return area;
- }
-
- template <typename P, typename V, typename I>
- void
- compute_area(const Image<I>& input_, fllt_tree(P, V)& tree)
- {
- const I& input = exact(input_);
-
- image2d<bool> ima(input.domain());
- data::fill(ima, false);
- compute_area_rec(tree.root(), ima);
- }
-
- void draw_shape(image2d<value::int_u8>& output,
- fllt_node(point2d, value::int_u8)* node)
- {
- typedef point2d P ;
- typedef value::int_u8 V;
-
- fllt_tree(P, V) subtree(node);
- fllt_branch_iter_ind(P, V) s(fllt_branch(P, V)(subtree, *node));
- for_all(s)
- data::fill(output | (*s).elt().points), (*s).elt().value);
- }
-
- void area_filter(image2d<value::int_u8>& output,
- fllt_node(point2d, value::int_u8)* node,
- unsigned min_area,
- unsigned max_area,
- value::int_u8 bg)
- {
- typedef point2d P ;
- typedef value::int_u8 V;
-
- data::fill(output, bg);
- fllt_tree(P, V) subtree(node);
- fllt_branch_iter_ind(P, V) s(fllt_branch(P, V)(subtree, *node));
- for_all(s)
- if ((*s).elt().nsites > min_area && (*s).elt().nsites < max_area)
- draw_shape(output, &*s);
- }
-
- void area_filter_min(image2d<value::int_u8>& output,
- fllt_node(point2d, value::int_u8)* node,
- unsigned min_area,
- value::int_u8 g,
- unsigned accu)
- {
-// if ((*node).elt().nsites >= min_area)
- if (accu > min_area)
- {
- accu = 0;
- g = (*node).elt().value;
- }
-
- accu += (*node).elt().nsites;
- data::fill(output | (*node).elt().points), g);
-
- for (int i = 0; i < node->children().size();i++)
- area_filter_min(output, node->children()[i], min_area, g, accu);
- }
-
- } // end of namespace mln::my
-
-} // end of namespace mln
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using namespace mln::my;
- using value::int_u8;
-
- typedef fllt_tree(point2d, int_u8) tree_type;
-
-
-
-// if (argc != 2)
-// {
-// std::cerr << "usage: " << argv[0] << " filename" << std::endl;
-// return 1;
-// }
-
- image2d<int_u8> lena;
- io::pgm::load(lena, argv[1]);
-
-
-// int vs[8][9] = { {0,0,0,0,0,0,0,0,0},
-// {0,0,0,0,0,0,0,0,0},
-// {0,1,1,1,1,1,1,1,0},
-// {0,1,0,0,1,3,3,1,0},
-// {0,1,0,0,1,3,4,1,0},
-// {0,1,0,0,1,3,3,1,0},
-// {0,1,1,1,1,1,1,1,0},
-// {0,0,0,0,0,0,0,0,0} };
-
-
-
-// int vs[8][9] = { {6,6,6,6,6,6,6,6,6},
-// {6,6,6,6,6,6,6,6,6},
-// {6,5,5,5,5,5,5,5,6},
-// {6,5,6,6,5,3,3,5,6},
-// {6,5,6,6,5,3,0,5,6},
-// {6,5,6,6,5,3,3,5,6},
-// {6,5,5,5,5,5,5,5,6},
-// {6,6,6,6,6,6,6,6,6} };
-
-// int vs[8][9] = { {2,2,2,2,2,2,2,2,2},
-// {2,2,2,2,2,2,2,2,2},
-// {2,1,1,1,1,1,1,1,2},
-// {2,1,2,2,1,0,0,1,2},
-// {2,1,2,2,1,0,0,1,2},
-// {2,1,2,2,1,0,0,1,2},
-// {2,1,1,1,1,1,1,1,2},
-// {2,2,2,2,2,2,2,2,2} };
-
-
- int vs[8][9] = { {2,2,2,2,2,2,2,2,2},
- {2,2,2,2,2,2,2,2,2},
- {2,1,1,1,1,1,1,1,2},
- {2,1,2,2,1,0,0,1,2},
- {2,1,2,2,1,0,4,1,2},
- {2,1,2,2,1,0,0,1,2},
- {2,1,1,1,1,1,1,1,2},
- {2,2,2,2,2,2,2,2,2} };
-
-// int vs[10][13] = { {1,1,1,1, 1,1,1,1, 1,1,1,1,1},
-// {1,2,2,2,2,2,2,2,2,2,2,2,1},
-// {1,2,2,2,2,2,2,2,2,2,2,2,1},
-// {1,2,2,2,3,3,3,3,3,3,3,2,1},
-// {1,2,2,2,3,3,3,2,2,2,3,2,1},
-// {1,2,2,2,3,4,3,2,4,4,3,2,1},
-
-// {1,2,2,2,3,3,3,2,2,2,3,2,1},
-// {1,2,2,2,3,3,3,3,3,3,3,2,1},
-// {1,2,2,2,2,2,2,2,2,2,2,2,1},
-// {1,1,1,1,1,1,1,1,1,1,1,1,1}};
-
-
-// image2d<int> lena_(make::image2d(vs));
-// image2d<int_u8> lena(lena_.domain());
-// data::fill(lena, lena_);
-
- tree_type tree = my::fllt(lena);
- compute_area(lena, tree);
-
- image2d<value::int_u8> output (lena.domain ());
-// area_filter_min(output, tree.root(), atoi(argv[2]), 0, 0);
- area_filter(output, tree.root(), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
- io::pgm::save(output, "out.pgm");
-
- // draw_tree(lena, tree);
-}
Index: geraud/p_runs__with_dedicated_piter.hh
--- geraud/p_runs__with_dedicated_piter.hh (revision 3151)
+++ geraud/p_runs__with_dedicated_piter.hh (working copy)
@@ -1,758 +0,0 @@
-// Copyright (C) 2007, 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_CORE_SITE_SET_P_RUNS_HH
-# define MLN_CORE_SITE_SET_P_RUNS_HH
-
-/*! \file mln/core/p_runs.hh
- *
- * \brief Definition of a set of point runs.
- */
-
-# include <mln/accu/bbox.hh>
-# include <mln/core/site_set/p_run.hh>
-# include <mln/core/p_double.hh>
-# include <mln/core/internal/piter_adaptor.hh>
-# include <mln/util/set.hh>
-
-
-
-namespace mln
-{
-
- // Forward declarations.
- template <typename P> class p_runs;
- template <typename P> class p_runs_psite;
- template <typename P> class p_runs_fwd_piter_;
- template <typename P> class p_runs_bkd_piter_;
-
-
- namespace trait
- {
-
- template <typename P>
- struct site_set_< p_runs<P> >
- {
- typedef trait::site_set::nsites::known nsites;
- typedef trait::site_set::bbox::known bbox;
- typedef trait::site_set::contents::growing contents;
- typedef trait::site_set::arity::unique arity;
- };
-
- } // end of namespace trait
-
-
-
- /*! \brief p_runs is a site set composed of runs.
- *
- * Parameter \c P is the type of the image point.
- */
- template <typename P>
- class p_runs : public internal::site_set_base_< P, p_runs<P> >
- {
- typedef p_runs<P> self_;
- public:
-
- /// Element associated type.
- typedef p_run<P> element;
-
-
- /// Psite associated type.
- typedef p_runs_psite<P> psite;
-
- /// Forward Site_Iterator associated type.
- typedef p_runs_fwd_piter_<P> fwd_piter;
-
- /// Backward Site_Iterator associated type.
- typedef p_runs_bkd_piter_<P> bkd_piter;
-
- /// Site_Iterator associated type.
- typedef fwd_piter piter;
-
-
- /// Constructor without arguments.
- p_runs();
-
-
- /// Test if \p p belongs to this point set.
- bool has(const psite&) const;
-
- /// Test if this set of runs is valid.
- bool is_valid() const;
-
-
- /// Box associated type.
- typedef const mln::box<P>& q_box;
-
- /// Give the exact bounding box.
- const box<P>& bbox() const;
-
-
- /// Give the number of points.
- unsigned nsites() const;
-
- /// Give the number of runs.
- unsigned nruns() const;
-
- /// Give the compression ratio: FIXME: explain...
- float zratio() const;
-
-
- /// Insertion element associated type.
- typedef p_run<P> i_element;
-
- /// Insert a run \p r.
- void insert(const p_run<P>& r);
-
- /// Insert a run from \p start to \p end.
- void insert(const P& start, const P& end);
-
- /// Insert a run defined by \p start with length \p len.
- void insert(const P& start, unsigned short len);
-
- /// Insert another set of runs.
- void insert(const p_runs<P>& other);
-
-
- /// Clear this set.
- void clear();
-
-
- /// Return the i-th run.
- const p_run<P>& run(unsigned i) const;
-
- /// Return the size of this site set in memory.
- std::size_t memory_size() const;
-
- /// Hook to the set of runs.
- const util::set< p_run<P> >& hook_() const;
-
-
- protected:
-
- /// Number of points.
- unsigned nsites_;
-
- /// Bounding box accumulator.
- accu::bbox<P> b_;
-
- /// Set of runs.
- util::set< p_run<P> > run_;
- };
-
-
-
- template <typename P>
- std::ostream& operator<<(std::ostream& ostr, const p_runs<P>& r);
-
-
- namespace util
- {
-
- template <typename P>
- struct less< p_runs<P> >
- {
- bool operator()(const p_runs<P>& lhs,
- const p_runs<P>& rhs) const;
- };
-
- } // end of namespace mln::util
-
-
-
- // p_runs_psite<P>
-
- template <typename P>
- class p_runs_psite : public internal::pseudo_site_base_< const P&,
- p_runs_psite<P> >
- {
- typedef p_runs_psite<P> self;
- typedef internal::pseudo_site_base_<const P&, self> super;
-
- public:
-
- // This associated type is important to know that this particular
- // pseudo site knows the site set it refers to.
- typedef p_runs<P> target;
-
- p_runs_psite();
-
- // As a Proxy:
- const P& subj_();
-
- const p_runs<P>* target_() const;
- void change_target(const p_runs<P>& new_target);
-
- bool is_valid() const;
-
- short index_in_run() const;
- void set_index_in_run(short i);
- void inc_index_in_run();
- void dec_index_in_run();
-
- unsigned run_index() const;
- void goto_run_start(unsigned r);
- void goto_run_end(unsigned r);
-
- unsigned run_length() const;
-
- private:
-
- const p_runs<P>* s_;
- unsigned r_;
- short i_;
- mutable P p_;
- };
-
-
- // p_runs_fwd_piter_
-
- template <typename P>
- class p_runs_fwd_piter_
- :
- public internal::site_set_iterator_base< p_runs<P>,
- p_runs_fwd_piter_<P> >
- {
- typedef p_runs_fwd_piter_<P> self_;
- typedef internal::site_set_iterator_base< p_runs<P>, self_ > super_;
- public:
-
- /// Constructor without arguments.
- p_runs_fwd_piter_();
-
- /// Constructor.
- p_runs_fwd_piter_(const p_runs<P>& r);
-
- /// Test if the iterator is valid.
- bool is_valid_() const;
-
- /// Invalidate the iterator.
- void invalidate_();
-
- /// Start an iteration.
- void start_();
-
- /// Go to the next point.
- void next_();
-
- protected:
- using super_::p_;
- using super_::s_;
- unsigned short len_;
- };
-
-
-
- // p_runs_bkd_piter_
-
- template <typename P>
- class p_runs_bkd_piter_
- :
- public internal::site_set_iterator_base< p_runs<P>,
- p_runs_bkd_piter_<P> >
- {
- typedef p_runs_bkd_piter_<P> self_;
- typedef internal::site_set_iterator_base< p_runs<P>, self_ > super_;
- public:
-
- /// Constructor without arguments.
- p_runs_bkd_piter_();
-
- /// Constructor.
- p_runs_bkd_piter_(const p_runs<P>& r);
-
- /// Test if the iterator is valid.
- bool is_valid_() const;
-
- /// Invalidate the iterator.
- void invalidate_();
-
- /// Start an iteration.
- void start_();
-
- /// Go to the next point.
- void next_();
-
- protected:
- using super_::p_;
- using super_::s_;
- };
-
-
-
-
-# ifndef MLN_INCLUDE_ONLY
-
-
- // p_runs
-
- template <typename P>
- inline
- p_runs<P>::p_runs()
- :
- nsites_(0)
- {
- }
-
- template <typename P>
- inline
- bool
- p_runs<P>::has(const p_runs_psite<P>& p) const
- {
- mln_precondition(p.target_() == this); // FIXME: Refine.
- if (p.run_index() >= nruns() ||
- p.index_in_run() < 0 ||
- p.index_in_run() >= run_[p.run_index()].length())
- return false;
- // The type of rhs below is mln_site(p_run<P>).
- mln_invariant(p.to_site() == run_[p.run_index()][p.index_in_run()]);
- return true;
- }
-
- template <typename P>
- inline
- bool
- p_runs<P>::is_valid() const
- {
- // FIXME: A run of this set can be invalid...
- return true;
- }
-
- template <typename P>
- inline
- const box<P>&
- p_runs<P>::bbox() const
- {
- return b_.to_result();
- }
-
- template <typename P>
- inline
- unsigned
- p_runs<P>::nsites() const
- {
- return nsites_;
- }
-
- template <typename P>
- inline
- void
- p_runs<P>::insert(const p_runs<P>& other)
- {
- if (other.nsites() == 0)
- // No-op.
- return;
- nsites_ += other.nsites();
- b_.take(other.bbox());
- run_.insert(other.run_);
- }
-
- template <typename P>
- inline
- void
- p_runs<P>::insert(const p_run<P>& r)
- {
- nsites_ += r.nsites();
- b_.take(r.bbox());
- run_.insert(r);
- }
-
-
-// Previous code of 'insert' was:
-//
-// {
-// typename std::vector<p_run<P> >::const_iterator iter = con_.vect().begin();
-// while (iter != con_.vect().end() && iter->first() < pr.first())
-// ++iter;
-
-// if (iter != con_.vect().begin())
-// {
-// typename std::vector<p_run<P> >::const_iterator prec = iter;
-// --prec;
-// bool equal = true;
-// for (int i = P::dim - 2; i >= 0; --i)
-// if (!(equal = equal && (prec->first()[i] == pr.first()[i])))
-// break;
-// if (equal)
-// mln_assertion(prec->first()[P::dim - 1] + (signed)prec->length()
-// <= pr.first()[P::dim - 1]);
-// }
-
-// if (iter != con_.vect().end())
-// {
-// bool equal = true;
-// for (int i = P::dim - 2; i >= 0; --i)
-// if (!(equal = equal && ((*iter).first()[i] == pr.first()[i])))
-// break;
-// if (equal)
-// mln_assertion(pr.first()[P::dim - 1] + (signed)pr.length()
-// <= iter->first()[P::dim - 1]);
-// }
-// con_.insert(pr);
-
-// // update box
-// fb_.take(pr.bbox().pmin());
-// fb_.take(pr.bbox().pmax());
-// // update size
-// nsites_ += pr.nsites();
-// }
-
-
- template <typename P>
- inline
- void
- p_runs<P>::insert(const P& start, const P& end)
- {
- mln_precondition(cut_(end) == cut_(start));
- mln_precondition(end.last_coord() >= start.last_coord());
- p_run<P> r(start, end);
- this->insert(r);
- }
-
- template <typename P>
- inline
- void
- p_runs<P>::insert(const P& start, unsigned short len)
- {
- mln_precondition(len != 0);
- p_run<P> r(start, len);
- this->insert(r);
- }
-
- template <typename P>
- inline
- void
- p_runs<P>::clear()
- {
- nsites_ = 0;
- b_.init();
- run_.clear();
- }
-
- template <typename P>
- inline
- unsigned
- p_runs<P>::nruns() const
- {
- return run_.nelements();
- }
-
- template <typename P>
- inline
- const p_run<P>&
- p_runs<P>::run(unsigned i) const
- {
- mln_precondition(i < nruns());
- return run_[i];
- }
-
- template <typename P>
- inline
- std::size_t
- p_runs<P>::memory_size() const
- {
- return run_.memory_size() + sizeof(nsites_) + sizeof(b_);
- }
-
- template <typename P>
- inline
- float
- p_runs<P>::zratio() const
- {
- return
- float(memory_size()) /
- float(b_.to_result().nsites() * sizeof(P));
- }
-
- template <typename P>
- inline
- const util::set< p_run<P> >&
- p_runs<P>::hook_() const
- {
- return run_;
- }
-
-
- template <typename P>
- std::ostream& operator<<(std::ostream& ostr, const p_runs<P>& r)
- {
- return ostr << r.hook_();
- }
-
-
- namespace util
- {
-
- template <typename P>
- inline
- bool
- less< p_runs<P> >::operator()(const p_runs<P>& lhs,
- const p_runs<P>& rhs) const
- {
- return op_less(lhs.run(0), rhs.run(0));
- }
-
- } // end of namespace mln::util
-
-
-
- // p_runs_psite<P>
-
- template <typename P>
- inline
- p_runs_psite<P>::p_runs_psite()
- {
- s_ = 0;
- }
-
- template <typename P>
- inline
- const P&
- p_runs_psite<P>::subj_()
- {
- return p_;
- }
-
- template <typename P>
- inline
- const p_runs<P>*
- p_runs_psite<P>::target_() const
- {
- return s_;
- }
-
- template <typename P>
- inline
- void
- p_runs_psite<P>::change_target(const p_runs<P>& new_target)
- {
- s_ = & new_target;
- goto_run_start(0);
- }
-
- template <typename P>
- inline
- bool
- p_runs_psite<P>::is_valid() const
- {
- return
- s_ != 0 &&
- r_ < s_->nruns() &&
- i_ >= 0 && i_ < s_->run(r_).length();
- }
-
- template <typename P>
- inline
- short
- p_runs_psite<P>::index_in_run() const
- {
- return i_;
- }
-
- template <typename P>
- inline
- void
- p_runs_psite<P>::set_index_in_run(short i)
- {
- p_.last_coord() += (i - i_);
- i_ = i;
- }
-
- template <typename P>
- inline
- void
- p_runs_psite<P>::inc_index_in_run()
- {
- ++i_;
- p_.last_coord() += 1;
- }
-
- template <typename P>
- inline
- void
- p_runs_psite<P>::dec_index_in_run()
- {
- --i_;
- p_.last_coord() -= 1;
- }
-
- template <typename P>
- inline
- unsigned
- p_runs_psite<P>::run_index() const
- {
- return r_;
- }
-
- template <typename P>
- inline
- void
- p_runs_psite<P>::goto_run_start(unsigned r)
- {
- r_ = r;
- if (r_ < s_->nruns())
- {
- i_ = 0;
- p_ = s_->run(r).start();
- }
- }
-
- template <typename P>
- inline
- void
- p_runs_psite<P>::goto_run_end(unsigned r)
- {
- r_ = r;
- if (r_ < s_->nruns())
- {
- i_ = s_->run(r).length() - 1;
- p_ = s_->run(r).end();
- }
- }
-
- template <typename P>
- inline
- unsigned
- p_runs_psite<P>::run_length() const
- {
- if (s_ == 0 || r_ >= s_->nruns())
- return 0;
- else
- return s_->run(r_).length();
- }
-
-
- // p_runs_fwd_piter_<P>
-
- template <typename P>
- inline
- p_runs_fwd_piter_<P>::p_runs_fwd_piter_()
- {
- }
-
- template <typename P>
- inline
- p_runs_fwd_piter_<P>::p_runs_fwd_piter_(const p_runs<P>& r)
- {
- this->change_target(r);
- }
-
- template <typename P>
- inline
- bool
- p_runs_fwd_piter_<P>::is_valid_() const
- {
- return len_ != 0;
- }
-
- template <typename P>
- inline
- void
- p_runs_fwd_piter_<P>::invalidate_()
- {
- len_ = 0;
- }
-
- template <typename P>
- inline
- void
- p_runs_fwd_piter_<P>::start_()
- {
- p_.goto_run_start(0);
- len_ = p_.run_length();
- }
-
- template <typename P>
- inline
- void
- p_runs_fwd_piter_<P>::next_()
- {
- p_.inc_index_in_run();
- if (p_.index_in_run() == short(len_))
- {
- p_.goto_run_start(p_.run_index() + 1);
- len_ = p_.run_length();
- // len_ is null when p_ is invalid.
- }
- }
-
-
- // p_runs_bkd_piter_<P>
-
- template <typename P>
- inline
- p_runs_bkd_piter_<P>::p_runs_bkd_piter_()
- {
- }
-
- template <typename P>
- inline
- p_runs_bkd_piter_<P>::p_runs_bkd_piter_(const p_runs<P>& r)
- {
- this->change_target(r);
- }
-
- template <typename P>
- inline
- bool
- p_runs_bkd_piter_<P>::is_valid_() const
- {
- return p_.index_in_run() != -1;
- }
-
- template <typename P>
- inline
- void
- p_runs_bkd_piter_<P>::invalidate_()
- {
- p_.set_index_in_run(-1);
- }
-
- template <typename P>
- inline
- void
- p_runs_bkd_piter_<P>::start_()
- {
- p_.goto_run_end(s_->nruns() - 1);
- }
-
- template <typename P>
- inline
- void
- p_runs_bkd_piter_<P>::next_()
- {
- p_.dec_index_in_run();
- if (p_.index_in_run() == -1)
- p_.goto_run_end(p_.run_index() - 1);
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
-} // end of namespace mln
-
-
-#endif // ! MLN_CORE_SITE_SET_P_RUNS_HH
Index: geraud/win_fun.cc
--- geraud/win_fun.cc (revision 3151)
+++ geraud/win_fun.cc (working copy)
@@ -1,160 +0,0 @@
-# include <mln/core/image/image2d.hh>
-# include <mln/core/alias/window2d.hh>
-# include <mln/win/rectangle2d.hh>
-# include <mln/win/fun.hh>
-
-# include <mln/debug/iota.hh>
-# include <mln/debug/println.hh>
-
-
-// # include <mln/morpho/gradient.bis.hh>
-// # include <mln/morpho/erosion.bis.hh>
-
-// # include <mln/value/int_u8.hh>
-// # include <mln/io/pgm/load.hh>
-// # include <mln/io/pgm/save.hh>
-
-
-template <typename I, typename W, typename P>
-void picture(const I& ima, const W& win, const P& p)
-{
- std::cout << ima(p) << ": ";
- mln_qiter(W) q(win, p);
- for_all(q)
- if (ima.has(q))
- std::cout << ima(q) << ' ';
- else
- std::cout << "- ";
- std::cout << std::endl;
-}
-
-
-
-struct uni_t
-{
- typedef mln::window2d result;
- mln::window2d win_;
- uni_t() { win_.insert(-1,0).insert(0,-1); }
- const mln::window2d& operator()(const mln::point2d& p) const { return win_; }
-} uni;
-
-
-struct bi_t
-{
- typedef mln::window2d result;
- mln::window2d win1_, win2_;
- bi_t() {
- win1_.insert(-1,0).insert(0,-1);
- win2_.insert( 1,0).insert(0, 1);
- }
- const mln::window2d& operator()(const mln::point2d& p) const {
- return p.col() % 2 ? win1_ : win2_;
- }
-} bi;
-
-
-struct bi_rect_t
-{
- typedef mln::win::rectangle2d result;
- result *win1_, *win2_;
- bi_rect_t() {
- win1_ = new result(1,3);
- win2_ = new result(3,1);
- }
- const result& operator()(const mln::point2d& p) const {
- return p.row() % 2 ? *win1_ : *win2_;
- }
-} bi_rect;
-
-
-// template <typename T>
-// struct grad_t
-// {
-// typedef mln::win::rectangle2d result;
-// mln::image2d<T> grad_;
-// std::vector<result*> win_;
-
-// grad_t(const mln::image2d<T>& gr)
-// {
-// grad_ = gr;
-// for (unsigned i = 0; i < 10; ++i)
-// {
-// unsigned l = i % 2 ? i : i + 1;
-// win_.push_back(new result(l, l));
-// }
-// }
-// const result& operator()(const mln::point2d& p) const {
-// float s = 1.f - grad_(p) / 256.f;
-// s *= s * s;
-// return * win_[unsigned(s * 9)];
-// }
-// };
-
-
-
-
-int main()
-{
- using namespace mln;
-
- typedef image2d<unsigned> I;
- I ima(2, 3, 0); // no border
- debug::iota(ima);
- debug::println(ima);
-
-
- {
- win::fun<uni_t> win(uni);
- mln_fwd_piter_(I) p(ima.domain());
- for_all(p)
- picture(ima, win, p);
- std::cout << std::endl;
- }
-
- {
- win::fun<bi_t> win(bi);
- mln_fwd_piter_(I) p(ima.domain());
- for_all(p)
- picture(ima, win, p);
- std::cout << std::endl;
- }
-
- {
- win::rectangle2d rect(3, 3);
- mln_fwd_piter_(I) p(ima.domain());
- for_all(p)
- picture(ima, rect, p);
- std::cout << std::endl;
- }
-
- {
- win::fun<bi_rect_t> win(bi_rect);
- mln_fwd_piter_(I) p(ima.domain());
- for_all(p)
- picture(ima, win, p);
- std::cout << std::endl;
- }
-
-
-
-// {
-// using value::int_u8;
-// image2d<int_u8> ima(2, 2);
-// // io::pgm::load(ima, "small.pgm");
-
-// window2d c4p;
-// c4p.insert(-1,0).insert(0,-1).insert(0,0).insert(0,1).insert(1,0);
-
-// grad_t<int_u8> f(morpho::gradient(ima, c4p));
-// win::fun< grad_t<int_u8> > win(f);
-
-// image2d<int_u8> ero = morpho::erosion(ima, win);
-// // io::pgm::save(ero, "ero.pgm");
-
-// mln_fwd_piter_(I) p(ima.domain());
-// for_all(p)
-// picture(ima, win, p);
-// std::cout << std::endl;
-// }
-
-}
Index: geraud/browsing/fwd.cc
--- geraud/browsing/fwd.cc (revision 3151)
+++ geraud/browsing/fwd.cc (working copy)
@@ -1,515 +0,0 @@
-# include <mln/core/image/image2d.hh>
-# include <mln/core/alias/window2d.hh>
-# include <mln/value/int_u8.hh>
-# include <mln/accu/min_h.hh>
-# include <mln/accu/max_h.hh>
-# include <mln/opt/at.hh>
-
-# include <mln/debug/println.hh>
-# include <mln/debug/iota.hh>
-
-# include "fwd.hh"
-
-
-struct base
-{
- void init() {}
- void final() {}
-
- void next() {}
-
- void begin() {}
- void end() {}
-};
-
-
-
-template <typename I_>
-struct iota : base
-{
- typedef I_ I;
-
- I input;
- mln_psite(I) p;
-
- unsigned c;
-
- void init()
- {
- c = 0;
- }
-
- void next()
- {
- input(p) = ++c;
- }
-};
-
-
-
-template <typename I_, typename A, typename W>
-struct accu_win : base
-{
- typedef I_ I;
-
- I input;
- W win;
- mln_psite(I) p;
- mln_qiter(W) q;
-
- mln_accu_with(A, mln_value(I)) a;
-
- accu_win(const I& input,
- const W& win)
- : input(input),
- win(win),
- p(),
- q(win, p)
- {
- }
-
- void next()
- {
- a.init();
- for_all(q) if (input.has(q))
- a.take(input(q));
- std::cout << a << ' ';
- }
-
- void final()
- {
- std::cout << std::endl;
- }
-};
-
-
-// generic(accu, ima)
-
-
-namespace mln
-{
-
- // template <typename I>
- // void line_inc(const I& ima, unsigned half)
- // {
- // box2d b = ima.domain();
- // unsigned nrows = b.nrows(), ncols = b.ncols();
-
- // for (unsigned row = 0; row < nrows; ++row)
- // {
- // unsigned col = 0;
-
- // std::cout << std::endl
- // << "START : "
- // << std::endl
- // << std::endl;
-
- // for (unsigned c = 0; c <= half; ++c)
- // std::cout << " take " << opt::at(ima, row, c) << " ";
- // std::cout << std::endl;
-
- // std::cout << " --> OK at " << opt::at(ima, row, col) << std::endl;
- // // ok (row, col) at line start
-
-
- // std::cout << std::endl
- // << "BEGIN : "
- // << std::endl
- // << std::endl;
-
- // unsigned col_plus = half;
-
- // while (col < half)
- // {
- // ++col;
- // ++col_plus;
- // std::cout << " take " << opt::at(ima, row, col_plus) << " ";
- // std::cout << " --> OK at " << opt::at(ima, row, col) << std::endl;
- // }
-
- // std::cout << std::endl
- // << "MIDDLE : "
- // << std::endl
- // << std::endl;
-
- // int col_minus = -1;
-
- // while (col < ncols - half - 1)
- // {
- // ++col;
- // ++col_plus;
- // ++col_minus;
- // std::cout << " take " << opt::at(ima, row, col_plus) << " ";
- // std::cout << " untake " << opt::at(ima, row, col_minus) << " ";
- // std::cout << " --> OK at " << opt::at(ima, row, col) << std::endl;
- // // ok (row, col) at line middle
- // }
- // std::cout << std::endl;
-
-
- // std::cout << std::endl
- // << "END : "
- // << std::endl
- // << std::endl;
-
- // while (col < ncols - 1)
- // {
- // ++col;
- // ++col_minus;
- // std::cout << " untake " << opt::at(ima, row, col_minus) << " ";
- // std::cout << " --> OK at " << opt::at(ima, row, col) << std::endl;
- // }
- // std::cout << std::endl;
-
- // abort();
- // }
- // }
-
-
-
- /*
-
- template <typename I>
- void line_inc(const I& ima,
- const mln_site(I)& pstart, unsigned len,
- unsigned half)
- {
- unsigned row = pstart.row();
- const unsigned col_start = pstart.col();
- const unsigned col_last = col_start + len - 1;
-
- std::cout << std::endl
- << "START : "
- << std::endl
- << std::endl;
-
- unsigned col = col_start;
-
- for (unsigned c = 0; c <= half && c < len; ++c)
- std::cout << " take " << opt::at(ima, row, col + c) << " ";
- std::cout << std::endl;
-
- std::cout << " --> OK at " << opt::at(ima, row, col) << std::endl;
- // ok (row, col) at line start
-
- if (col == col_last)
- return;
-
- std::cout << std::endl
- << "BEGIN : "
- << std::endl
- << std::endl;
-
- unsigned col_plus = col_start + half;
-
- while (col < col_start + half && col < col_last)
- {
- ++col;
- ++col_plus;
- if (col_plus <= col_last)
- std::cout << " take " << opt::at(ima, row, col_plus) << " ";
- std::cout << " --> OK at " << opt::at(ima, row, col) << std::endl;
- }
-
- if (col == col_last)
- return;
-
- std::cout << std::endl
- << "MIDDLE : "
- << std::endl
- << std::endl;
-
- int col_minus = col_start - 1;
-
-
- while (col < col_last - half)
- {
- ++col;
- ++col_plus;
- ++col_minus;
- mln_invariant(col_plus >= col_start && col_plus <= col_last);
- std::cout << " take " << opt::at(ima, row, col_plus) << " ";
- mln_invariant(col_minus >= col_start && col_minus <= col_last);
- std::cout << " untake " << opt::at(ima, row, col_minus) << " ";
- std::cout << " --> OK at " << opt::at(ima, row, col) << std::endl;
- // ok (row, col) at line middle
- }
- std::cout << std::endl;
-
- if (col == col_last)
- return;
-
- std::cout << std::endl
- << "END : "
- << std::endl
- << std::endl;
-
- while (col < col_last)
- {
- ++col;
- ++col_minus;
- mln_invariant(col_minus >= col_start && col_minus <= col_last);
- std::cout << " untake " << opt::at(ima, row, col_minus) << " ";
- std::cout << " --> OK at " << opt::at(ima, row, col) << std::endl;
- }
- std::cout << std::endl;
-
- }
-
- */
-
-
-
- /*
-
- template <typename I>
- void line_inc(unsigned dir,
- const I& ima,
- const mln_site(I)& p_start, unsigned len,
- unsigned half)
- {
- typedef mln_site(I) P;
- const unsigned start = p_start[dir];
- const unsigned last = start + len - 1;
-
- std::cout << std::endl
- << "START : "
- << std::endl
- << std::endl;
-
- P p = p_start;
-
- P q = p;
- for (unsigned c = 0; c <= half && c < len; ++c)
- {
- std::cout << " take " << ima(q) << " ";
- ++q[dir];
- }
- std::cout << std::endl;
-
- std::cout << " --> OK at " << ima(p) << std::endl;
-
- def::coord& cur = p[dir];
- if (cur == last)
- return;
-
- std::cout << std::endl
- << "BEGIN : "
- << std::endl
- << std::endl;
-
- P p_plus = p_start;
- def::coord& plus = p_plus[dir];
- plus += half;
-
- while (cur < start + half && cur < last)
- {
- ++cur;
- ++plus;
- if (plus <= last)
- std::cout << " take " << ima(p_plus) << " ";
- std::cout << " --> OK at " << ima(p) << std::endl;
- }
-
- if (cur == last)
- return;
-
- std::cout << std::endl
- << "MIDDLE : "
- << std::endl
- << std::endl;
-
- P p_minus = p_start;
- def::coord& minus = p_minus[dir];
- --minus;
-
- while (cur < last - half)
- {
- ++cur;
- ++plus;
- ++minus;
- mln_invariant(plus >= start && plus <= last);
- std::cout << " take " << ima(p_plus) << " ";
- mln_invariant(minus >= start && minus <= last);
- std::cout << " untake " << ima(p_minus) << " ";
- std::cout << " --> OK at " << ima(p) << std::endl;
- // ok (row, cur) at line middle
- }
- std::cout << std::endl;
-
- if (cur == last)
- return;
-
- std::cout << std::endl
- << "END : "
- << std::endl
- << std::endl;
-
- while (cur < last)
- {
- ++cur;
- ++minus;
- mln_invariant(minus >= start && minus <= last);
- std::cout << " untake " << ima(p_minus) << " ";
- std::cout << " --> OK at " << ima(p) << std::endl;
- }
- std::cout << std::endl;
-
- }
-
-*/
-
-
- template <typename I, typename A, typename O>
- void line_inc(unsigned dir,
- const I& input,
- const mln_site(I)& p_start, unsigned len,
- A a, unsigned half,
- O& output)
- {
- typedef mln_site(I) P;
- const unsigned start = p_start[dir];
- const unsigned last = start + len - 1;
-
- std::cout << std::endl
- << "START : "
- << std::endl
- << std::endl;
-
- P p = p_start;
- a.init();
-
- P q = p;
- for (unsigned c = 0; c <= half && c < len; ++c)
- {
- a.take(input(q));
- std::cout << " take " << debug::format(input(q)) << " ";
- ++q[dir];
- }
- std::cout << std::endl;
-
- std::cout << " --> OK at " << debug::format(input(p)) << std::endl;
- output(p) = a;
-
- def::coord& cur = p[dir];
- if (cur == last)
- return;
-
- std::cout << std::endl
- << "BEGIN : "
- << std::endl
- << std::endl;
-
- P p_plus = p_start;
- def::coord& plus = p_plus[dir];
- plus += half;
-
- while (cur < start + half && cur < last)
- {
- ++cur;
- ++plus;
- if (plus <= last)
- {
- a.take(input(p_plus));
- std::cout << " take " << debug::format(input(p_plus)) << " ";
- }
- std::cout << " --> OK at " << debug::format(input(p)) << std::endl;
- output(p) = a;
- }
-
- if (cur == last)
- return;
-
- std::cout << std::endl
- << "MIDDLE : "
- << std::endl
- << std::endl;
-
- P p_minus = p_start;
- def::coord& minus = p_minus[dir];
- --minus;
-
- while (cur < last - half)
- {
- ++cur;
- ++plus;
- ++minus;
- mln_invariant(plus >= start && plus <= last);
- a.take(input(p_plus));
- std::cout << " take " << debug::format(input(p_plus)) << " ";
- mln_invariant(minus >= start && minus <= last);
- a.untake(input(p_minus));
- std::cout << " untake " << debug::format(input(p_minus)) << " ";
- std::cout << " --> OK at " << debug::format(input(p)) << std::endl;
- output(p) = a;
- // ok (row, cur) at line middle
- }
- std::cout << std::endl;
-
- if (cur == last)
- return;
-
- std::cout << std::endl
- << "END : "
- << std::endl
- << std::endl;
-
- while (cur < last)
- {
- ++cur;
- ++minus;
- mln_invariant(minus >= start && minus <= last);
- a.untake(input(p_minus));
- std::cout << " untake " << debug::format(input(p_minus)) << " ";
- std::cout << " --> OK at " << debug::format(input(p)) << std::endl;
- output(p) = a;
- }
- std::cout << std::endl;
-
- }
-
-
-
-} // mln
-
-
-
-
-int main()
-{
- using namespace mln;
- using value::int_u8;
-
- typedef image2d<int_u8> I;
- I ima(12, 12);
- debug::iota(ima);
- debug::println(ima);
-
-
- I out(12, 12);
- point2d p_start(0, 0);
- line_inc(0, // dir
- ima, p_start, ima.ncols(),
- accu::min_h<int_u8>(), 4, // half
- out);
-
- debug::println(out);
-
-
-// typedef window2d W;
-// W win;
-// win.insert(dpoint2d(0,-1));
-// win.insert(dpoint2d(0, 0));
-// win.insert(dpoint2d(0, 1));
-
-// accu_win<I, accu::min, W> f(ima, win);
-// canvas::browsing::fwd(f);
-
-// canvas::browsing::row_fwd(f);
-
-// iota<I> f;
-// f.input = ima;
-// canvas::browsing::col_fwd(f);
-// debug::println(ima);
-
-}
Index: geraud/browsing/fwd.hh
--- geraud/browsing/fwd.hh (revision 3151)
+++ geraud/browsing/fwd.hh (working copy)
@@ -1,88 +0,0 @@
-
-
-namespace mln
-{
-
- namespace canvas
- {
-
- namespace browsing
- {
-
- template <typename F>
- void fwd(F& f)
- {
- trace::entering("canvas::browsing::fwd");
- mln_precondition(f.input.is_valid());
- typedef typename F::I I;
- mln_fwd_piter(I) p(f.input.domain());
- f.init();
- for_all(p)
- {
- f.p = p;
- f.next();
- }
- f.final();
- trace::exiting("canvas::browsing::fwd");
- }
-
-
- template <typename F>
- void row_fwd(F& f)
- {
- trace::entering("canvas::browsing::row_fwd");
- mln_precondition(f.input.is_valid());
- box2d b = f.input.domain();
- unsigned nrows = b.nrows(), ncols = b.ncols();
- def::coord& row = f.p.row();
- def::coord& col = f.p.col();
-
- f.init();
- for (row = 0; row < nrows; ++row)
- {
- col = 0;
- f.begin();
- while (col < ncols)
- {
- f.next();
- ++col;
- }
- f.end();
- }
- f.final();
- trace::exiting("canvas::browsing::row_fwd");
- }
-
-
- template <typename F>
- void col_fwd(F& f)
- {
- trace::entering("canvas::browsing::col_fwd");
- mln_precondition(f.input.is_valid());
- box2d b = f.input.domain();
- unsigned nrows = b.nrows(), ncols = b.ncols();
- def::coord& row = f.p.row();
- def::coord& col = f.p.col();
-
- f.init();
- for (col = 0; col < ncols; ++col)
- {
- row = 0;
- f.begin();
- while (row < nrows)
- {
- f.next();
- ++row;
- }
- f.end(); // FIXME: p invalid...
- }
- f.final();
- trace::exiting("canvas::browsing::col_fwd");
- }
-
-
- } // end of namespace mln::canvas::browsing
-
- } // end of namespace mln::canvas
-
-} // end of namespace mln
Index: geraud/cs2d/cs2d.cc
--- geraud/cs2d/cs2d.cc (revision 3151)
+++ geraud/cs2d/cs2d.cc (working copy)
@@ -1,110 +0,0 @@
-# include "cs2d.hh"
-# include "cs2d_morpho.hh"
-# include "dbl_neighb.hh"
-
-# include <mln/debug/println.hh>
-
-# include <mln/io/pgm/load.hh>
-# include <mln/io/pgm/save.hh>
-# include <mln/io/ppm/save.hh>
-
-# include <mln/data/paste.hh>
-# include <mln/data/fill.hh>
-
-# include <mln/morpho/dilation.hh>
-# include <mln/morpho/meyer_wst.hh>
-# include <mln/morpho/closing_area.hh>
-
-# include <mln/logical/not.hh>
-# include <mln/labeling/blobs.hh>
-# include <mln/accu/mean.hh>
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm lambda output.pgm" << std::endl;
- abort();
-}
-
-
-struct is_row_odd_t
-{
- bool operator()(const mln::point2d& p) const
- {
- return p.row() % 2;
- }
-} is_row_odd;
-
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 4)
- usage(argv);
-
-
- using namespace mln;
- using value::int_u8;
-
- // trace::quiet = false;
-
- cmorpho::dbl_neighb2d nbh_e;
- nbh_e
- .insert_even(dpoint2d(-1,-1))
- .insert_even(dpoint2d(-1,+1))
- .insert_even(dpoint2d( 0,-2))
- .insert_odd(dpoint2d(-2, 0))
- .insert_odd(dpoint2d(-1,-1))
- .insert_odd(dpoint2d(-1,+1));
-
- // display_masks(make::box2d(2,3));
-
- image2d<int_u8> lena;
- io::pgm::load(lena, argv[1]);
-
- cs2d<int_u8, int_u8, int_u8> cs(lena.domain());
-
- fill_cells_with(cs, lena);
- data::fill(cs.vertex, 0);
-
- cmorpho::dbl_neighb2d nbh_g;
- nbh_g.insert_odd(up).insert_even(left);
- data::paste(cmorpho::gradient(cs.edge, nbh_g),
- cs.edge);
- // io::pgm::save(cs.impl, "grad.pgm");
-
- int lambda = atoi(argv[2]);
- if (lambda < 0)
- usage(argv);
-
- if (lambda != 0)
- data::paste(morpho::closing_area(cs.edge, nbh_e, lambda), cs.edge);
-
- cs2d<int_u8, bool, bool> cs_(lena.domain());
- data::fill(cs_.impl, false);
- fill_cells_with(cs_, lena);
-
- unsigned l;
- data::fill(cs_.edge,
- pw::value(cmorpho::meyer_wst(cs.edge, nbh_e, l)) == pw::cst(0));
- std::cout << "l = " << l << std::endl;
-
- data::paste(morpho::dilation(cs_.vertex,
- convert::to_window(c4())),
- cs_.vertex);
-
- unsigned L;
- // debug::println(cs_.impl);
- image2d<unsigned> label = labeling::blobs(logical::not_(cs_.impl), c4(), L);
- // debug::println(label);
- mln_invariant(L == l);
-
- std::vector<int_u8> v(l + 1);
- accu::compute<accu::mean>(cs_.cell, label, v);
-
- data::fill(cs_.cell, level::transform(label, v));
- io::pgm::save(cell_image(cs_), argv[3]);
-
-// io::ppm::save(pack(cs_, colorize, 7), "log.ppm");
-}
Index: geraud/cs2d/tuto.cc
--- geraud/cs2d/tuto.cc (revision 3151)
+++ geraud/cs2d/tuto.cc (working copy)
@@ -1,145 +0,0 @@
-# include <mln/core/image/image2d.hh>
-# include <mln/core/image/image_if.hh>
-
-# include <mln/core/alias/neighb2d.hh>
-# include <mln/core/alias/window2d.hh>
-# include <mln/convert/to_window.hh>
-
-# include <mln/debug/println.hh>
-# include <mln/fun/p2v/iota.hh>
-# include <mln/data/paste.hh>
-# include <mln/data/fill.hh>
-# include <mln/morpho/dilation.hh>
-
-
-
- struct is_cell_t : mln::Function_p2b<is_cell_t>
- {
- typedef bool result;
- bool operator()(const mln::point2d& p) const
- {
- return p.row() % 2 == 0 && p.col() % 2 == 0;
- }
- }
- is_cell;
-
- struct is_edge_t : mln::Function_p2b<is_edge_t>
- {
- typedef bool result;
- bool operator()(const mln::point2d& p) const
- {
- return p.row() % 2 + p.col() % 2 == 1;
- }
- }
- is_edge;
-
- struct is_point_t : mln::Function_p2b<is_point_t>
- {
- typedef bool result;
- bool operator()(const mln::point2d& p) const
- {
- return p.row() % 2 && p.col() % 2;
- }
- }
- is_point;
-
-
-
-int main()
-{
- using namespace mln;
-
- window2d c4 = convert::to_window(mln::c4());
-
- {
- image2d<char> ima(3, 5);
-
- data::fill(ima, 'o');
-
- debug::println(ima);
- // o o o o o
- // o o o o o
- // o o o o o
-
- debug::println(ima | is_cell);
- // o o o
- //
- // o o o
-
- data::fill((ima | is_cell).rw(), 'c');
- data::fill((ima | is_edge).rw(), 'e');
- data::fill((ima | is_point).rw(), 'p');
-
- debug::println(ima);
- // c e c e c
- // e p e p e
- // c e c e c
- }
-
- {
- image2d<int> ima(3, 5);
-
- data::fill(ima, 0);
- debug::println(ima);
- // 0 0 0 0 0
- // 0 0 0 0 0
- // 0 0 0 0 0
-
- data::fill((ima | is_cell).rw(), fun::p2v::iota);
- debug::println(ima | is_cell);
- // 1 2 3
- //
- // 4 5 6
-
- // --- for the record:
- // debug::println(morpho::dilation(ima, win::square(3)));
-
- debug::println(ima);
- // 1 0 2 0 3
- // 0 0 0 0 0
- // 4 0 5 0 6
-
- debug::println(ima | is_edge);
- // 0 0
- // 0 0 0
- // 0 0
-
- debug::println(morpho::dilation(ima | is_edge, c4));
- // 2 3
- // 4 5 6
- // 5 6
-
- // Attention : les traitements ne travaillent généralement pas en
- // place ; l'entrée n'est pas modifiée, une nouvelle image est
- // retournée. Dans le code ci-dessus, l'image dilatée est envoyée
- // à la routine d'affichage puis, n'étant plus utilisée, elle est
- // automatiquement désallouée.
-
- // On peut vérifier que 'ima' n'a pas été modifié :
-
- debug::println(ima);
- // 1 0 2 0 3
- // 0 0 0 0 0
- // 4 0 5 0 6
-
- // En revanche, rien n'empêche de "coller" le résultat d'un
- // traitement dans l'image d'entrée :
-
- data::paste(morpho::dilation(ima | is_edge, c4), ima);
-
- // Maintenant, le dilaté de "ima restreint à edge" est collé dans
- // 'ima' :
-
- debug::println(ima);
- // 1 2 2 3 3
- // 4 0 5 0 6
- // 4 5 5 6 6
-
- data::paste(morpho::dilation(ima | is_point, c4), ima);
- debug::println(ima);
- // 1 2 2 3 3
- // 4 5 5 6 6
- // 4 5 5 6 6
- }
-
-}
Index: geraud/cs2d/kruskal.cc
--- geraud/cs2d/kruskal.cc (revision 3151)
+++ geraud/cs2d/kruskal.cc (working copy)
@@ -1,357 +0,0 @@
-# include <vector>
-
-# include <mln/core/image/image2d.hh>
-# include <mln/core/image/sub_image.hh>
-# include <mln/core/image/image_if.hh>
-# include <mln/core/image_if_value.hh>
-
-# include <mln/core/alias/neighb2d.hh>
-# include <mln/core/alias/window2d.hh>
-# include <mln/convert/to_window.hh>
-
-# include <mln/debug/println.hh>
-# include <mln/debug/iota.hh>
-# include <mln/fun/p2v/iota.hh>
-# include <mln/data/paste.hh>
-# include <mln/data/fill.hh>
-# include <mln/morpho/gradient.hh>
-# include <mln/morpho/meyer_wst.hh>
-
-# include <mln/level/sort_points.hh>
-
-# include <mln/io/pgm/load.hh>
-# include <mln/io/ppm/save.hh>
-# include <mln/value/int_u8.hh>
-# include <mln/pw/all.hh>
-# include <mln/win/rectangle2d.hh>
-
-# include <mln/value/rgb8.hh>
-# include <mln/literal/black.hh>
-# include <mln/literal/white.hh>
-# include <mln/literal/colors.hh>
-
-# include <mln/labeling/regional_minima.hh>
-
-# include "dbl_neighb.hh"
-
-
-
-// KRUSKAL-MST(G, w)
-// T := Ø
-// for each vertex u in V
-// MAKE-SET(DS, u)
-// end for
-// for each edge (u,v) in E in order of nondecreasing weight
-// if FIND-SET(DS, u) != FIND-SET(DS, v)
-// UNION-SET(DS, u, v)
-// T := T U {(u,v)}
-// end for
-// return T
-
-
-
-struct is_cell_t : mln::Function_p2b<is_cell_t>
-{
- typedef bool result;
- bool operator()(const mln::point2d& p) const
- {
- return p.row() % 2 == 0 && p.col() % 2 == 0;
- }
-}
- is_cell;
-
-struct is_edge_t : mln::Function_p2b<is_edge_t>
-{
- typedef bool result;
- bool operator()(const mln::point2d& p) const
- {
- return p.row() % 2 + p.col() % 2 == 1;
- }
-}
- is_edge;
-
-struct is_point_t : mln::Function_p2b<is_point_t>
-{
- typedef bool result;
- bool operator()(const mln::point2d& p) const
- {
- return p.row() % 2 && p.col() % 2;
- }
-}
- is_point;
-
-
-struct is_row_odd_t
- {
- bool operator()(const mln::point2d& p) const
- {
- return p.row() % 2;
- }
- } is_row_odd;
-
-
-template<typename T_t>
-struct is_tree_t : mln::Function_p2b< is_tree_t<T_t> >
-{
- typedef bool result;
- bool operator()(const mln::point2d& p) const
- {
- return p.row() % 2 + p.col() % 2 == 1 && T(p) == true;
- }
- T_t T;
-};
-
-namespace mln
-{
-
- template <typename E>
- image2d<value::rgb8> show_edge(const E& edge,
- unsigned nrows,unsigned ncols,
- unsigned clen)
- {
- mln_precondition(clen % 2); // oddity
-
- typedef win::hline2d H;
- H hline(clen);
-
- typedef win::vline2d V;
- V vline(clen);
-
- box2d b(nrows * clen + 3 * (nrows - 1),
- ncols * clen + 3 * (ncols - 1));
- image2d<value::rgb8> output(b);
- data::fill(output, literal::black);
-
-
- // 0 1 2 3 4
- // 0 c e c e c
- // 1 e x e x e
- // 2 c e c e c
-
- // 0 1 2 3 4 5 6 7 8 9 10
-
- // 0 c c c . e . c c c . e . c c c
- // 1 c c c . e . c c c . e . c c c
- // 2 c c c . e . c c c . e . c c c
- // 3 . . . . . . . . . . . . . . .
- // 4 e e e . x . e e e . x . e e e
- // 5 . . . . . . . . . . . . . . .
- // 6 c c c . e . c c c . e . c c c
- // 7 c c c . e . c c c . e . c c c
- // 8 c c c . e . c c c . e . c c c
-
- // Edges.
- mln_piter(E) e(edge.domain());
- for_all(e)
- {
- value::rgb8 v;
- if (edge(e))
- v = literal::red;
- else
- v = literal::black;
- point2d e_ = e, p_;
- if (e_.row() % 2) // Odd => horizontal.
- {
- p_.row() = clen + 1 + (clen + 3) * (e_.row() / 2); // vertex-like
- p_.col() = clen / 2 + (clen + 3) * (e_.col() / 2); // cell-like
- mln_qiter(V) q(hline, p_);
- for_all(q) if (output.has(q))
- output(q) = v;
- }
- else // Even => vertical.
- {
- p_.row() = clen / 2 + (clen + 3) * (e_.row() / 2); // cell-like
- p_.col() = clen + 1 + (clen + 3) * (e_.col() / 2); // vertex-like
- mln_qiter(H) q(vline, p_);
- for_all(q) if (output.has(q))
- output(q) = v;
- }
- }
-
- return output;
- }
-
-} // mln
-
-
-#define mln_VAR(Var, Expr) typeof(Expr) Var = Expr;
-
-
-template <typename DS_t, typename U>
-void make_set(DS_t& DS, const U& u)
-{
- DS(u) = u;
-}
-
-
-template <typename DS_t, typename U>
-U find_set(DS_t& DS, U u)
-{
- if (DS(u) == u) // is root
- return u;
- return DS(u) = find_set(DS, DS(u));
-}
-
-
-template <typename DS_t, typename U>
-void union_set(DS_t& DS, const U& u, const U& v)
-{
- U ru = find_set(DS, u),
- rv = find_set(DS, v);
- mln_precondition(ru != rv);
- if (rv > ru)
- DS(ru) = rv;
- else
- DS(rv) = ru;
-}
-
-
-
-int main()
-{
- using namespace mln;
- using value::int_u8;
-
- window2d c4 = convert::to_window(mln::c4());
-
-
- typedef dbl_neighb_<dpoint2d, is_row_odd_t> nbh_t;
- nbh_t nbh_e2c, win_p_e2c, nbh_e2e;
-
- {
- bool e2c_h[] = { 0, 1, 0,
- 0, 0, 0,
- 0, 1, 0 };
-
- bool e2c_v[] = { 0, 0, 0,
- 1, 0, 1,
- 0, 0, 0 };
- nbh_e2c
- .when_true (make::neighb2d(e2c_h))
- .when_false(make::neighb2d(e2c_v));
-
- win_p_e2c = nbh_e2c;
- win_p_e2c
- .insert_true(dpoint2d(0,0))
- .insert_false(dpoint2d(0,0));
-
- bool e2e_h[] = { 0, 0, 1, 0, 0,
- 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 0,
- 0, 0, 1, 0, 0 };
-
- bool e2e_v[] = { 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 0,
- 1, 0, 0, 0, 1,
- 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0 };
- nbh_e2e
- .when_true (make::neighb2d(e2e_h))
- .when_false(make::neighb2d(e2e_v));
- }
-
- typedef image2d<int_u8> I;
-
- image2d<int_u8> input;
- io::pgm::load(input, "fly.pgm");
-
- image2d<int_u8> ima(input.nrows() * 2 - 1,
- input.ncols() * 2 - 1, 0);
-
- mln_VAR(cell, ima | is_cell);
- typedef typeof(cell) cell_t;
- debug::println(cell);
-
- {
- mln_fwd_piter_(I) pi(input.domain());
- mln_fwd_piter_(cell_t) pc(cell.domain());
- for_all_2(pi, pc)
- cell(pc) = input(pi);
- }
-
- mln_VAR(edge, ima | is_edge);
- data::paste(morpho::gradient(edge, nbh_e2c), edge);
- // ^^^^^^^
- // edge -> neighboring cells
-
- debug::println(edge);
-
- typedef typeof(edge) edge_t;
-
- typedef p_array<point2d> Arr;
- Arr E = level::sort_points_increasing(edge);
-
- // Aux data.
- mln_ch_value_(edge_t, bool) T;
- initialize(T, edge);
- data::fill(T, false);
-
- mln_ch_value_(cell_t, point2d) DS;
- initialize(DS, cell);
-
- {
- mln_piter_(cell_t) u(cell.domain());
- for_all(u) // in V
- make_set(DS, u);
- }
-
- {
- mln_fwd_piter_(Arr) uv(E);
- for_all(uv)
- {
- point2d
- uv_ = uv.to_point(),
- u, v;
- if (uv_.row() % 2)
- u = uv_ + up, v = uv_ + down;
- else
- u = uv_ + left, v = uv_ + right;
- if (find_set(DS, u) != find_set(DS, v))
- {
- union_set(DS, u, v);
- T(uv) = true;
- }
- }
- }
-
- debug::println(T);
-
- mln_VAR(is_T, pw::value(T) == pw::cst(true));
-
- mln_VAR(dom, (T | is_T).domain());
- typedef typeof(dom) dom_t;
-
- io::ppm::save(show_edge(T, input.nrows(), input.ncols(), 7),
- "edge.ppm");
-
-
- typedef typeof(T) T_t;
- is_tree_t<T_t> is_tree;
- is_tree.T = T;
- // [*] See EOF.
-
- unsigned nbasins;
- mln_VAR(wst, morpho::meyer_wst(ima | is_tree, nbh_e2e, nbasins) );
- std::cout << "nbasins : " << nbasins << std::endl;
-
- {
- mln_piter_(dom_t) e(dom);
- mln_niter_(nbh_t) n(nbh_e2c, e);
- for_all(e)
- if (wst(e) != 0)
- for_all(n)
- cell(n) = wst(e);
- debug::println(cell);
- }
-
-}
-
-// [*] FIXME: "edge | is_T" does not properly work because of
-// initialization failure of the predicate function (pw expr do not
-// have ctor without arg so the init cannot be delayed). As a
-// consequence, we cannot have the following code:
-//
-// mln_VAR(tree, edge | is_T);
-// typedef typeof(tree) tree_t;
-// morpho::meyer_wst(tree, nbh_e2e, nbasins);
Index: geraud/cs2d/cs2d_utils.hh
--- geraud/cs2d/cs2d_utils.hh (revision 3151)
+++ geraud/cs2d/cs2d_utils.hh (working copy)
@@ -1,251 +0,0 @@
-# include <mln/value/rgb8.hh>
-# include <mln/value/int_u8.hh>
-# include <mln/literal/black.hh>
-# include <mln/literal/white.hh>
-# include <mln/literal/colors.hh>
-# include <mln/win/rectangle2d.hh>
-# include <mln/data/fill.hh>
-
-
-namespace mln
-{
-
- // 0 1 2
- // 0 c c c
- // 1 c c c
-
- // 0 1 2 3 4
- // 0 c e c e c
- // 1 e x e x e
- // 2 c e c e c
-
-
- struct is_cell_t : Function_p2b<is_cell_t>
- {
- typedef bool result;
- bool operator()(const point2d& p) const
- {
- return p.row() % 2 == 0 && p.col() % 2 == 0;
- }
- }
- is_cell;
-
-
- struct is_edge_t : Function_p2b<is_edge_t>
- {
- typedef bool result;
- bool operator()(const point2d& p) const
- {
- return p.row() % 2 + p.col() % 2 == 1;
- }
- }
- is_edge;
-
-
- struct is_vertex_t : Function_p2b<is_vertex_t>
- {
- typedef bool result;
- bool operator()(const point2d& p) const
- {
- return p.row() % 2 && p.col() % 2;
- }
- }
- is_vertex;
-
-
-
- void display_masks(box2d b)
- {
- box2d b_(2 * b.nrows() - 1, 2 * b.ncols() - 1);
- image2d<char> tmp(b_);
- mln_piter_(box2d) p(b_);
- for_all(p)
- if (is_cell(p))
- {
- mln_invariant(! is_edge(p) && ! is_vertex(p));
- tmp(p) = 'O';
- }
- else if (is_edge(p))
- {
- mln_invariant(! is_cell(p) && ! is_vertex(p));
- tmp(p) = p.to_point().row() % 2 ? '-' : '|';
- }
- else if (is_vertex(p))
- {
- mln_invariant(! is_edge(p) && ! is_cell(p));
- tmp(p) = '+';
- }
- else
- mln_invariant(0);
- debug::println(tmp);
- }
-
-
- struct colorize_t
- {
- typedef value::rgb8 result;
- result operator()(value::int_u8 i) const
- {
- return result(i,i,i);
- }
- result operator()(bool b) const
- {
- if (b)
- return literal::red;
- else
- return literal::black;
- }
- }
- colorize;
-
-
- template <typename Cs, typename F>
- image2d<mln_result(F)> pack(const Cs& cs, F f)
- {
- image2d<mln_result(F)> output(cs.b);
- mln_piter(box2d) p(cs.b);
- for_all(p)
- if (is_cell(p))
- output(p) = f(cs.cell(p));
- else if (is_edge(p))
- output(p) = f(cs.edge(p));
- else
- output(p) = f(cs.vertex(p));
- return output;
- }
-
-
- template <typename Cs, typename F>
- image2d<mln_result(F)> pack(const Cs& cs, F f, unsigned clen)
- {
- typedef mln_result(F) R;
-
- mln_precondition(clen % 2); // oddity
-
- typedef win::rectangle2d Sqr;
- Sqr sqr(clen, clen);
-
- typedef win::hline2d H;
- H hline(clen);
-
- typedef win::vline2d V;
- V vline(clen);
-
- // 0 1 2 3 4
- // 0 c e c e c
- // 1 e x e x e
- // 2 c e c e c
-
- // 0 1 2 3 4 5 6 7 8 9 10
-
- // 0 c c c . e . c c c . e . c c c
- // 1 c c c . e . c c c . e . c c c
- // 2 c c c . e . c c c . e . c c c
- // 3 . . . . . . . . . . . . . . .
- // 4 e e e . x . e e e . x . e e e
- // 5 . . . . . . . . . . . . . . .
- // 6 c c c . e . c c c . e . c c c
- // 7 c c c . e . c c c . e . c c c
- // 8 c c c . e . c c c . e . c c c
-
- box2d b(cs.nrows() * clen + 3 * (cs.nrows() - 1),
- cs.ncols() * clen + 3 * (cs.ncols() - 1));
- image2d<R> output(b);
- data::fill(output, literal::black);
-
- // Cells.
- mln_piter(Cs::cell_t) c(cs.cell.domain());
- for_all(c)
- {
- R v = f(cs.cell(c));
- point2d c_ = c.to_point(), p_;
- p_.row() = clen / 2 + (clen + 3) * (c_.row() / 2);
- p_.col() = clen / 2 + (clen + 3) * (c_.col() / 2);
- mln_qiter(Sqr) q(sqr, p_);
- for_all(q)
- output(q) = v;
- }
-
- // Points.
- mln_piter(Cs::vertex_t) x(cs.vertex.domain());
- for_all(x)
- {
- point2d x_ = x, q;
- q.row() = clen + 1 + (clen + 3) * (x_.row() / 2);
- q.col() = clen + 1 + (clen + 3) * (x_.col() / 2);
- output(q) = f(cs.vertex(x));
- }
-
-
- // 0 1 2 3 4
- // 0 c e c e c
- // 1 e x e x e
- // 2 c e c e c
-
- // 0 1 2 3 4 5 6 7 8 9 10
-
- // 0 c c c . e . c c c . e . c c c
- // 1 c c c . e . c c c . e . c c c
- // 2 c c c . e . c c c . e . c c c
- // 3 . . . . . . . . . . . . . . .
- // 4 e e e . x . e e e . x . e e e
- // 5 . . . . . . . . . . . . . . .
- // 6 c c c . e . c c c . e . c c c
- // 7 c c c . e . c c c . e . c c c
- // 8 c c c . e . c c c . e . c c c
-
-
- // Edges.
- mln_piter(Cs::edge_t) e(cs.edge.domain());
- for_all(e)
- {
- R v = f(cs.edge(e));
- point2d e_ = e, p_;
- if (e_.row() % 2) // Odd => horizontal.
- {
- p_.row() = clen + 1 + (clen + 3) * (e_.row() / 2); // vertex-like
- p_.col() = clen / 2 + (clen + 3) * (e_.col() / 2); // cell-like
- mln_qiter(V) q(hline, p_);
- for_all(q) if (output.has(q))
- output(q) = v;
- }
- else // Even => vertical.
- {
- p_.row() = clen / 2 + (clen + 3) * (e_.row() / 2); // cell-like
- p_.col() = clen + 1 + (clen + 3) * (e_.col() / 2); // vertex-like
- mln_qiter(H) q(vline, p_);
- for_all(q) if (output.has(q))
- output(q) = v;
- }
- }
-
- return output;
- }
-
-
-
- template <typename Cs, typename T>
- void fill_cells_with(Cs& cs, const image2d<T>& input)
- {
- mlc_equal(T, typename Cs::cell_value)::check();
- mln_piter(box2d) p(input.domain());
- mln_piter(Cs::cell_t) c(cs.cell.domain());
- for_all_2(p, c)
- cs.cell(c) = input(p);
- }
-
- template <typename Cs>
- image2d<typename Cs::cell_value>
- cell_image(const Cs& cs)
- {
- image2d<typename Cs::cell_value> output(cs.nrows(), cs.ncols());
- mln_piter(box2d) p(output.domain());
- mln_piter(Cs::cell_t) c(cs.cell.domain());
- for_all_2(p, c)
- output(p) = cs.cell(c);
- return output;
- }
-
-} // mln
-
-
Index: geraud/cs2d/cs2d.hh
--- geraud/cs2d/cs2d.hh (revision 3151)
+++ geraud/cs2d/cs2d.hh (working copy)
@@ -1,172 +0,0 @@
-# include <mln/core/image/image2d.hh>
-# include <mln/core/alias/neighb2d.hh>
-# include <mln/core/alias/window2d.hh>
-# include <mln/convert/to_window.hh>
-
-# include <mln/core/image/image_if.hh>
-# include <mln/debug/println.hh>
-
-
-# include "cs2d_utils.hh"
-
-
-namespace mln
-{
-
-
- template <typename C, typename E, typename X>
- struct cs2d
- {
- typedef C cell_value;
- typedef E edge_value;
- typedef X vertex_value;
-
- cs2d(unsigned nrows, unsigned ncols)
- {
- init(nrows, ncols);
- }
-
- cs2d(const box2d& b)
- {
- init(b.nrows(), b.ncols());
- }
-
- void init(unsigned nrows, unsigned ncols)
- {
- mln_precondition(nrows && ncols);
-
- // Raw data (impl).
- b = make::box2d(2 * nrows - 1, 2 * ncols - 1);
- cimpl = image2d<C>(b, 0);
- eimpl = image2d<E>(b, 0);
- ximpl = image2d<X>(b, 0);
-
- // Images.
- cell = cimpl | is_cell;
- edge = eimpl | is_edge;
- vertex = ximpl | is_vertex;
- }
-
- unsigned nrows() const { return (b.nrows() + 1) / 2; }
- unsigned ncols() const { return (b.ncols() + 1) / 2; }
-
- box2d b;
- image2d<C> cimpl;
- image2d<E> eimpl;
- image2d<X> ximpl;
-
- typedef image_if< image2d<C>, is_cell_t > cell_t;
- cell_t cell;
-
- typedef image_if< image2d<E>, is_edge_t > edge_t;
- edge_t edge;
-
- typedef image_if< image2d<X>, is_vertex_t > vertex_t;
- vertex_t vertex;
- };
-
-
-
-
- template <typename T>
- struct cs2d< T, T, T>
- {
- typedef T cell_value;
- typedef T edge_value;
- typedef T vertex_value;
-
- cs2d(unsigned nrows, unsigned ncols)
- {
- init(nrows, ncols);
- }
-
- cs2d(const box2d& b)
- {
- init(b.nrows(), b.ncols());
- }
-
- void init(unsigned nrows, unsigned ncols)
- {
- mln_precondition(nrows && ncols);
-
- // Raw data (impl).
- b = make::box2d(2 * nrows - 1, 2 * ncols - 1);
- impl = image2d<T>(b, 0);
-
- // Images.
- cell = impl | is_cell;
- edge = impl | is_edge;
- vertex = impl | is_vertex;
- }
-
- unsigned nrows() const { return (b.nrows() + 1) / 2; }
- unsigned ncols() const { return (b.ncols() + 1) / 2; }
-
- box2d b;
- image2d<T> impl;
-
- typedef image_if< image2d<T>, is_cell_t > cell_t;
- cell_t cell;
-
- typedef image_if< image2d<T>, is_edge_t > edge_t;
- edge_t edge;
-
- typedef image_if< image2d<T>, is_vertex_t > vertex_t;
- vertex_t vertex;
- };
-
-
-
-
-
- template <typename C, typename T>
- struct cs2d< C, T, T>
- {
- typedef C cell_value;
- typedef T edge_value;
- typedef T vertex_value;
-
- cs2d(unsigned nrows, unsigned ncols)
- {
- init(nrows, ncols);
- }
-
- cs2d(const box2d& b)
- {
- init(b.nrows(), b.ncols());
- }
-
- void init(unsigned nrows, unsigned ncols)
- {
- mln_precondition(nrows && ncols);
-
- // Raw data (impl).
- b = make::box2d(2 * nrows - 1, 2 * ncols - 1);
- cimpl = image2d<C>(b, 0);
- impl = image2d<T>(b, 0);
-
- // Images.
- cell = cimpl | is_cell;
- edge = impl | is_edge;
- vertex = impl | is_vertex;
- }
-
- unsigned nrows() const { return (b.nrows() + 1) / 2; }
- unsigned ncols() const { return (b.ncols() + 1) / 2; }
-
- box2d b;
- image2d<C> cimpl;
- image2d<T> impl;
-
- typedef image_if< image2d<C>, is_cell_t > cell_t;
- cell_t cell;
-
- typedef image_if< image2d<T>, is_edge_t > edge_t;
- edge_t edge;
-
- typedef image_if< image2d<T>, is_vertex_t > vertex_t;
- vertex_t vertex;
- };
-
-
-} // mln
Index: geraud/cs2d/dbl_neighb.hh
--- geraud/cs2d/dbl_neighb.hh (revision 3151)
+++ geraud/cs2d/dbl_neighb.hh (working copy)
@@ -1,167 +0,0 @@
-# include <mln/core/concept/neighborhood.hh>
-
-
-namespace mln
-{
-
-
- // Fwd decl.
- template <typename D, typename F> class dbl_niter_;
-
-
- template <typename D, typename F>
- struct dbl_neighb_ : public Neighborhood< dbl_neighb_<D,F> >
- {
- typedef D dpoint;
- typedef mln_point(D) point;
-
- typedef dbl_niter_<D,F> fwd_niter;
- typedef dbl_niter_<D,F> bkd_niter;
- typedef dbl_niter_<D,F> niter;
-
- dbl_neighb_(F f)
- : f(f)
- {
- }
-
- dbl_neighb_()
- : f()
- {
- }
-
- bool is_empty() const
- {
- return trues.size() == 0 && falses.size() == 0;
- }
-
- dbl_neighb_& insert_true(const D& dp)
- {
- trues.push_back(dp);
- trues.push_back(-dp);
- return *this;
- }
-
- dbl_neighb_& insert_false(const D& dp)
- {
- falses.push_back(dp);
- falses.push_back(-dp);
- return *this;
- }
-
- template <typename N>
- dbl_neighb_& when_true(const Neighborhood<N>& nbh_)
- {
- const N& nbh = exact(nbh_);
- for (unsigned i = 0; i < nbh.size(); ++i)
- trues.push_back(nbh.dp(i));
- return *this;
- }
-
- template <typename N>
- dbl_neighb_& when_false(const Neighborhood<N>& nbh_)
- {
- const N& nbh = exact(nbh_);
- for (unsigned i = 0; i < nbh.size(); ++i)
- falses.push_back(nbh.dp(i));
- return *this;
- }
-
- std::vector<D> trues, falses;
- F f;
- };
-
-
-
- template <typename D, typename F>
- class dbl_niter_
- : public internal::point_iterator_base_< mln_point(D), dbl_niter_<D,F> >
- {
- public:
-
- typedef mln_point(D) point;
-
- template <typename Pref>
- dbl_niter_(const Neighborhood< dbl_neighb_<D,F> >& nbh,
- const Point_Site<Pref>& p_ref) :
- dps_true(exact(nbh).trues),
- dps_false(exact(nbh).falses),
- p_ref_(exact(p_ref).to_point()),
- f(exact(nbh).f)
- {
- invalidate();
- }
-
- /// Conversion to point.
- operator point () const
- {
- mln_precondition(is_valid());
- return p_;
- }
-
- /// Reference to the corresponding point.
- const point& to_point() const
- {
- return p_;
- }
-
- /// Test the iterator validity.
- bool is_valid() const
- {
- return i_ != dps_true.size();
- }
-
- /// Invalidate the iterator.
- void invalidate()
- {
- i_ = dps_true.size();
- }
-
- /// Start an iteration.
- void start()
- {
- i_ = 0;
- update();
- }
-
- /// Go to the next point.
- void next_()
- {
- ++i_;
- update();
- }
-
- /// Give the i-th coordinate.
- int operator[](unsigned i) const
- {
- mln_precondition(is_valid());
- return p_[i];
- }
-
- /// The point around which this iterator moves.
- const point& center_point() const
- {
- return p_ref_;
- }
-
- /// Force this iterator to update its location to take into
- /// account that its center point may have moved.
- void update()
- {
- if (is_valid())
- p_ = p_ref_ + (f(p_ref_) ? dps_true[i_] : dps_false[i_]);
- }
-
- protected:
-
- const std::vector<D>& dps_true, dps_false;
- const point& p_ref_; // reference point (or "center point")
- F f;
-
- unsigned i_;
- point p_; // location of this iterator; p_ makes this iterator be
- // itself a potential center point.
- };
-
-
-
-} // mln
Index: geraud/cs2d/cs2d_morpho.hh
--- geraud/cs2d/cs2d_morpho.hh (revision 3151)
+++ geraud/cs2d/cs2d_morpho.hh (working copy)
@@ -1,372 +0,0 @@
-# include <mln/accu/max.hh>
-# include <mln/accu/min_max.hh>
-# include <mln/labeling/regional_minima.hh>
-
-# include <mln/core/site_set/p_queue_fast.hh>
-
-
-namespace mln
-{
-
- namespace cmorpho
- {
-
- template <typename T>
- T abs_diff(T t1, T t2)
- {
- return t1 > t2 ? t1 - t2 : t2 - t1;
- }
-
- template <typename I>
- void gradient(I& input)
- {
- mln_piter(I) p(input.domain());
- for_all(p)
- {
- mln_psite(I) p_ = p;
- input(p) =
- p_.row() % 2 ?
- // Odd so horizontal edge and vertical cells.
- abs_diff(input(p_ + left), input(p_ + right)) :
- // Otherwise
- abs_diff(input(p_ + up), input(p_ + down));
- }
- }
-
-
- template <typename I, typename N>
- inline
- mln_concrete(I) gradient(const Image<I>& input_,
- const Neighborhood<N>& nbh_)
- {
- const I& input = exact(input_);
- const N& nbh = exact(nbh_);
-
- mln_concrete(I) output;
- initialize(output, input);
-
- accu::min_max<mln_value(I)> m;
-
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- m.init();
- for_all(n) if (input.has(n))
- m.take(input(n));
- output(p) = m.second() - m.first();
- }
- return output;
- }
-
-
- class dbl_niter;
-
- struct dbl_neighb2d : public Neighborhood< dbl_neighb2d >
- {
- typedef dpoint2d dpoint;
- typedef point2d point;
-
- typedef dbl_niter fwd_niter;
- typedef dbl_niter bkd_niter;
- typedef dbl_niter niter;
-
- dbl_neighb2d()
- {
- }
-
- dbl_neighb2d& insert_odd(const dpoint2d& dp)
- {
- odds.push_back(dp);
- odds.push_back(-dp);
- return *this;
- }
- dbl_neighb2d& insert_even(const dpoint2d& dp)
- {
- evens.push_back(dp);
- evens.push_back(-dp);
- return *this;
- }
-
- std::vector<dpoint2d> odds, evens;
- };
-
-
- class dbl_niter
- : public internal::point_iterator_base_< point2d, dbl_niter >
- {
- public:
-
- typedef dpoint2d D;
-
- template <typename N, typename Pref>
- dbl_niter(const N& nbh, const Point_Site<Pref>& p_ref) :
- dps_odd(exact(nbh).odds),
- dps_even(exact(nbh).evens),
- p_ref_(exact(p_ref).to_point())
- {
-
- invalidate();
- }
-
- /// Conversion to point.
- operator point2d () const
- {
- mln_precondition(is_valid());
- return p_;
- }
-
- /// Reference to the corresponding point.
- const point2d& to_point() const
- {
- return p_;
- }
-
- /// Test the iterator validity.
- bool is_valid() const
- {
- return i_ != dps_odd.size();
- }
-
- /// Invalidate the iterator.
- void invalidate()
- {
- i_ = dps_odd.size();
- }
-
- /// Start an iteration.
- void start()
- {
- i_ = 0;
- update();
- }
-
- /// Go to the next point.
- void next_()
- {
- ++i_;
- update();
- }
-
- /// Give the i-th coordinate.
- int operator[](unsigned i) const
- {
- mln_precondition(is_valid());
- return p_[i];
- }
-
- /// The point around which this iterator moves.
- const point2d& center_point() const
- {
- return p_ref_;
- }
-
- /// Force this iterator to update its location to take into
- /// account that its center point may have moved.
- void update()
- {
- if (is_valid())
- p_ = p_ref_ + (p_ref_.row() % 2 ? dps_odd[i_] : dps_even[i_]);
- }
-
- protected:
-
- const std::vector<dpoint2d>& dps_odd, dps_even;
- const point2d& p_ref_; // reference point (or "center point")
-
- unsigned i_;
- point2d p_; // location of this iterator; p_ makes this iterator be
- // itself a potential center point.
- };
-
-
- template <typename L, typename I, typename N>
- mln_ch_value(I, L)
- meyer_wst(const Image<I>& input_, const Neighborhood<N>& nbh_,
- L& nbasins)
- {
- trace::entering("morpho::meyer_wst");
-
- const I& input = exact(input_);
- const N& nbh = exact(nbh_);
-
- /* FIXME: Ensure the input image has scalar values. */
-
- const L unmarked = 0;
-
- // Initialize the output with the markers (minima components).
- mln_ch_value(I, L) output;
- output = labeling::regional_minima(input, nbh, nbasins);
-
- // Ordered queue.
- std::vector< p_queue_fast<mln_psite(I)> > qu(256);
- unsigned qu_size = 0;
-
- // Insert every neighbor P of every marked area in a
- // hierarchical queue, with a priority level corresponding to
- // the grey level input(P).
- {
- mln_piter(I) p(output.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- if (output(p) == unmarked)
- for_all(n)
- if (output.has(n) && output(n) != unmarked)
- {
- qu[input(p)].push_force(p);
- ++qu_size;
- break;
- }
- }
-
- /* Until the queue is empty, extract a psite p from the
- hierarchical queue, at the highest priority level, that is,
- the lowest level. */
- mln_psite(I) p;
- mln_niter(N) n(nbh, p);
-
- while (qu_size != 0)
- {
-
- for (unsigned l = 0; l < 256; ++l)
- if (! qu[l].is_empty())
- {
- p = qu[l].pop_front();
- // qu[l].pop();
- break;
- }
- --qu_size;
-
- // Last seen marker adjacent to P.
- L adjacent_marker = unmarked;
- // Has P a single adjacent marker?
- bool single_adjacent_marker_p = true;
- for_all(n)
- if (output.has(n) && output(n) != unmarked)
- {
- if (adjacent_marker == unmarked)
- {
- adjacent_marker = output(n);
- single_adjacent_marker_p = true;
- }
- else
- if (adjacent_marker != output(n))
- {
- single_adjacent_marker_p = false;
- break;
- }
- }
-
- /* If the neighborhood of P contains only psites with the
- same label, then P is marked with this label, and its
- neighbors that are not yet marked are put into the
- hierarchical queue. */
- if (single_adjacent_marker_p)
- {
- output(p) = adjacent_marker;
- for_all(n)
- if (output.has(n) && output(n) == unmarked)
- {
- qu[input(n)].push_force(n);
- ++qu_size;
- }
- }
- }
-
- trace::exiting("morpho::meyer_wst");
- return output;
- }
-
- } // mln::cmorpho
-
-
- namespace accu
- {
-
- template <typename A_, typename I, typename L>
- inline
- std::vector<mln_accu_with(A_, mln_value(I))::result>
- compute(const Image<I>& input_,
- const Image<L>& label_,
- mln_value(L) n)
- {
- mlc_is_a(A_, Meta_Accumulator)::check();
-
- trace::entering("accu::compute");
-
- const I& input = exact(input_);
- const L& label = exact(label_);
-
- typedef mln_accu_with(A_, mln_value(I)) A;
- std::vector<A> a(n + 1);
-
- mln_piter(I) p(input.domain());
- for_all(p)
- a[label(p)].take(input(p));
-
- typedef typename A::result R;
- std::vector<R> v(n + 1);
- for (unsigned l = 1; l <= n; ++l)
- v[l] = a[l].to_result();
-
- trace::exiting("accu::compute");
- return v;
- }
-
-
- template <typename A_, typename I, typename L, typename R>
- inline
- void
- compute(const Image<I>& input_,
- const Image<L>& label_,
- std::vector<R>& v)
- {
- mlc_is_a(A_, Meta_Accumulator)::check();
-
- trace::entering("accu::compute");
-
- const I& input = exact(input_);
- const L& label = exact(label_);
-
- typedef mln_accu_with(A_, mln_value(I)) A;
- const unsigned n = v.size();
- std::vector<A> a(n);
-
- mln_piter(I) p(input.domain());
- for_all(p)
- a[label(p)].take(input(p));
-
- for (unsigned l = 1; l < n; ++l)
- v[l] = a[l].to_result();
-
- trace::exiting("accu::compute");
- }
-
- } // mln::accu
-
-
- namespace level
- {
-
- template<typename I, typename R>
- mln_ch_value(I, R)
- transform(const Image<I>& input_, const std::vector<R>& v)
- {
- trace::entering("level::transform");
- const I& input = exact(input_);
-
- mln_ch_value(I, R) output;
- initialize(output, input);
-
- mln_piter(I) p(input.domain());
- for_all(p)
- output(p) = v[input(p)];
-
- trace::exiting("level::transform");
- return output;
- }
-
- } // mln::level
-
-
-} // mln
Index: geraud/dead/inplace.hh
--- geraud/dead/inplace.hh (revision 3151)
+++ geraud/dead/inplace.hh (working copy)
@@ -1,66 +0,0 @@
-// Copyright (C) 2007 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_CORE_IMAGE_INPLACE_HH
-# define MLN_CORE_IMAGE_INPLACE_HH
-
-/*! \file mln/core/image/inplace.hh
- *
- * \brief Definition of routine that make temporary objects become
- * mutable.
- */
-
-# include <mln/core/routine/exact.hh>
-
-
-namespace mln
-{
-
- /*! \brief Routine to make temporary objects become mutable.
- *
- * \warning This routine is not safe! FIXME: Explain.
- */
- template <typename E>
- E& inplace(const Object<E>& temp);
-
-
-
-# ifndef MLN_INCLUDE_ONLY
-
- template <typename E>
- inline
- E& inplace(const Object<E>& temp)
- {
- return const_cast<E&>( exact(temp) );
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
-} // end of namespace mln
-
-
-#endif // ! MLN_CORE_IMAGE_INPLACE_HH
Index: geraud/dead/instant.hh
--- geraud/dead/instant.hh (revision 3151)
+++ geraud/dead/instant.hh (working copy)
@@ -1,168 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_CORE_IMAGE_INSTANT_HH
-# define MLN_CORE_IMAGE_INSTANT_HH
-
-/*! \file mln/core/image/instant.hh
- *
- * \brief Definition of a morpher that prevent an image from sharing
- * his data.
- *
- * \todo Fix FIXME; see todo in image_identity...
- */
-
-# include <mln/core/internal/image_identity.hh>
-# include <mln/metal/is_not_const.hh>
-
-
-
-namespace mln
-{
-
- // Forward declaration.
- template <typename I> struct instant_;
-
-
- namespace trait
- {
-
- template <typename I>
- struct image_< instant_<I> > : image_< I > // Same as I except...
- {
- // ...this change.
- typedef trait::image::category::identity_morpher category;
- };
-
- } // end of namespace mln::trait
-
-
-
- namespace internal
- {
-
- /// Data structure for \c mln::instant_<I>.
- template <typename I>
- struct data< instant_<I> >
- {
- data(const I& ima);
- I ima_;
- };
-
- } // end of namespace mln::internal
-
-
-
-
-
- /*! \brief FIXME
- *
- */
- template <typename I>
- struct instant_
-
- : public mln::internal::image_identity< I, mln_pset(I), instant_<I> >,
- private mlc_is_not_const(I)::check_t
- {
-
- /// Skeleton.
- typedef tag::image_<I> skeleton; // Remove the "instant" envelope.
-
- /// Constructor.
- instant_(I& ima);
-
- /// Deferred initialization.
- void init_(I& ima);
-
- /// Remove the "instant" envelope.
- I& un_instant_();
- I& un_instant_() const;
- };
-
-
-
-# ifndef MLN_INCLUDE_ONLY
-
- namespace internal
- {
-
- // internal::data< instant_<I> >
-
- template <typename I>
- inline
- data< instant_<I> >::data(const I& ima)
- : ima_(ima)
- {
- }
-
- } // end of namespace mln::internal
-
-
- // instant_<I>
-
- template <typename I>
- inline
- instant_<I>::instant_(I& ima)
- {
- mln_precondition(ima.is_valid());
- this->init_(ima);
- this->data_ = new internal::data< instant_<I> >(ima);
- }
-
- template <typename I>
- inline
- void
- instant_<I>::init_(I& ima)
- {
- mln_precondition(ima.is_valid());
- this->data_ = new internal::data< instant_<I> >(ima);
- }
-
- template <typename I>
- inline
- I&
- instant_<I>::un_instant_()
- {
- mln_precondition(this->is_valid());
- return this->data_->ima_;
- }
-
- template <typename I>
- inline
- I&
- instant_<I>::un_instant_() const
- {
- mln_precondition(this->is_valid());
- return const_cast<I&>(this->data_->ima_);
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
-} // end of namespace mln
-
-
-#endif // ! MLN_CORE_IMAGE_INSTANT_HH
Index: geraud/fllt/fllt.hh
--- geraud/fllt/fllt.hh (revision 3151)
+++ geraud/fllt/fllt.hh (working copy)
@@ -1,1017 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <iomanip>
-#include <set>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-#include <mln/core/image/sub_image.hh>
-#include <mln/core/site_set/p_queue_fast.hh>
-#include <mln/core/image/cast_image.hh>
-#include <mln/opt/at.hh>
-
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/data/paste.hh>
-#include <mln/level/stretch.hh>
-#include <mln/level/compare.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/labeling/regional_maxima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-#include <mln/pw/all.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/util/tree.hh>
-#include <mln/util/branch_iter_ind.hh>
-#include <mln/util/branch_iter.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
-# define fllt_tree(P, V) mln::util::tree< fllt_node_elt<P, V> >
-# define fllt_node(P, V) mln::util::tree_node< fllt_node_elt<P, V> >
-# define fllt_tree_ptr(P, V) mln::util::tree< fllt_node_elt<P, V>* >
-# define fllt_node_ptr(P, V) mln::util::tree_node< fllt_node_elt<P, V>* >
-# define fllt_branch(P, V) mln::util::branch< fllt_node_elt<P, V> >
-# define fllt_branch_iter_ind(P, V) mln::util::branch_iter_ind< fllt_node_elt<P, V> >
-# define fllt_branch_iter(P, V) mln::util::branch_iter< fllt_node_elt<P, V> >
-
-# define stl_to_mln_iter(T) stl_iterator< T >
-
- //Fwd declarations.
- template <typename V> struct lower;
- template <typename V> struct upper;
-
- template <typename P, typename V>
- struct fllt_node_elt
- {
- V value;
- p_array<P> points;
- p_array<P> holes;
- std::vector<fllt_node(P, V)*> hole_shapes;
- /// Tell if his parent if brighter or not. Nb : if the parent
- /// if brighter, the node come from the lower level set
- bool brighter;
- unsigned nsites;
- bool tagged;
- bool set_id;
- std::vector<p_array<P>*> N;
- fllt_node(P, V)* root;
- unsigned root_version;
- unsigned deja_vu;
-
- fllt_node_elt(bool set_id) : nsites(0),
- tagged(false),
- set_id(set_id),
- root(0) {}
- };
-
-
- template <typename C>
- class stl_iterator
- {
- public:
- stl_iterator(C& c) : container_(c) {}
- void start(){ it_ = container_.begin(); }
- void next() { it_++; }
- bool is_valid() const{ return it_ != container_.end(); }
- typename C::value_type& operator*() { return *it_; }
-
- private:
- C& container_;
- typename C::iterator it_;
- };
-
- template <typename N_t, typename G, typename Set>
- void update_gN(const N_t& N, G& gN);
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, lower<V>)
- {
- // gN is the min.
- for (unsigned g = 0; g < 256; ++g)
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, upper<V>)
- {
- // gN is the max.
- for (int g = 255; g >= 0; --g)
- {
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- }
- // if N is empty, gN is the min value.
- gN = 0;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 257; ++i)
- {
- if (N[i]->nsites() == 0)
- continue;
- std::cout << i << ": " << *N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 257; ++i)
- N[i]->clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- opt::at(output, row, col) = opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- void save_u(const image2d<value::int_u8>& u,
- const image2d<int>& is,
- box2d R_box,
- int in_R,
- int in_N)
- {
- static int id = 0;
- std::stringstream filename, is_filename;
- filename << "fllt_trace_" << std::setw(5) << std::setfill('0')
- << std::right << id++ << ".ppm";
- is_filename << "is_" << std::setw(5) << std::setfill('0')
- << std::right << id << ".pgm";
-
- //std::cout << " Save in " << filename.str() << std::endl;
- image2d<value::int_u8> out(is.domain());// = duplicate(cast_image<value::int_u8>(is));
- data::fill(out, 0);
- mln_assertion(R_box.nsites() > 0);
- mln_piter_(box2d) p(R_box);
- for_all(p)
- if (is(p) == in_R)
- out(p) = 255;
- else if (is(p) == in_N)
- out(p) = 127;
- // else if (is(p) == in_N)
- // out(p) = literal::green;
-
- io::pgm::save(out, filename.str());
-
- //save is
- image2d<value::int_u8> is_out(is.domain());
- level::stretch(cast_image<value::int_u8>(is), is_out);
- io::pgm::save(is_out, is_filename.str());
- //io::pgm::save(out, filename.str());
- }
-
- template <typename I>
- void save(const I& is, unsigned in_N, unsigned in_R, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- if (is(p) == in_R)
- temp(p) = literal::red;
- else if (is(p) == in_N) // N
- temp(p) = literal::green;
- else if (is(p) < in_N)
- temp(p) = literal::blue;
- else
- temp(p) = literal::white;
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
- template <typename I, typename P, typename V, typename Set>
- void blob(const Set&,
- const I& is,
- p_array<mln_point(I)>* N[257],
- unsigned in_N,
- const box2d& N_box,
- fllt_node(P, V)* current_cc)
- {
- typedef p_array<mln_point(I)> arr_t;
-
- // std::cout << ">>>>>>>enter blob. " << current_cc << std::endl;
- bool flower = true;
- unsigned ncc = 0;
- static image2d<unsigned> is_labeled(is.domain());
- static unsigned label = 0;
-
- if (label == 0)
- {
- data::fill(is_labeled, 0);
- label++;
- }
-
- P cur;
- mln_niter(neighb2d) n(Set::bdr_nbh(), cur);
- p_queue_fast<P> qu;
- p_array<P>& holes = current_cc->elt().holes;
-
- mln_piter(I) p(N_box);
- for_all(p)
- if (is(p) == in_N)
- break;
-
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
-
-
-
- for (unsigned i = 0; i < 256; ++i)
- //for (int i = 255; i >= 0; --i)
- {
- mln_piter(arr_t) p(*N[i]);
- for_all(p)
- {
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
- }
- }
-
- ++label;
-
- // if (holes.size() == 2)
- // std::cout << holes[0] << holes[1] << std::endl;
- // std::cout << " <<<<<<<exiting blob." << std::endl;
- }
-
- template <typename P, typename V>
- fllt_node(P, V)* find_root(fllt_node(P, V)* shape, unsigned in_R)
- {
- if (shape->elt().root_version == in_R)
- return shape->elt().root;
-
- fllt_node(P, V)* root = shape;
-
- shape->elt().root_version = in_R;
-
- while(root->parent())
- {
- mln_assertion(root->parent() != root);
- root = root->parent();
- mln_assertion(root);
- }
-
- shape->elt().root = root;
- return root;
- }
-
- template <typename P, typename V>
- fllt_node(P, V)* find_root(fllt_node(P, V)* shape)
- {
- fllt_node(P, V)* root = shape;
-
- while(root->parent())
- {
- mln_assertion(root->parent() != root);
- root = root->parent();
- mln_assertion(root);
- }
-
-// shape->elt().root = root;
- return root;
- }
-
- template <typename I, typename P, typename V, typename Set>
- void
- move_A_to_R(const Set&,
- p_array<P>& A,
- image2d<int>& deja_vu,
- const I& u,
- fllt_node(P, V)* current_cc,
- image2d< fllt_node(P, V)* >& smallest_shapes,
- int in_R,
- int in_N,
- accu::bbox<P>& N_box,
- p_array<P>* N[257],
- const V& g,
- unsigned& n_comps)
- {
- typedef p_array<P> arr_t;
-
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
- std::set<fllt_node(P, V)*> to_merge;
-
- // Add points of A to R.
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- if (smallest_shapes(a) && find_root(smallest_shapes(a)) == current_cc)
- continue;
- mln_invariant(deja_vu(a) == in_N);
- // mln_invariant(u(a) == g);
- mln_invariant(smallest_shapes(a) != current_cc);
-
- if (!smallest_shapes(a))
- {
- smallest_shapes(a) = current_cc;
- mln_assertion(!current_cc->elt().points.has(a));
- current_cc->elt().points.append(a);
- }
- else
- {
- mln_assertion(smallest_shapes(a)->elt().value == g ||
- Set::compare(smallest_shapes(a)->elt().value, g));
-
- to_merge.insert(smallest_shapes(a));
-
- smallest_shapes(a) = current_cc;
- mln_assertion(!current_cc->elt().points.has(a));
- current_cc->elt().points.append(a);
- }
- }
-
- // Add alreardy computed coponents to R, and also their neighborhood to N.
- typename std::set<fllt_node(P, V)*>::iterator shape_;
- for (shape_ = to_merge.begin();
- shape_ != to_merge.end();
- shape_++)
- {
- fllt_node(P, V)* to_delete = find_root(*shape_);
-
- if (to_delete == current_cc)
- continue;
-
- // Add the neighborhood of to_delete to the current one.
- //std::cout << "Merge into " << current_cc << " to_delete :" << to_delete << std::endl;
- // std::cout << to_delete->elt().N.size() << " " << to_delete << std::endl;
- mln_assertion(to_delete->elt().N.size() == 257);
- for (unsigned i = 0; i < 257; ++i)
- {
- if (!to_delete->elt().N[i])
- continue;
- mln_piter(p_array<P>) p(*to_delete->elt().N[i]);
- for_all(p)
- {
- if (deja_vu(p) != in_N &&
- (!smallest_shapes(p) || find_root(smallest_shapes(p)) != current_cc))
- {
- mln_assertion(! N[i]->has(p));
- N[i]->append(p);
- deja_vu(p) = in_N;
- N_box.take(p);
- }
- }
- delete to_delete->elt().N[i];
- }
- to_delete->elt().N.clear();
-
- // the shape containing a cannot have a parent in this case.
- mln_assertion(!to_delete->parent());
- // Add points of to_delete to current_cc.
-// if (to_delete->elt().value == g)
-// {
-// mln_piter(arr_t) p(to_delete->elt().points);
-// for_all(p)
-// {
-// if (smallest_shapes(p) != current_cc)
-// {
-// mln_assertion(!current_cc->elt().points.has(p));
-// current_cc->elt().points.append(p);
-// smallest_shapes(p) = current_cc;
-// }
-// mln_postcondition(smallest_shapes(p) == current_cc);
-// }
-// }
-
-// if (to_delete->elt().value == g)
-// {
-// while(!to_delete->children().empty())
-// {
- // mln_assertion(!(*to_delete->children().begin())->elt().root ||
-// (*to_delete->children().begin())->elt().root == to_delete);
-// (*to_delete->children().begin())->elt().root = current_cc;
-// current_cc->add_child(*(to_delete->children().begin()));
-
-// }
-// delete to_delete;
-// n_comps--;
-// }
-// else
-// {
- mln_assertion(Set::compare(to_delete->elt().value, g));
- to_delete->set_parent(current_cc);
- to_delete->elt().root = current_cc;
-// }
- }
- }
-
- // LOWER LEVEL SET : region = c4, border = c8
- template <typename V>
- struct lower
- {
- typedef upper<V> opposite;
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- {
- return u < v;
- }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- {
- return labeling::regional_minima(input, nbh, nlabels);
- }
-
- static const bool parent_is_brighter = true;
- static const bool id = false;
- static const V e() { return mln_max(V); }
-
-
- static const neighb2d& bdr_nbh() { return c8(); }
- static const neighb2d& reg_nbh() { return c4(); }
- };
-
-
- // UPPER LEVEL SET : region = c8, border = c4
- template <typename V>
- struct upper
- {
- typedef lower<V> opposite;
-
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- { return u > v; }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- { return labeling::regional_maxima(input, nbh, nlabels); }
-
- static const bool parent_is_brighter = false;
- static const bool id = true;
- static const V e() { return mln_min(V); }
-
- static const neighb2d& bdr_nbh() { return c4(); }
- static const neighb2d& reg_nbh() { return c8(); }
- };
-
- template <typename I, typename Set>
- fllt_tree(mln_point(I), mln_value(I))&
- level_set(const Image<I>& input_,
- image2d< fllt_node(mln_point(I), mln_value(I))* >& smallest_shapes)
- {
-
- typedef mln_point(I) P;
- typedef mln_value(I) V;
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
-
- const I& input = exact(input_);
-
- mln_assertion(input.domain() == smallest_shapes.domain());
-
- unsigned l = 0, l_max = 0;
- mln_ch_value(I, unsigned) reg_min = Set::regional_extremum(input, Set::reg_nbh(), l_max);
- std::vector<bool> tag(l_max + 1, false);
- tag[0] = true;
-
- // Variables.
- P x0;
- V g, gN;
- mln_fwd_piter(I) p(input.domain());
- p.start();
- data::fill(smallest_shapes, 0);
- node_type* current_cc;
-
- unsigned in_N = 1, in_R = 2;
-
- image2d<int> deja_vu(input.domain().to_larger(1));
- data::fill(deja_vu, 0);
-
- typedef p_array<P> arr_t;
- arr_t* A = new arr_t();
- arr_t* N[257];
- for (unsigned i = 0; i < 257; ++i)
- N[i] = new arr_t();
- accu::bbox<P> N_box;
-
- unsigned n_step_1 = 0, n_step_3 = 0, n_step_4c = 0, sum4c = 0,
- n_comps = 0, n_holes = 0, n_browsed = 0, n_find_root = 0,
- n_neighb = 0, n_pass = 0;
-
- // Step 1.
- step_1:
- {
- // std::cout << " step 1" << std::endl;
- while (tag[reg_min(p)] && p.is_valid())
- p.next();
- if (p.is_valid())
- tag[reg_min(p)] = true; // To be processed.
- else
- goto the_end;
-
- ++n_step_1;
- x0 = p;
- g = input(x0);
- ++n_comps;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
-
- // std::cout << " new cc " << current_cc
- // << " value " << g << " point " << p << std::endl;
-
- }
-
- // Step 2.
- step_2:
- {
- in_N += 2;
- in_R = in_N + 1;
- // R <- 0 and N <- 0
- clear_N(N);
- N_box.init();
-
- // A <- { x0 }
- A->clear();
- A->append(x0);
- N_box.take(x0);
-
-// deja_vu(x0) = in_R;
- smallest_shapes(x0) = current_cc;
- current_cc->elt().points.append(x0);
- current_cc->elt().nsites++;
-
- }
-
- // Step 3.
- step_3:
- {
- //std::cout << " step 3" << std::endl;
-// save_u(input, deja_vu, N_box, in_R, in_N);
- ++n_step_3;
-
- mln_piter(arr_t) a(*A);
- mln_niter(neighb2d) x(Set::reg_nbh(), a);
-
-
- // R <- R U A
- if (A->nsites() == 0)
- goto the_end;
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- {
- n_browsed++;
- for_all(x)
- {
- if (deja_vu.has(x) && deja_vu(x) < in_N && smallest_shapes(x) != current_cc)
- {
- //std::cout << x << std::endl;
- if (input.has(x))
- {
- n_neighb++;
- short vx;
- if (smallest_shapes(x))
- {
- n_find_root++;
- if (smallest_shapes(x)->elt().deja_vu == in_R)
- continue;
-
- smallest_shapes(x)->elt().deja_vu = in_R;
- fllt_node(P,V)* r = find_root(smallest_shapes(x), in_R);
- if (r == current_cc)
- {
- n_pass++;
- continue;
- }
- vx = r->elt().value;
- }
- else
- vx = input(x);
- mln_assertion(! N[vx]->has(x));
- N[vx]->append(x);
- }
- else
- {
- mln_assertion(!smallest_shapes(x));
- mln_assertion(! N[256]->has(x));
- N[256]->append(x);
- }
- N_box.take(x);
- deja_vu(x) = in_N;
- }
- }
- }
- // gN = min u(x) for all x in N
- update_gN(N, gN, Set());
- //save_u(u, deja_vu, N_box, in_R, in_N);
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (Set::compare(g, gN))
- {
- // std::cout << " step 4a" << std::endl;
- g = gN;
-
- ++n_comps;
-
- //save_u(u, deja_vu, N_box, in_R, in_N);
- blob(Set(), deja_vu, N, in_N, N_box, current_cc);
-
- n_holes += current_cc->elt().holes.nsites();
-
- node_type* child = current_cc;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- child->set_parent(current_cc);
- child->elt().root = current_cc;
- // std::cout << " new cc " << current_cc
- // << " value " << g << std::endl;
-
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(Set(), *A, deja_vu, input, current_cc, smallest_shapes, in_R, in_N, N_box, N, g, n_comps);
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- //std::cout << " step 4b" << std::endl;
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(Set(), *A, deja_vu, input, current_cc, smallest_shapes, in_R, in_N, N_box, N, g, n_comps);
- goto step_3;
- }
- // c)
- else
- {
- //std::cout << " step 4c " << current_cc << std::endl;
- n_step_4c++;
-
- current_cc->elt().N.resize(257);
- for (unsigned i = 0; i < 257; ++i)
- {
- if (N[i]->nsites() > 0)
- {
- current_cc->elt().N[i] = N[i];
- N[i] = new arr_t();
- }
- else
- current_cc->elt().N[i] = 0;
- }
- goto step_1;
- }
- }
-
- the_end:
- std::cout << " n_step1=" << n_step_1 << " n_step3=" << n_step_3
- << " n_browsed=" << n_browsed
- << " n_browsed/nsites=" << n_browsed / input.domain().nsites()
- << " n_find_root=" << n_find_root
- << " n_neighb=" << n_neighb
- << " n_pass=" << n_pass
- << std::endl;
- std::cout << "n comps = " << n_comps << " n holes = " << n_holes << std::endl;
-
- return *new tree_type(current_cc);
- }
-
- template <typename P>
- void swap_p_arrays(p_array<P>*& a, p_array<P>*& b)
- {
- p_array<P>* tmp = a;
- a = b;
- b = tmp;
- }
-
- // F is the set in which we get the node.
- template <typename P, typename V, typename F>
- fllt_node(P, V)*
- find_hole(fllt_node(P, V)& node,
- const P p,
- const image2d<fllt_node(P, V)*>& other_reg)
- {
- fllt_node(P, V)* s = other_reg(p);
- mln_assertion(s);
- while (s->parent() && F::compare(s->parent()->elt().value, node.elt().value))
- {
- mln_assertion(s);
- s = s->parent();
- mln_assertion(s);
- }
- // std::cout << " [Find the hole] of " << p
- // << " from " << &node
- // << " return " << s
- // << std::endl;
- return s;
- }
-
- template <typename P, typename V>
- bool shape_is_included(fllt_node(P, V)* A,
- fllt_node(P, V)* B)
- {
- return A->parent() == B || A == B;
- }
-
- template <typename P, typename V>
- void find_all_holes(fllt_tree(P, V)& lower_tree,
- fllt_tree(P, V)& upper_tree,
- const image2d<fllt_node(P, V)*>& low_reg,
- const image2d<fllt_node(P, V)*>& upp_reg)
- {
- typedef p_array<P> arr_t;
- typedef fllt_node(P, V) node_type;
-
- {
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,upper<V> >(node, P(hole), upp_reg));
- }
- }
-
- {
- fllt_branch_iter_ind(P, V) node_(upper_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,lower<V> >(node, P(hole), low_reg));
- }
- }
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- merge_trees(fllt_tree(mln_point(I), mln_value(I))& lower_tree,
- fllt_tree(mln_point(I), mln_value(I))& upper_tree,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& low_reg,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& upp_reg,
- const Image<I>& input_)
- {
-
- const I& input = exact(input_);
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
- typedef p_array<P> arr_t;
-
-
- find_all_holes(lower_tree, upper_tree, low_reg, upp_reg);
- std::vector<node_type*> to_fill;
-
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != lower<V>::id)
- continue;
-
- // std::cout << "Fill " << &node << std::endl;
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- // std::cout << "hole : " << hole << " " << hole->elt().points << " " << std::endl;
- // std::cout << "child hole : " << child_hole << " " << child_hole->elt().points << std::endl;
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
- if (!child_has_bigger_hole)
- {
- // // std::cout << "move " << hole << " as child of " << &node << std::endl;
- node.add_child(hole);
- to_fill.push_back(hole);
- }
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- for(typename std::vector<node_type*>::iterator node_ = to_fill.begin();
- node_ != to_fill.end();
- node_++)
- {
- node_type& node = **node_;
-
- fllt_branch_iter_ind(P, V) node_(fllt_branch(P, V)(upper_tree, node));
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != upper<V>::id)
- continue;
-
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
-
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- //if (hole->elt().points <= child_hole->elt().points)
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
-
- if (!child_has_bigger_hole)
- node.add_child(hole);
-
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- }
-
- return lower_tree;
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- fllt(const Image<I>& input_)
- {
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- const I& input = exact(input_);
-
- fllt_tree(P, V) upper_tree;
- fllt_tree(P, V) lower_tree;
- image2d<fllt_node(P, V)*> low_reg(input.domain());
- image2d<fllt_node(P, V)*> upp_reg(input.domain());
-
- std::cout << "1/ Compute the lower level set.----------------------------------------" << std::endl;
- lower_tree = level_set<I, lower<V> >(input, low_reg);
-
- std::cout << "2/ Compute the upper level set.----------------------------------------" << std::endl;
- upper_tree = level_set<I, upper<V> >(input, upp_reg);
-
- std::cout << "3/ Merge.---------------------------------------------------------------" << std::endl;
- fllt_tree(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, input);
-
- return result_tree;
- }
-
-} // end of namespace mln
Index: geraud/fllt/simple_tests.cc
--- geraud/fllt/simple_tests.cc (revision 3151)
+++ geraud/fllt/simple_tests.cc (working copy)
@@ -1,84 +0,0 @@
-#include "fllt_test.hh"
-
-namespace mln
-{
- template <typename P, typename V>
- void
- draw_tree(const image2d<V>& ima,
- fllt_tree(P, V)& tree)
- {
- p_array<P> tmp;
-
- fllt_branch_iter_ind(P, V) p(tree.main_branch());
- for_all(p)
- {
- std::cout << "region mere : " << (*p).parent() << std::endl;
- std::cout << " ^" << std::endl;
- std::cout << " |" << std::endl;
- std::cout << "region : " << &*p
- << " value = " << (*p).elt().value << std::endl
- << " from " << ((*p).elt().set_id == lower<V>::id ?
- "lower" : "upper") << " level set."
- << std::endl
- << " nsites = " << (*p).elt().nsites << std::endl
- << " holes = " << (*p).elt().holes << std::endl;
-
- std::cout << std::endl;
-
- tmp.append((*p).elt().points);
-
- fllt_branch_iter_ind(P, V) n(fllt_branch(P, V)(tree, *p));
- for_all(n)
- tmp.append((*n).elt().points);
-
- if ((*p).elt().points.nsites() > 0)
- debug::println(ima | tmp);
- tmp.clear();
-
- std::cout << std::endl;
- }
- }
-
-} // End of namespace mln.
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- typedef fllt_tree(point2d, int_u8) tree_type;
-
-// int vs[8][9] = { {2,2,2,2,2,2,2,2,2},
-// {2,2,2,2,2,2,2,2,2},
-// {2,1,1,1,1,1,1,1,2},
-// {2,1,2,2,1,0,0,1,2},
-// {2,1,2,2,1,0,4,1,2},
-// {2,1,2,2,1,0,0,1,2},
-// {2,1,1,1,1,1,1,1,2},
-// {2,2,2,2,2,2,2,2,2} };
-
-
-// int vs[3][4] = { {1,8,2,4},
-// {5,6,3,8},
-// {9,14,0,12} };
-
- int vs[3][4] = { {1,1,2,1},
- {1,1,2,2},
- {1,1,2,1} };
-
-// int vs[8][9] = { {0,0,0,0,0,0,0,0,0},
-// {0,0,0,0,0,0,0,0,0},
-// {0,1,1,1,1,1,1,1,0},
-// {0,1,0,0,1,5,5,1,1},
-// {0,1,0,0,1,5,5,1,0},
-// {0,1,0,0,1,5,5,1,0},
-// {0,1,1,1,1,1,1,1,0},
-// {0,0,0,0,0,0,0,0,0} };
-
- image2d<int> lena_(make::image2d(vs));
- image2d<int_u8> lena(lena_.domain());
- data::fill(lena, lena_);
-
- tree_type tree = fllt(lena);
- draw_tree(lena, tree);
-}
Index: geraud/fllt/compute_fllt.cc
--- geraud/fllt/compute_fllt.cc (revision 3151)
+++ geraud/fllt/compute_fllt.cc (working copy)
@@ -1,19 +0,0 @@
-#include "fllt.hh"
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- typedef fllt_tree(point2d, int_u8) tree_type;
-
- if (argc != 2)
- {
- std::cerr << "usage: " << argv[0] << " filename" << std::endl;
- return 1;
- }
-
- image2d<int_u8> lena;
- io::pgm::load(lena, argv[1]);
- tree_type tree = fllt(lena);
-}
Index: geraud/fllt/fllt.svg.1.cc
--- geraud/fllt/fllt.svg.1.cc (revision 3151)
+++ geraud/fllt/fllt.svg.1.cc (working copy)
@@ -1,222 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-
-#include <mln/value/int_u8.hh>
-# include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/accu/bbox.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
- namespace my
- {
-
- template <typename N_t>
- unsigned compute_gN(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- if (N[i].nsites() != 0)
- return i;
- mln_invariant(0);
- return 0;
- }
-
-
- template <typename I, typename A_t>
- void save(const I& is, const A_t& A)
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- switch (is(p)) {
- case 1: // R
- temp(p) = literal::red;
- break;
- case 2: // N
- temp(p) = literal::green;
- break;
- }
-
- mln_piter(A_t) a(A);
- for_all(a) // A
- temp(a) = literal::blue;
-
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(temp, filename.str());
- }
-
-
- template <typename I, typename Nbh>
- void fllt(const Image<I>& input_, const Neighborhood<Nbh>& nbh_)
- {
- const I& input = exact(input_);
- const Nbh& nbh = exact(nbh_);
-
- unsigned l = 0, l_max;
- mln_ch_value(I, unsigned) reg_min = labeling::regional_minima(input, nbh, l_max);
-
- // Variables.
- I u = mln::duplicate(input);
- mln_point(I) x0;
- mln_value(I) g, gN;
- image2d<unsigned char> is(input.domain());
- const unsigned in_R = 1, in_N = 2, in_O = 0;
-
- typedef p_array<mln_point(I)> arr_t;
- arr_t A;
- arr_t N[256];
-
- accu::bbox<mln_point(I)> R_box;
-
-
- // Step 1.
- step_1:
- {
- if (l == l_max)
- return;
- l += 1;
- mln_piter(I) p(input.domain());
- for_all(p)
- if (reg_min(p) == l)
- break;
- x0 = p;
- g = input(x0);
- }
-
- // Step 2.
- step_2:
- {
- R_box.init();
- data::fill(is, in_O);
- A.append(x0);
- }
-
- // Step 3.
- step_3:
- {
- mln_piter(arr_t) a(A);
- mln_niter(Nbh) x(nbh, a);
-
- my::save(is, A);
-
- // R <- R U A
- for_all(a)
- is(a) = in_R;
- R_box.take(A.bbox());
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- if (u.has(x) && is(x) == in_O)
- {
- N[u(x)].append(x);
- is(x) = in_N;
- }
- // gN = min u(x) for all x in N
- gN = compute_gN(N);
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (g < gN)
- {
- // FIXME: DO the hole thing.
- A = N[g];
- N[g].clear();
- g = gN;
- gN = compute_gN(N);
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- A = N[g];
- N[g].clear();
- g = gN;
- gN = compute_gN(N);
- goto step_3;
- }
- // c)
- else
- {
- mln_piter(box_<mln_point(I)>) p(R_box);
- for_all(p)
- if (is(p) == in_R)
- u(p) = g;
- goto step_1;
- }
- }
-
- }
-
- } // end of namespace mln::my
-
-} // end of namespace mln
-
-
-int main()
-{
- using namespace mln;
- using value::int_u8;
-
- image2d<int_u8> lena;
- io::pgm::load(lena, "../../img/tiny.pgm");
-
- my::fllt(lena, c4());
- io::pgm::save(lena, "./out.pgm");
-
-}
Index: geraud/fllt/fllt.svg.7.hh
--- geraud/fllt/fllt.svg.7.hh (revision 3151)
+++ geraud/fllt/fllt.svg.7.hh (working copy)
@@ -1,913 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_FLLT_HH
-# define MLN_FLLT_HH
-
-#include <iomanip>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-#include <mln/core/image/sub_image.hh>
-#include <mln/core/site_set/p_queue_fast.hh>
-#include <mln/core/image/cast_image.hh>
-
-#include <mln/opt/at.hh>
-
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/level/compare.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/labeling/regional_maxima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-#include <mln/pw/all.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/util/tree.hh>
-#include <mln/util/branch_iter_ind.hh>
-#include <mln/util/branch_iter.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
-# define fllt_tree(P, V) mln::util::tree< fllt_node_elt<P, V> >
-# define fllt_node(P, V) mln::util::tree_node< fllt_node_elt<P, V> >
-# define fllt_tree_ptr(P, V) mln::util::tree< fllt_node_elt<P, V>* >
-# define fllt_node_ptr(P, V) mln::util::tree_node< fllt_node_elt<P, V>* >
-# define fllt_branch(P, V) mln::util::branch< fllt_node_elt<P, V> >
-# define fllt_branch_iter_ind(P, V) mln::util::branch_iter_ind< fllt_node_elt<P, V> >
-# define fllt_branch_iter(P, V) mln::util::branch_iter< fllt_node_elt<P, V> >
-
-# define stl_to_mln_iter(T) stl_iterator< T >
-
- //Fwd declarations.
- template <typename V> struct lower;
- template <typename V> struct upper;
-
- template <typename P, typename V>
- struct fllt_node_elt
- {
- V value;
- p_array<P> points;
- p_array<P> holes;
- std::vector<fllt_node(P, V)*> hole_shapes;
- /// Tell if his parent if brighter or not. Nb : if the parent
- /// if brighter, the node come from the lower level set
- bool brighter;
- unsigned nsites;
- bool tagged;
- bool set_id;
-
- fllt_node_elt(bool set_id) : nsites(0), tagged(false), set_id(set_id) {}
- };
-
-
- template <typename C>
- class stl_iterator
- {
- public:
- stl_iterator(C& c) : container_(c) {}
- void start(){ it_ = container_.begin(); }
- void next() { it_++; }
- bool is_valid() const{ return it_ != container_.end(); }
- typename C::value_type& operator*() { return *it_; }
-
- private:
- C& container_;
- typename C::iterator it_;
- };
-
- template <typename N_t, typename G, typename Set>
- void update_gN(const N_t& N, G& gN);
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, lower<V>)
- {
- for (unsigned g = 0; g < 256; ++g)
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, upper<V>)
- {
- for (int g = 255; g >= 0; --g)
- {
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- }
- // if N is empty, gN is the min value.
- gN = 0;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- {
- if (N[i]->nsites() == 0)
- continue;
- std::cout << i << ": " << *N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- N[i]->clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- opt::at(output, row, col) = opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- void save_u(const image2d<value::int_u8>& u,
- const image2d<int>& is,
- box2d R_box,
- int in_R,
- int in_N)
- {
- static int id = 0;
- std::stringstream filename;
- filename << "fllt_trace_" << std::setw(5) << std::setfill('0')
- << std::right << id++ << ".ppm";
-
- image2d<value::int_u8> out = duplicate(cast_image<value::int_u8>(is));
-
- mln_assertion(R_box.nsites() > 0);
- mln_piter_(box2d) p(R_box);
- for_all(p)
- if (is(p) == in_R)
- out(p) = 255;
- else if (is(p) == in_N)
- out(p) = 127;
- // else if (is(p) == in_N)
- // out(p) = literal::green;
-
- io::pgm::save(out, filename.str());
- //io::pgm::save(out, filename.str());
- }
-
- template <typename I>
- void save(const I& is, unsigned in_N, unsigned in_R, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- if (is(p) == in_R)
- temp(p) = literal::red;
- else if (is(p) == in_N) // N
- temp(p) = literal::green;
- else if (is(p) < in_N)
- temp(p) = literal::blue;
- else
- temp(p) = literal::white;
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
- template <typename I, typename P, typename V, typename Set>
- void blob(const Set&,
- const I& is,
- p_array<mln_point(I)>* N[256],
- unsigned in_N,
- const box2d& N_box,
- fllt_node(P, V)* current_cc)
- {
- typedef p_array<mln_point(I)> arr_t;
-
- // std::cout << ">>>>>>>enter blob. " << current_cc << std::endl;
- bool flower = true;
- unsigned ncc = 0;
- static image2d<unsigned> is_labeled(is.domain());
- static unsigned label = 0;
-
- if (label == 0)
- {
- data::fill(is_labeled, 0);
- label++;
- }
-
- P cur;
- mln_niter(neighb2d) n(Set::bdr_nbh(), cur);
- p_queue_fast<P> qu;
- p_array<P>& holes = current_cc->elt().holes;
-
- mln_piter(I) p(N_box);
- for_all(p)
- if (is(p) == in_N)
- break;
-
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
-
-
-
- for (unsigned i = 0; i < 256; ++i)
- //for (int i = 255; i >= 0; --i)
- {
- mln_piter(arr_t) p(*N[i]);
- for_all(p)
- {
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
- }
- }
-
- ++label;
-
- }
-
- template <typename P, typename V>
- void
- move_A_to_R(p_array<P>& A,
- image2d<int>& deja_vu,
- fllt_node(P, V)* current_cc,
- image2d< fllt_node(P, V)* >& smallest_shapes,
- int in_R,
- int in_N,
- const V& g,
- unsigned& n_comps)
- {
- typedef p_array<P> arr_t;
-
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- mln_invariant(deja_vu(a) == in_N);
- mln_invariant(smallest_shapes(a) != current_cc);
- // if (smallest_shapes(a) == current_cc)
- // continue;
-
- deja_vu(a) = in_R;
- if (!smallest_shapes(a))
- {
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- if (!smallest_shapes(a)->parent())
- if (smallest_shapes(a)->elt().value == g)
- {
- fllt_node(P, V)* to_delete = smallest_shapes(a);
-
- // current_cc->elt().points.append(smallest_shapes(a)->elt().points);
- // A.append(smallest_shapes(a)->elt().points);
-
- mln_piter(arr_t) p(smallest_shapes(a)->elt().points);
- // Todo optimization here.
- for_all(p)
- {
- smallest_shapes(p) = 0;
- // deja_vu(p) = in_R;
- //smallest_shapes(p) = current_cc;
- }
-
- while(!to_delete->children().empty())
- current_cc->add_child(*to_delete->children().begin());
- delete to_delete;
- n_comps--;
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- smallest_shapes(a)->set_parent(current_cc);
- }
- }
-
- // LOWER LEVEL SET information to compute the max tree.
- // -> region = c4, border = c8
- template <typename V>
- struct lower
- {
- typedef upper<V> opposite;
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- {
- return u < v;
- }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- {
- return labeling::regional_minima(input, nbh, nlabels);
- }
-
- static const bool parent_is_brighter = true;
- static const bool id = false;
-
- static const neighb2d& bdr_nbh() { return c8(); }
- static const neighb2d& reg_nbh() { return c4(); }
- };
-
-
- // UPPER LEVEL SET information to compute the max tree.
- // -> region = c8, border = c4
- template <typename V>
- struct upper
- {
- typedef lower<V> opposite;
-
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- { return u > v; }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- { return labeling::regional_maxima(input, nbh, nlabels); }
-
- static const bool parent_is_brighter = false;
- static const bool id = true;
-
- static const neighb2d& bdr_nbh() { return c4(); }
- static const neighb2d& reg_nbh() { return c8(); }
- };
-
- /*! Fast computation of a min/max tree.
- *
- * \param[in] input_ An input image.
- * \param[out] smallest_shapes We stock in this image, for each point, a pointer
- * to the smallest shape containing it.
- * \return The min/max tree built.
- *
- */
- template <typename I, typename Set>
- fllt_tree(mln_point(I), mln_value(I))&
- level_set(const Image<I>& input_,
- image2d< fllt_node(mln_point(I), mln_value(I))* >& smallest_shapes)
- {
-
- typedef mln_point(I) P;
- typedef mln_value(I) V;
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
-
- const I& input = exact(input_);
-
- mln_assertion(input.domain() == smallest_shapes.domain());
-
- unsigned l = 0, l_max = 0;
- mln_ch_value(I, unsigned) reg_min = Set::regional_extremum(input, Set::reg_nbh(), l_max);
- std::vector<bool> tag(l_max + 1, false);
- tag[0] = true;
-
- // Variables.
- I u = mln::duplicate(input);
- P x0;
- V g, gN;
- mln_fwd_piter(I) p(input.domain());
- p.start();
- data::fill(smallest_shapes, 0);
- node_type* current_cc;
-
- unsigned in_N = 1, in_R = 2;
-
- image2d<int> deja_vu(input.domain().to_larger(1));
- data::fill(deja_vu, 0);
-
- typedef p_array<P> arr_t;
- arr_t* A = new arr_t();
- arr_t* N[256];
- for (unsigned i = 0; i < 256; ++i)
- N[i] = new arr_t();
- accu::bbox<P> N_box;
-
- bool touch_border_of_image = false;
- unsigned n_step_1 = 0, n_step_3 = 0, n_step_4c = 0, n_comps = 0, n_holes = 0;
-
- // Step 1.
- step_1:
- {
- while (tag[reg_min(p)] && p.is_valid())
- p.next();
- if (p.is_valid())
- tag[reg_min(p)] = true; // To be processed.
- else
- goto the_end;
-
- ++n_step_1;
- x0 = p;
- g = input(x0);
- ++n_comps;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- touch_border_of_image = false;
-
- }
-
- // Step 2.
- step_2:
- {
- in_N += 2;
- in_R = in_N + 1;
- // R <- 0 and N <- 0
- clear_N(N);
- N_box.init();
-
- // A <- { x0 }
- A->clear();
- A->append(x0);
- N_box.take(x0);
-
- deja_vu(x0) = in_R;
- smallest_shapes(x0) = current_cc;
- current_cc->elt().points.append(x0);
- current_cc->elt().nsites++;
-
- }
-
- // Step 3.
- step_3:
- {
- // save_u(u, deja_vu, N_box, in_R, in_N);
- ++n_step_3;
-
- mln_piter(arr_t) a(*A);
- mln_niter(neighb2d) x(Set::reg_nbh(), a);
-
-
- // R <- R U A
- if (A->nsites() == 0)
- goto the_end;
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- {
- if (deja_vu.has(x) && deja_vu(x) < in_N)
- {
- if (u.has(x))
- {
- N[u(x)]->append(x);
- N_box.take(x);
- }
- else
- touch_border_of_image = true;
- deja_vu(x) = in_N;
- }
- }
- // gN <- min u(x) for all x in N
- update_gN(N, gN, Set());
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (Set::compare(g, gN))
- {
- g = gN;
-
- ++n_comps;
-
- if (touch_border_of_image)
- blob(Set(), deja_vu, N, in_N, N_box.to_result().to_larger(1), current_cc);
- else
- blob(Set(), deja_vu, N, in_N, N_box, current_cc);
-
- n_holes += current_cc->elt().holes.nsites();
-
- node_type* child = current_cc;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- child->set_parent(current_cc);
-
-
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // c)
- else
- {
- n_step_4c++;
- mln_piter(I) r(N_box);
- for_all(r)
- if (deja_vu(r) == in_R)
- u(r) = g;
-
- goto step_1;
- }
- }
-
- the_end:
- std::cout << " n_step1 : " << n_step_1 << " n_step3 : " << n_step_3 << " n_step4c : " << n_step_4c << std::endl;
- std::cout << "n comps = " << n_comps << " n holes = " << n_holes << std::endl;
-
- return *new tree_type(current_cc);
- }
-
- /*! Get the hole of a shape which contains a given point.
- *
- * \param[in] node a shape.
- * \param[in] p a point.
- * \param[in] other_reg The map which associate a point with its smallest shape
- * of the oposite tree.
- * \return true if A is included in B.
- *
- */
- // F is the set in which we get the node.
- template <typename P, typename V, typename F>
- fllt_node(P, V)*
- find_hole(fllt_node(P, V)& node,
- const P p,
- const image2d<fllt_node(P, V)*>& other_reg)
- {
- fllt_node(P, V)* s = other_reg(p);
- mln_assertion(s);
- // Go up the tree.
- while (s->parent() && F::compare(s->parent()->elt().value, node.elt().value))
- {
- mln_assertion(s);
- s = s->parent();
- mln_assertion(s);
- }
- // std::cout << " [Find the hole] of " << p
- // << " from " << &node
- // << " return " << s
- // << std::endl;
- return s;
- }
-
- /*! Test the inclusion of two shapes of the same tree
- *
- * \param[in] A a shape.
- * \param[in] B a shape.
- * \return true if A is included in B.
- *
- * \pre The shapes have to come from the same tree.
- */
- template <typename P, typename V>
- bool shape_is_included(fllt_node(P, V)* A,
- fllt_node(P, V)* B)
- {
- return A->parent() == B || A == B;
- }
-
- /*! Associated the points of the holes of the min/max tree's shapes.
- *
- * \param[in] lower_tree The min tree.
- * \param[in] upper_tree The max tree.
- * \param[in] low_reg The map which associate a point with its smallest shape
- * of the min tree.
- * \param[in] upp_reg The map which associate a point with its smallest shape
- * of the max tree.
- * \return The merged tree.
- *
- */
- template <typename P, typename V>
- void find_all_holes(fllt_tree(P, V)& lower_tree,
- fllt_tree(P, V)& upper_tree,
- const image2d<fllt_node(P, V)*>& low_reg,
- const image2d<fllt_node(P, V)*>& upp_reg)
- {
- typedef p_array<P> arr_t;
- typedef fllt_node(P, V) node_type;
-
- // Get the holes of the min tree
- {
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,upper<V> >(node, P(hole), upp_reg));
- }
- }
-
- // Get the holes of the max tree
- {
- fllt_branch_iter_ind(P, V) node_(upper_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,lower<V> >(node, P(hole), low_reg));
- }
- }
- }
-
- /*! Merge the Min and the max tree.
- *
- * \param[in] lower_tree The min tree.
- * \param[in] upper_tree The max tree.
- * \param[in] low_reg The map which associate a point with its smallest shape
- * of the min tree.
- * \param[in] upp_reg The map which associate a point with its smallest shape
- * of the max tree.
- * \return The merged tree.
- *
- */
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- merge_trees(fllt_tree(mln_point(I), mln_value(I))& lower_tree,
- fllt_tree(mln_point(I), mln_value(I))& upper_tree,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& low_reg,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& upp_reg,
- const Image<I>& input_)
- {
-
- const I& input = exact(input_);
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
- typedef p_array<P> arr_t;
-
-
- // Here, a hole of a shape of the max or min tree is represented
- // by a point belonging to this hole. We need to associate each of
- // these points with its shape in the oposite tree.
- find_all_holes(lower_tree, upper_tree, low_reg, upp_reg);
- std::vector<node_type*> to_fill;
-
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- // Browse the shapes of the min_tree, in order to put as child of
- // min tree's shapes the shapes of the max tree corresponding to
- // their holes.
- for_all(node_)
- {
- node_type& node = *node_;
- // If the node was not in the min tree at the begining, we ignore it.
- if (node.elt().set_id != lower<V>::id)
- continue;
-
- // Browse the holes of the shape.
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- // Check if hole_ is contained by a hole of the children of node.
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
-
- // If no, move the shape of the max tree previously associated to this hole.
- // as child of node.
- if (!child_has_bigger_hole)
- {
- // // std::cout << "move " << hole << " as child of " << &node << std::endl;
- node.add_child(hole);
- to_fill.push_back(hole);
- }
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- // At this step, we have filled all the holes of the min
- // tree. But, by filling these holes, we introduced somes holes of
- // the max tree in the result tree. We need to fill them.
-
- // Thus, we browse the shapes of the max tree previously merged in
- // the min tree, in order to check their holes.
- for(typename std::vector<node_type*>::iterator node_ = to_fill.begin();
- node_ != to_fill.end();
- node_++)
- {
- node_type& node = **node_;
-
- fllt_branch_iter_ind(P, V) node_(fllt_branch(P, V)(upper_tree, node));
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != upper<V>::id)
- continue;
-
- // Check if hole_ is contained by a hole of the children of node.
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
-
- // If no, move the shape of the max tree previously associated to this hole.
- // as child of node.
- if (!child_has_bigger_hole)
- node.add_child(hole);
-
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- }
-
- return lower_tree;
- }
-
- /*! This function compute the fllt tree of an image.
- *
- * \param[in] input_ An input image.
- * \return The computed tree.
- *
- */
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- fllt(const Image<I>& input_)
- {
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- const I& input = exact(input_);
-
- fllt_tree(P, V) upper_tree;
- fllt_tree(P, V) lower_tree;
- image2d<fllt_node(P, V)*> low_reg(input.domain());
- image2d<fllt_node(P, V)*> upp_reg(input.domain());
-
- // Compute the Min tree.
- std::cout << "1/ Compute the lower level set.----------------------------------------" << std::endl;
- lower_tree = level_set<I, lower<V> >(input, low_reg);
-
- // Compute the Max tree.
- std::cout << "2/ Compute the upper level set.----------------------------------------" << std::endl;
- upper_tree = level_set<I, upper<V> >(input, upp_reg);
-
- // Merge the two trees.
- std::cout << "3/ Merge.---------------------------------------------------------------" << std::endl;
- fllt_tree(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, input);
-
- return result_tree;
- }
-
-} // end of namespace mln
-
-#endif // ! MLN_FLLT_HH
Index: geraud/fllt/fllt_tree_to_image.hh
--- geraud/fllt/fllt_tree_to_image.hh (revision 3151)
+++ geraud/fllt/fllt_tree_to_image.hh (working copy)
@@ -1,30 +0,0 @@
-#ifndef MLN_FLLT_TREE_TO_IMAGE_HH
-# define MLN_FLLT_TREE_TO_IMAGE_HH
-
-#include "fllt.svg.7.hh"
-
-namespace mln
-{
- template <typename I>
- void fllt_tree_to_image_(I& output,
- fllt_node(point2d, value::int_u8)* node)
- {
- data::fill((output | node->elt().points).rw(), node->elt().value);
-
- for (int i = 0; i < node->children().size(); i++)
- fllt_tree_to_image_(output, node->children()[i]);
- }
-
- template <typename I>
- I fllt_tree_to_image(const I& input,
- fllt_tree(point2d, value::int_u8)& tree)
- {
- I output;
- initialize(output, input);
- fllt_tree_to_image_(output, tree.root());
- return output;
- }
-
-}
-
-#endif // ! MLN_FLLT_TREE_TO_IMAGE_HH
Index: geraud/fllt/fllt.svg.2.cc
--- geraud/fllt/fllt.svg.2.cc (revision 3151)
+++ geraud/fllt/fllt.svg.2.cc (working copy)
@@ -1,304 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-
-#include <mln/value/int_u8.hh>
-# include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/opt/at.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
- namespace my
- {
-
- template <typename N_t, typename G>
- void update_gN(const N_t& N, G& gN)
- {
- for (unsigned g = 0; g < 256; ++g)
- if (N[g].nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- {
- if (N[i].nsites() == 0)
- continue;
- std::cout << i << ": " << N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- N[i].clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- opt::at(output, row, col) =
- mln::opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- template <typename I>
- void save(const I& is, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- switch (is(p)) {
- case 1: // R
- temp(p) = literal::red;
- break;
- case 2: // N
- temp(p) = literal::green;
- break;
- case 3: // A
- temp(p) = literal::blue;
- break;
- }
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(my::enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
- template <typename I, typename Nbh>
- void fllt(const Image<I>& input_, const Neighborhood<Nbh>& nbh_)
- {
- const I& input = exact(input_);
- const Nbh& nbh = exact(nbh_);
-
- unsigned l = 0, l_max;
- mln_ch_value(I, unsigned) reg_min = labeling::regional_minima(input, nbh, l_max);
-
- // Variables.
- I u = mln::duplicate(input);
- mln_point(I) x0;
- mln_value(I) g, gN;
- image2d<unsigned char> is(input.domain());
- const unsigned in_R = 1, in_N = 2, in_A = 3, in_O = 0;
-
- typedef p_array<mln_point(I)> arr_t;
- arr_t A, R;
- R.reserve(input.nsites());
- arr_t N[256];
-
- accu::bbox<mln_point(I)> R_box;
-
- unsigned n_step_1 = 0, n_step_3 = 0;
-
- // Step 1.
- step_1:
- {
- if (l == l_max)
- goto the_end;
-
- ++n_step_1;
-
- l += 1;
- mln_piter(I) p(input.domain());
- for_all(p)
- if (reg_min(p) == l)
- break;
- x0 = p;
- g = input(x0);
- }
-
- // Step 2.
- step_2:
- {
- data::fill(is, in_O);
- // R <- 0
- R_box.init();
- R.clear();
- // A <- { x0 }
- A.clear();
- A.append(x0);
- is(x0) = in_A;
- // N <- 0
- clear_N(N);
- }
-
- // Step 3.
- step_3:
- {
- ++n_step_3;
-
- mln_piter(arr_t) a(A);
- mln_niter(Nbh) x(nbh, a);
-
-
- my::save(is);
-
-
- // R <- R U A
- if (A.nsites() == 0)
- goto the_end;
-
- R.append(A);
- for_all(a)
- {
- mln_invariant(is(a) == in_A);
- is(a) = in_R;
- }
- mln_invariant(R.nsites() == (is | in_R).nsites());
- R_box.take(A.bbox());
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- if (u.has(x) && is(x) == in_O)
- {
- N[u(x)].append(x);
- is(x) = in_N;
- }
- // gN = min u(x) for all x in N
- update_gN(N, gN);
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (g < gN)
- {
- g = gN;
- // FIXME: DO the hole thing.
- A = N[g];
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- mln_invariant(is(a) == in_N);
- is(a) = in_A;
- }
- N[g].clear();
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- A = N[g];
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- mln_invariant(is(a) == in_N);
- is(a) = in_A;
- }
- N[g].clear();
- goto step_3;
- }
- // c)
- else
- {
- mln_invariant(R_box.to_result() == geom::bbox(is | in_R));
- mln_piter(arr_t) r(R);
- for_all(r)
- u(r) = g;
- goto step_1;
- }
- }
-
- the_end:
- std::cout << n_step_1 << ' ' << n_step_3 << std::endl;
-
- }
-
- } // end of namespace mln::my
-
-} // end of namespace mln
-
-
-int main()
-{
- using namespace mln;
- using value::int_u8;
-
- image2d<int_u8> lena;
- io::pgm::load(lena, "../../img/tiny.pgm");
-
- my::fllt(lena, c4());
- io::pgm::save(lena, "./out.pgm");
-
-}
Index: geraud/fllt/fllt.svg.3.cc
--- geraud/fllt/fllt.svg.3.cc (revision 3151)
+++ geraud/fllt/fllt.svg.3.cc (working copy)
@@ -1,313 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-#include <mln/core/image/sub_image.hh>
-
-#include <mln/value/int_u8.hh>
-# include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/opt/at.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
- namespace my
- {
-
- template <typename N_t, typename G>
- void update_gN(const N_t& N, G& gN)
- {
- for (unsigned g = 0; g < 256; ++g)
- if (N[g].nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- {
- if (N[i].nsites() == 0)
- continue;
- std::cout << i << ": " << N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- N[i].clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- mln::opt::at(output, row, col) =
- mln::opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- template <typename I>
- void save(const I& is, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- switch (is(p)) {
- case 1: // R
- temp(p) = literal::red;
- break;
- case 2: // N
- temp(p) = literal::green;
- break;
- case 3: // A
- temp(p) = literal::blue;
- break;
- }
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(my::enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
- template <typename I, typename Nbh>
- void fllt(const Image<I>& input_, const Neighborhood<Nbh>& nbh_)
- {
- const I& input = exact(input_);
- const Nbh& nbh = exact(nbh_);
-
- unsigned l = 0, l_max;
- mln_ch_value(I, unsigned) reg_min = labeling::regional_minima(input, nbh, l_max);
- std::vector<bool> tag(l_max + 1, false);
- tag[0] = true;
-
- // Variables.
- I u = mln::duplicate(input);
- mln_point(I) x0;
- mln_value(I) g, gN;
- mln_fwd_piter(I) p(input.domain());
- p.start();
-
- image2d<unsigned char> is(input.domain());
- const unsigned in_R = 1, in_N = 2, in_A = 3, in_O = 0;
- data::fill(is, in_O);
-
- typedef p_array<mln_point(I)> arr_t;
- arr_t A;
- arr_t N[256];
- accu::bbox<mln_point(I)> N_box;
-
- unsigned n_step_1 = 0, n_step_3 = 0;
-
- // Step 1.
- step_1:
- {
- while (tag[reg_min(p)] && p.is_valid())
- p.next();
- if (p.is_valid())
- tag[reg_min(p)] = true; // To be processed.
- else
- goto the_end;
-
- ++n_step_1;
- x0 = p;
- g = input(x0);
- }
-
- // Step 2.
- step_2:
- {
- // R <- 0 and N <- 0
- if (N_box.is_valid() != 0)
- data::fill((is | N_box.to_result()).rw(), in_O);
- clear_N(N);
- N_box.init();
-
- // A <- { x0 }
- A.clear();
- A.append(x0);
- is(x0) = in_A;
- }
-
- // Step 3.
- step_3:
- {
- ++n_step_3;
-
- mln_piter(arr_t) a(A);
- mln_niter(Nbh) x(nbh, a);
-
-
-// my::save(is);
-
-
- // R <- R U A
- if (A.nsites() == 0)
- goto the_end;
-
- for_all(a)
- {
- mln_invariant(is(a) == in_A);
- is(a) = in_R;
- }
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- if (u.has(x) && is(x) == in_O)
- {
- N[u(x)].append(x);
- is(x) = in_N;
- N_box.take(x);
- }
- // gN = min u(x) for all x in N
- update_gN(N, gN);
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (g < gN)
- {
- g = gN;
- // FIXME: DO the hole thing.
- A = N[g];
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- mln_invariant(is(a) == in_N);
- is(a) = in_A;
- // N_box is not re-computed so that we save time;
- // N_box is always growing while looping from step 3.
- }
- N[g].clear();
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- A = N[g];
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- mln_invariant(is(a) == in_N);
- is(a) = in_A;
- }
- N[g].clear();
- goto step_3;
- }
- // c)
- else
- {
- mln_piter(I) r(N_box);
- for_all(r)
- if (is(r) == in_R)
- u(r) = g;
- goto step_1;
- }
- }
-
- the_end:
- std::cout << n_step_1 << ' ' << n_step_3 << std::endl;
-
- }
-
- } // end of namespace mln::my
-
-} // end of namespace mln
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 2)
- {
- std::cerr << "usage: " << argv[0] << " filename" << std::endl;
- return 1;
- }
-
- using namespace mln;
- using value::int_u8;
-
- image2d<int_u8> lena;
- io::pgm::load(lena, argv[1]);
-
- my::fllt(lena, c4());
- io::pgm::save(lena, "./out.pgm");
-
-}
Index: geraud/fllt/fllt.svg.4.cc
--- geraud/fllt/fllt.svg.4.cc (revision 3151)
+++ geraud/fllt/fllt.svg.4.cc (working copy)
@@ -1,352 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-#include <mln/core/image/sub_image.hh>
-
-#include <mln/value/int_u8.hh>
-# include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/level/compare.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-#include <mln/pw/all.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/opt/at.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
- namespace my
- {
-
- template <typename N_t, typename G>
- void update_gN(const N_t& N, G& gN)
- {
- for (unsigned g = 0; g < 256; ++g)
- if (N[g].nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- {
- if (N[i].nsites() == 0)
- continue;
- std::cout << i << ": " << N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- N[i].clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- mln::opt::at(output, row, col) =
- mln::opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- template <typename I>
- void save(const I& is, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- switch (is(p)) {
- case 1: // R
- temp(p) = literal::red;
- break;
- case 2: // N
- temp(p) = literal::green;
- break;
- case 3: // A
- temp(p) = literal::blue;
- break;
- }
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(my::enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
- template <typename I, typename Nbh>
- void fllt(const Image<I>& input_, const Neighborhood<Nbh>& nbh_)
- {
- const I& input = exact(input_);
- const Nbh& nbh = exact(nbh_);
-
- unsigned l = 0, l_max;
- mln_ch_value(I, unsigned) reg_min = labeling::regional_minima(input, nbh, l_max);
- std::vector<bool> tag(l_max + 1, false);
- tag[0] = true;
-
- // Variables.
- I u = mln::duplicate(input);
- mln_point(I) x0;
- mln_value(I) g, gN;
- mln_fwd_piter(I) p(input.domain());
- p.start();
-
-// image2d<unsigned char> is(input.domain());
-// const unsigned in_R = 1, in_N = 2, in_A = 3, in_O = 0;
-// data::fill(is, in_O);
-
- image2d<bool> deja_vu(input.domain());
- data::fill(deja_vu, false);
-
- typedef p_array<mln_point(I)> arr_t;
- arr_t A;
- arr_t N[256];
- accu::bbox<mln_point(I)> N_box;
-
- unsigned n_step_1 = 0, n_step_3 = 0;
-
- // Step 1.
- step_1:
- {
- while (tag[reg_min(p)] && p.is_valid())
- p.next();
- if (p.is_valid())
- tag[reg_min(p)] = true; // To be processed.
- else
- goto the_end;
-
- ++n_step_1;
- x0 = p;
- g = input(x0);
- }
-
- // Step 2.
- step_2:
- {
- // R <- 0 and N <- 0
- if (N_box.is_valid() != 0)
- {
-// data::fill((is | N_box.to_result()).rw(), in_O);
- data::fill(deja_vu | N_box.to_result()), false);
- }
- clear_N(N);
- N_box.init();
-
- // A <- { x0 }
- A.clear();
- A.append(x0);
-// is(x0) = in_A;
- deja_vu(x0) = true;
- }
-
- // Step 3.
- step_3:
- {
- ++n_step_3;
-
- mln_piter(arr_t) a(A);
- mln_niter(Nbh) x(nbh, a);
-
-
-// my::save(is);
-
-
- // R <- R U A
- if (A.nsites() == 0)
- goto the_end;
-
-// for_all(a)
-// {
-// mln_invariant(is(a) == in_A);
-// is(a) = in_R;
-// }
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- {
-// if (u.has(x))
-// mln_invariant(is(x) != in_O || deja_vu(x) == false);
-
- //if (u.has(x) && is(x) == in_O)
- if (u.has(x) && !deja_vu(x))
- {
- N[u(x)].append(x);
-// is(x) = in_N;
- N_box.take(x);
- deja_vu(x) = true;
- }
- }
- // gN = min u(x) for all x in N
- update_gN(N, gN);
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (g < gN)
- {
- g = gN;
- // FIXME: DO the hole thing.
- A = N[g];
-// mln_piter(arr_t) a(A);
-// for_all(a)
-// {
-// mln_invariant(is(a) == in_N);
-// is(a) = in_A;
-// // N_box is not re-computed so that we save time;
-// // N_box is always growing while looping from step 3.
-// }
- N[g].clear();
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- A = N[g];
-// mln_piter(arr_t) a(A);
-// for_all(a)
-// {
-// mln_invariant(is(a) == in_N);
-// is(a) = in_A;
-// }
- N[g].clear();
- goto step_3;
- }
- // c)
- else
- {
- // Here deja_vu is (R U N U A)
- // we only want R
-
- // yet A is empty (cause included in R)
- // so this test is ok: mln_invariant((is | in_A).nsites() == 0);
-
- for (unsigned i = 0; i < 256; ++i)
- if (N[i].nsites())
- data::fill(deja_vu | N[i]), false);
-// {
-// mln_piter(arr_t) p(N[i]);
-// for_all(p)
-// deja_vu(p) = false;
-// }
-
-// mln_invariant(deja_vu == ((pw::value(is) == pw::cst(in_R)) | input.domain()));
-
-// mln_piter(I) r(N_box);
-// for_all(r)
-// if (is(r) == in_R)
-// u(r) = g;
-
- mln_piter(I) r(N_box);
- for_all(r)
- if (deja_vu(r))
- u(r) = g;
-
- goto step_1;
- }
- }
-
- the_end:
- std::cout << n_step_1 << ' ' << n_step_3 << std::endl;
-
- }
-
- } // end of namespace mln::my
-
-} // end of namespace mln
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 2)
- {
- std::cerr << "usage: " << argv[0] << " filename" << std::endl;
- return 1;
- }
-
- using namespace mln;
- using value::int_u8;
-
- image2d<int_u8> lena;
- io::pgm::load(lena, argv[1]);
-
- my::fllt(lena, c4());
- io::pgm::save(lena, "./out.pgm");
-
-}
Index: geraud/fllt/fllt.svg.5.cc
--- geraud/fllt/fllt.svg.5.cc (revision 3151)
+++ geraud/fllt/fllt.svg.5.cc (working copy)
@@ -1,353 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-#include <mln/core/image/sub_image.hh>
-
-#include <mln/value/int_u8.hh>
-# include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/level/compare.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-#include <mln/pw/all.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/opt/at.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
- namespace my
- {
-
- template <typename N_t, typename G>
- void update_gN(const N_t& N, G& gN)
- {
- for (unsigned g = 0; g < 256; ++g)
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- {
- if (N[i]->nsites() == 0)
- continue;
- std::cout << i << ": " << *N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- N[i]->clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- opt::at(output, row, col) =
- mln::opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- template <typename I>
- void save(const I& is, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- switch (is(p)) {
- case 1: // R
- temp(p) = literal::red;
- break;
- case 2: // N
- temp(p) = literal::green;
- break;
- case 3: // A
- temp(p) = literal::blue;
- break;
- }
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(my::enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
- template <typename I, typename Nbh>
- void fllt(const Image<I>& input_, const Neighborhood<Nbh>& nbh_)
- {
- const I& input = exact(input_);
- const Nbh& nbh = exact(nbh_);
-
- unsigned l = 0, l_max;
- mln_ch_value(I, unsigned) reg_min = labeling::regional_minima(input, nbh, l_max);
- std::vector<bool> tag(l_max + 1, false);
- tag[0] = true;
-
- // Variables.
- I u = mln::duplicate(input);
- mln_point(I) x0;
- mln_value(I) g, gN;
- mln_fwd_piter(I) p(input.domain());
- p.start();
-
-// image2d<unsigned char> is(input.domain());
-// const unsigned in_R = 1, in_N = 2, in_A = 3, in_O = 0;
-// data::fill(is, in_O);
-
- image2d<bool> deja_vu(input.domain());
- data::fill(deja_vu, false);
-
- typedef p_array<mln_point(I)> arr_t;
- arr_t* A = new arr_t();
- arr_t* N[256];
- for (unsigned i = 0; i < 256; ++i)
- N[i] = new arr_t();
- accu::bbox<mln_point(I)> N_box;
-
- unsigned n_step_1 = 0, n_step_3 = 0;
-
- // Step 1.
- step_1:
- {
- while (tag[reg_min(p)] && p.is_valid())
- p.next();
- if (p.is_valid())
- tag[reg_min(p)] = true; // To be processed.
- else
- goto the_end;
-
- ++n_step_1;
- x0 = p;
- g = input(x0);
- }
-
- // Step 2.
- step_2:
- {
- // R <- 0 and N <- 0
- if (N_box.is_valid() != 0)
- {
-// data::fill((is | N_box.to_result()).rw(), in_O);
- data::fill(deja_vu | N_box.to_result()), false);
- }
- clear_N(N);
- N_box.init();
-
- // A <- { x0 }
- A->clear();
- A->append(x0);
-// is(x0) = in_A;
- deja_vu(x0) = true;
- }
-
- // Step 3.
- step_3:
- {
- ++n_step_3;
-
- mln_piter(arr_t) a(*A);
- mln_niter(Nbh) x(nbh, a);
-
-
-// my::save(is);
-
-
- // R <- R U A
- if (A->nsites() == 0)
- goto the_end;
-
-// for_all(a)
-// {
-// mln_invariant(is(a) == in_A);
-// is(a) = in_R;
-// }
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- {
-// if (u.has(x))
-// mln_invariant(is(x) != in_O || deja_vu(x) == false);
-
- //if (u.has(x) && is(x) == in_O)
- if (u.has(x) && !deja_vu(x))
- {
- N[u(x)]->append(x);
-// is(x) = in_N;
- N_box.take(x);
- deja_vu(x) = true;
- }
- }
- // gN = min u(x) for all x in N
- update_gN(N, gN);
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (g < gN)
- {
- g = gN;
- // FIXME: DO the hole thing.
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
-// mln_piter(arr_t) a(A);
-// for_all(a)
-// {
-// mln_invariant(is(a) == in_N);
-// is(a) = in_A;
-// // N_box is not re-computed so that we save time;
-// // N_box is always growing while looping from step 3.
-// }
- N[g]->clear();
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
-// mln_piter(arr_t) a(A);
-// for_all(a)
-// {
-// mln_invariant(is(a) == in_N);
-// is(a) = in_A;
-// }
- N[g]->clear();
- goto step_3;
- }
- // c)
- else
- {
- // Here deja_vu is (R U N U A)
- // we only want R
-
- // yet A is empty (cause included in R)
- // so this test is ok: mln_invariant((is | in_A).nsites() == 0);
-
- for (unsigned i = 0; i < 256; ++i)
- if (N[i]->nsites())
- data::fill(deja_vu | *N[i]), false);
-
-// mln_invariant(deja_vu == ((pw::value(is) == pw::cst(in_R)) | input.domain()));
-
-// mln_piter(I) r(N_box);
-// for_all(r)
-// if (is(r) == in_R)
-// u(r) = g;
-
- mln_piter(I) r(N_box);
- for_all(r)
- if (deja_vu(r))
- u(r) = g;
-
- goto step_1;
- }
- }
-
- the_end:
- std::cout << n_step_1 << ' ' << n_step_3 << std::endl;
-
- }
-
- } // end of namespace mln::my
-
-} // end of namespace mln
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 2)
- {
- std::cerr << "usage: " << argv[0] << " filename" << std::endl;
- return 1;
- }
-
- using namespace mln;
- using value::int_u8;
-
- image2d<int_u8> lena;
- io::pgm::load(lena, argv[1]);
-
- my::fllt(lena, c4());
- io::pgm::save(lena, "./out.pgm");
-
-}
Index: geraud/fllt/fllt.svg.6.cc
--- geraud/fllt/fllt.svg.6.cc (revision 3151)
+++ geraud/fllt/fllt.svg.6.cc (working copy)
@@ -1,1136 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <iomanip>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-#include <mln/core/image/sub_image.hh>
-#include <mln/core/site_set/p_queue_fast.hh>
-#include <mln/core/image/cast_image.hh>
-
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/level/compare.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/labeling/regional_maxima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-#include <mln/pw/all.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/util/tree.hh>
-#include <mln/util/branch_iter_ind.hh>
-#include <mln/util/branch_iter.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
- namespace my
- {
-
-# define fllt_tree(P, V) mln::util::tree< fllt_node_elt<P, V> >
-# define fllt_node(P, V) mln::util::tree_node< fllt_node_elt<P, V> >
-# define fllt_tree_ptr(P, V) mln::util::tree< fllt_node_elt<P, V>* >
-# define fllt_node_ptr(P, V) mln::util::tree_node< fllt_node_elt<P, V>* >
-# define fllt_branch(P, V) mln::util::branch< fllt_node_elt<P, V> >
-# define fllt_branch_iter_ind(P, V) mln::util::branch_iter_ind< fllt_node_elt<P, V> >
-# define fllt_branch_iter(P, V) mln::util::branch_iter< fllt_node_elt<P, V> >
-
-# define stl_to_mln_iter(T) stl_iterator< T >
-
- //Fwd declarations.
- template <typename V> struct lower;
- template <typename V> struct upper;
-
- template <typename P, typename V>
- struct fllt_node_elt
- {
- V value;
- p_array<P> points;
- p_array<P> holes;
- std::vector<fllt_node(P, V)*> hole_shapes;
- /// Tell if his parent if brighter or not. Nb : if the parent
- /// if brighter, the node come from the lower level set
- bool brighter;
- unsigned nsites;
- bool tagged;
- bool set_id;
-
- fllt_node_elt(bool set_id) : nsites(0), tagged(false), set_id(set_id) {}
- };
-
-
- template <typename C>
- class stl_iterator
- {
- public:
- stl_iterator(C& c) : container_(c) {}
- void start(){ it_ = container_.begin(); }
- void next() { it_++; }
- bool is_valid() const{ return it_ != container_.end(); }
- typename C::value_type& operator*() { return *it_; }
-
- private:
- C& container_;
- typename C::iterator it_;
- };
-
- template <typename N_t, typename G, typename Set>
- void update_gN(const N_t& N, G& gN);
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, lower<V>)
- {
- for (unsigned g = 0; g < 256; ++g)
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, upper<V>)
- {
- for (int g = 255; g >= 0; --g)
- {
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- }
- // if N is empty, gN is the min value.
- gN = 0;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- {
- if (N[i]->nsites() == 0)
- continue;
- std::cout << i << ": " << *N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- N[i]->clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- opt::at(output, row, col) = opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- void save_u(const image2d<value::int_u8>& u,
- const image2d<int>& is,
- box2d R_box,
- int in_R,
- int in_N)
- {
- static int id = 0;
- std::stringstream filename;
- filename << "fllt_trace_" << std::setw(5) << std::setfill('0')
- << std::right << id++ << ".ppm";
-
- image2d<value::int_u8> out = duplicate(cast_image<value::int_u8>(is));
-
- mln_assertion(R_box.nsites() > 0);
- mln_piter_(box2d) p(R_box);
- for_all(p)
- if (is(p) == in_R)
- out(p) = 255;
- else if (is(p) == in_N)
- out(p) = 127;
- // else if (is(p) == in_N)
- // out(p) = literal::green;
-
- io::pgm::save(out, filename.str());
- //io::pgm::save(out, filename.str());
- }
-
- template <typename I>
- void save(const I& is, unsigned in_N, unsigned in_R, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- if (is(p) == in_R)
- temp(p) = literal::red;
- else if (is(p) == in_N) // N
- temp(p) = literal::green;
- else if (is(p) < in_N)
- temp(p) = literal::blue;
- else
- temp(p) = literal::white;
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(my::enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
-
- template <typename I, typename P, typename V, typename Set>
- void blob(const Set&,
- const I& is,
- p_array<mln_point(I)>* N[256],
- unsigned in_N,
- const box2d& N_box,
- fllt_node(P, V)* current_cc)
- {
- typedef p_array<mln_point(I)> arr_t;
-
-// std::cout << ">>>>>>>enter blob. " << current_cc << std::endl;
- bool flower = true;
- unsigned ncc = 0;
- static image2d<unsigned> is_labeled(is.domain());
- static unsigned label = 0;
-
- if (label == 0)
- {
- data::fill(is_labeled, 0);
- label++;
- }
-
- P cur;
- mln_niter(neighb2d) n(Set::bdr_nbh()/*c8()*/, cur);
- p_queue_fast<P> qu;
- p_array<P>& holes = current_cc->elt().holes;
-
- mln_piter(I) p(N_box);
- for_all(p)
- if (is(p) == in_N)
- break;
-
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
-
-
-
- for (unsigned i = 0; i < 256; ++i)
- //for (int i = 255; i >= 0; --i)
- {
- mln_piter(arr_t) p(*N[i]);
- for_all(p)
- {
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
- }
- }
-
- ++label;
-
- // if (holes.size() == 2)
- // std::cout << holes[0] << holes[1] << std::endl;
- // std::cout << " <<<<<<<exiting blob." << std::endl;
- }
-
-// template <typename I, typename V>
-// void blob(const I& is,
-// p_array<mln_point(I)>* N[256],
-// unsigned in_N,
-// const box2d& N_box,
-// fllt_node(mln_point(I), V)* current_cc)
-// {
-// typedef p_array<mln_point(I)> arr_t;
-
-// // std::cout << ">>>>>>>enter blob. " << current_cc << std::endl;
-// bool flower = true;
-// unsigned ncc = 0;
-// static image2d<unsigned> is_labeled(is.domain());
-// static unsigned label = 0;
-
-// if (label == 0)
-// {
-// data::fill(is_labeled, 0);
-// label++;
-// }
-
-// typedef mln_psite(I) P;
-// P cur;
-// mln_niter(neighb2d) n(c8(), cur);
-// p_queue_fast<P> qu;
-// p_array<P>& holes = current_cc->elt().holes;
-
-// mln_piter(I) p(N_box);
-// for_all(p)
-// if (is(p) == in_N)
-// break;
-
-// mln_assertion(is(p) == in_N);
-// if (is_labeled(p) != label)
-// {
-// if (flower == false)
-// holes.append(p);
-// else
-// flower = false;
-// qu.push(p);
-// is_labeled(p) = label;
-// do
-// {
-// cur = qu.front();
-// qu.pop();
-// for_all(n) if (is.has(n))
-// if (is(n) == in_N && is_labeled(n) != label)
-// {
-// qu.push(n);
-// is_labeled(n) = label;
-// }
-// }
-// while (! qu.is_empty());
-// }
-
-
-
-// for (unsigned i = 0; i < 256; ++i)
-// //for (int i = 255; i >= 0; --i)
-// {
-// mln_piter(arr_t) p(*N[i]);
-// for_all(p)
-// {
-// mln_assertion(is(p) == in_N);
-// if (is_labeled(p) != label)
-// {
-// if (flower == false)
-// holes.append(p);
-// else
-// flower = false;
-// qu.push(p);
-// is_labeled(p) = label;
-// do
-// {
-// cur = qu.front();
-// qu.pop();
-// for_all(n) if (is.has(n))
-// if (is(n) == in_N && is_labeled(n) != label)
-// {
-// qu.push(n);
-// is_labeled(n) = label;
-// }
-// }
-// while (! qu.is_empty());
-// }
-// }
-// }
-
-// ++label;
-
-// // if (holes.size() == 2)
-// // std::cout << holes[0] << holes[1] << std::endl;
-// // std::cout << " <<<<<<<exiting blob." << std::endl;
-// }
-
- template <typename P, typename V>
- void
- move_A_to_R(p_array<P>& A,
- image2d<int>& deja_vu,
- fllt_node(P, V)* current_cc,
- image2d< fllt_node(P, V)* >& smallest_shapes,
- int in_R,
- int in_N,
- const V& g,
- unsigned& n_comps)
- {
- typedef p_array<P> arr_t;
-
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- mln_invariant(deja_vu(a) == in_N);
- mln_invariant(smallest_shapes(a) != current_cc);
-
- deja_vu(a) = in_R;
- current_cc->elt().nsites++;
- if (!smallest_shapes(a))
- {
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- if (!smallest_shapes(a)->parent())
- if (smallest_shapes(a)->elt().value == g)
- {
- fllt_node(P, V)* to_delete = smallest_shapes(a);
-
- mln_piter(arr_t) p(smallest_shapes(a)->elt().points);
- // Todo optimization here.
- for_all(p)
- smallest_shapes(p) = 0;
-
- while(!to_delete->children().empty())
- current_cc->add_child(*to_delete->children().begin());
- delete to_delete;
- n_comps--;
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- smallest_shapes(a)->set_parent(current_cc);
- // N_box is not re-computed so that we save time;
- // N_box is always growing while looping from step 3.
- }
- }
-
- // LOWER LEVEL SET : region = c4, border = c8
- template <typename V>
- struct lower
- {
- typedef upper<V> opposite;
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- {
- return u < v;
- }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- {
- return labeling::regional_minima(input, nbh, nlabels);
- }
-
- static const bool parent_is_brighter = true;
- static const bool id = false;
-
- static const neighb2d& bdr_nbh() { return c8(); }
- static const neighb2d& reg_nbh() { return c4(); }
- };
-
-
- // UPPER LEVEL SET : region = c8, border = c4
- template <typename V>
- struct upper
- {
- typedef lower<V> opposite;
-
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- { return u > v; }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- { return labeling::regional_maxima(input, nbh, nlabels); }
-
- static const bool parent_is_brighter = false;
- static const bool id = true;
-
- static const neighb2d& bdr_nbh() { return c4(); }
- static const neighb2d& reg_nbh() { return c8(); }
- };
-
- template <typename I, typename Set>
- fllt_tree(mln_point(I), mln_value(I))&
- level_set(const Image<I>& input_,
- image2d< fllt_node(mln_point(I), mln_value(I))* >& smallest_shapes)
- {
-
- typedef mln_point(I) P;
- typedef mln_value(I) V;
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
-
- const I& input = exact(input_);
-
- mln_assertion(input.domain() == smallest_shapes.domain());
-
- unsigned l = 0, l_max = 0;
- mln_ch_value(I, unsigned) reg_min = Set::regional_extremum(input, Set::reg_nbh(), l_max);
- std::vector<bool> tag(l_max + 1, false);
- tag[0] = true;
-
- // Variables.
- I u = mln::duplicate(input);
- P x0;
- V g, gN;
- mln_fwd_piter(I) p(input.domain());
- p.start();
- data::fill(smallest_shapes, 0);
- node_type* current_cc;
-
- unsigned in_N = 1, in_R = 2;
-
- image2d<int> deja_vu(input.domain().to_larger(1));
- data::fill(deja_vu, 0);
-
- typedef p_array<P> arr_t;
- arr_t* A = new arr_t();
- arr_t* N[256];
- for (unsigned i = 0; i < 256; ++i)
- N[i] = new arr_t();
- accu::bbox<P> N_box;
-
- bool touch_border_of_image = false;
- unsigned n_step_1 = 0, n_step_3 = 0, n_comps = 0, n_holes = 0;
-
- // Step 1.
- step_1:
- {
- while (tag[reg_min(p)] && p.is_valid())
- p.next();
- if (p.is_valid())
- tag[reg_min(p)] = true; // To be processed.
- else
- goto the_end;
-
- ++n_step_1;
- x0 = p;
- g = input(x0);
- ++n_comps;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- touch_border_of_image = false;
-
- }
-
- // Step 2.
- step_2:
- {
- in_N += 2;
- in_R = in_N + 1;
- // R <- 0 and N <- 0
- clear_N(N);
- N_box.init();
-
- // A <- { x0 }
- A->clear();
- A->append(x0);
- N_box.take(x0);
-
- deja_vu(x0) = in_R;
- smallest_shapes(x0) = current_cc;
- current_cc->elt().points.append(x0);
- current_cc->elt().nsites++;
-
- }
-
- // Step 3.
- step_3:
- {
-// save_u(u, deja_vu, N_box, in_R, in_N);
- ++n_step_3;
-
- mln_piter(arr_t) a(*A);
- mln_niter(neighb2d) x(Set::reg_nbh(), a);
-
-
- // R <- R U A
- if (A->nsites() == 0)
- goto the_end;
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- {
- if (deja_vu.has(x) && deja_vu(x) < in_N)
- {
- if (u.has(x))
- {
- N[u(x)]->append(x);
- N_box.take(x);
- }
- else
- touch_border_of_image = true;
- deja_vu(x) = in_N;
- }
- }
- // gN = min u(x) for all x in N
- update_gN(N, gN, Set());
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (Set::compare(g, gN))
- {
- g = gN;
-
- ++n_comps;
-
- if (touch_border_of_image)
- blob(Set(), deja_vu, N, in_N, N_box.to_result().to_larger(1), current_cc);
- else
- blob(Set(), deja_vu, N, in_N, N_box, current_cc);
-
- n_holes += current_cc->elt().holes.nsites();
-
- node_type* child = current_cc;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- child->set_parent(current_cc);
-
-
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // c)
- else
- {
- // FIXME: IDEA: this change might be performed while R is constructed(?)
- mln_piter(I) r(N_box);
- for_all(r)
- if (deja_vu(r) == in_R)
- u(r) = g;
-
- goto step_1;
- }
- }
-
- the_end:
- std::cout << "l_max " << l_max << " " << n_step_1 << ' ' << n_step_3 << std::endl;
- std::cout << "n comps = " << n_comps << " n holes = " << n_holes << std::endl;
-
- return *new tree_type(current_cc);
- }
-
- // F is the set in which we get the node.
- template <typename P, typename V, typename F>
- fllt_node(P, V)*
- find_hole(fllt_node(P, V)& node,
- const P p,
- const image2d<fllt_node(P, V)*>& other_reg)
- {
- fllt_node(P, V)* s = other_reg(p);
- mln_assertion(s);
- while (s->parent() && F::compare(s->parent()->elt().value, node.elt().value))
- {
- mln_assertion(s);
- s = s->parent();
- mln_assertion(s);
- }
-// std::cout << " [Find the hole] of " << p
-// << " from " << &node
-// << " return " << s
-// << std::endl;
- return s;
- }
-
- template <typename P, typename V>
- bool shape_is_included(fllt_node(P, V)* A,
- fllt_node(P, V)* B)
- {
- return A->parent() == B || A == B;
- }
-
- template <typename P, typename V>
- void find_all_holes(fllt_tree(P, V)& lower_tree,
- fllt_tree(P, V)& upper_tree,
- const image2d<fllt_node(P, V)*>& low_reg,
- const image2d<fllt_node(P, V)*>& upp_reg)
- {
- typedef p_array<P> arr_t;
- typedef fllt_node(P, V) node_type;
-
- {
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,upper<V> >(node, P(hole), upp_reg));
- }
- }
-
- {
- fllt_branch_iter_ind(P, V) node_(upper_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,lower<V> >(node, P(hole), low_reg));
- }
- }
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- merge_trees(fllt_tree(mln_point(I), mln_value(I))& lower_tree,
- fllt_tree(mln_point(I), mln_value(I))& upper_tree,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& low_reg,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& upp_reg,
- const Image<I>& input_)
- {
-
- const I& input = exact(input_);
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
- typedef p_array<P> arr_t;
-
-
- find_all_holes(lower_tree, upper_tree, low_reg, upp_reg);
- std::vector<node_type*> to_fill;
-
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != lower<V>::id)
- continue;
-
- // std::cout << "Fill " << &node << std::endl;
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- // std::cout << "hole : " << hole << " " << hole->elt().points << " " << std::endl;
- // std::cout << "child hole : " << child_hole << " " << child_hole->elt().points << std::endl;
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
- if (!child_has_bigger_hole)
- {
- // // std::cout << "move " << hole << " as child of " << &node << std::endl;
- node.add_child(hole);
- to_fill.push_back(hole);
- }
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- for(typename std::vector<node_type*>::iterator node_ = to_fill.begin();
- node_ != to_fill.end();
- node_++)
- {
- node_type& node = **node_;
-
- fllt_branch_iter_ind(P, V) node_(fllt_branch(P, V)(upper_tree, node));
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != upper<V>::id)
- continue;
-
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- //if (hole->elt().points <= child_hole->elt().points)
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
-
- if (!child_has_bigger_hole)
- node.add_child(hole);
-
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- }
-
- return lower_tree;
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- fllt(const Image<I>& input_)
- {
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- const I& input = exact(input_);
-
- fllt_tree(P, V) upper_tree;
- fllt_tree(P, V) lower_tree;
- image2d<fllt_node(P, V)*> low_reg(input.domain());
- image2d<fllt_node(P, V)*> upp_reg(input.domain());
-
- std::cout << "1/ Compute the lower level set.----------------------------------------" << std::endl;
- lower_tree = level_set<I, lower<V> >(input, low_reg);
- //draw_tree(input, lower_tree);
-
- std::cout << "2/ Compute the upper level set.----------------------------------------" << std::endl;
- upper_tree = level_set<I, upper<V> >(input, upp_reg);
- //draw_tree(input, upper_tree);
-
- std::cout << "3/ Merge.---------------------------------------------------------------" << std::endl;
- fllt_tree(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, input);
-
- return result_tree;
- }
-
- template <typename P, typename V>
- void
- draw_tree(const image2d<V>& ima,
- fllt_tree(P, V)& tree)
- {
- p_array<P> tmp;
-
- fllt_branch_iter_ind(P, V) p(tree.main_branch());
- for_all(p)
- {
- std::cout << "region mere : " << (*p).parent() << std::endl;
- std::cout << " ^" << std::endl;
- std::cout << " |" << std::endl;
- std::cout << "region : " << &*p
- << " value = " << (*p).elt().value << std::endl
- << " from " << ((*p).elt().set_id == lower<V>::id ? "lower" : "upper") << " level set." << std::endl
- << " nsites = " << (*p).elt().nsites << std::endl
- << " holes = " << (*p).elt().holes << std::endl;
-
- std::cout << std::endl;
-
- tmp.append((*p).elt().points);
-
- fllt_branch_iter_ind(P, V) n(fllt_branch(P, V)(tree, *p));
- for_all(n)
- tmp.append((*n).elt().points);
-
- if ((*p).elt().points.nsites() > 0)
- debug::println(ima | tmp);
- tmp.clear();
-
- std::cout << std::endl;
- }
- }
-
-
- template <typename P, typename V, typename I>
- unsigned
- compute_area_rec(fllt_node(P, V)* node, I& ima)
- {
-
- if (!node)
- return 0;
-
- int area = 0;
-
- for (int i = 0; i < node->children().size();i++)
- area += compute_area_rec(node->children()[i], ima);
-
- mln_piter(p_array<P>) p(node->elt().points);
- for_all(p)
- if (!ima(P(p)))
- {
- ++area;
- ima(p) = true;
- }
-
- node->elt().nsites = area;
- return area;
- }
-
- template <typename P, typename V, typename I>
- void
- compute_area(const Image<I>& input_, fllt_tree(P, V)& tree)
- {
- const I& input = exact(input_);
-
- image2d<bool> ima(input.domain());
- data::fill(ima, false);
- compute_area_rec(tree.root(), ima);
- }
-
- void draw_shape(image2d<value::int_u8>& output,
- fllt_node(point2d, value::int_u8)* node)
- {
- typedef point2d P ;
- typedef value::int_u8 V;
-
- fllt_tree(P, V) subtree(node);
- fllt_branch_iter_ind(P, V) s(fllt_branch(P, V)(subtree, *node));
- for_all(s)
- data::fill(output | (*s).elt().points), (*s).elt().value);
- }
-
- void area_filter(image2d<value::int_u8>& output,
- fllt_node(point2d, value::int_u8)* node,
- unsigned min_area,
- unsigned max_area,
- value::int_u8 bg)
- {
- typedef point2d P ;
- typedef value::int_u8 V;
-
- data::fill(output, bg);
- fllt_tree(P, V) subtree(node);
- fllt_branch_iter_ind(P, V) s(fllt_branch(P, V)(subtree, *node));
- for_all(s)
- if ((*s).elt().nsites > min_area && (*s).elt().nsites < max_area)
- draw_shape(output, &*s);
- }
-
- void area_filter_min(image2d<value::int_u8>& output,
- fllt_node(point2d, value::int_u8)* node,
- unsigned min_area,
- value::int_u8 g,
- unsigned accu)
- {
-// if ((*node).elt().nsites >= min_area)
- if (accu > min_area)
- {
- accu = 0;
- g = (*node).elt().value;
- }
-
- accu += (*node).elt().nsites;
- data::fill(output | (*node).elt().points), g);
-
- for (int i = 0; i < node->children().size();i++)
- area_filter_min(output, node->children()[i], min_area, g, accu);
- }
-
- } // end of namespace mln::my
-
-} // end of namespace mln
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using namespace mln::my;
- using value::int_u8;
-
- typedef fllt_tree(point2d, int_u8) tree_type;
-
-
-
-// if (argc != 2)
-// {
-// std::cerr << "usage: " << argv[0] << " filename" << std::endl;
-// return 1;
-// }
-
- image2d<int_u8> lena;
- io::pgm::load(lena, argv[1]);
-
-
-// int vs[8][9] = { {0,0,0,0,0,0,0,0,0},
-// {0,0,0,0,0,0,0,0,0},
-// {0,1,1,1,1,1,1,1,0},
-// {0,1,0,0,1,3,3,1,0},
-// {0,1,0,0,1,3,4,1,0},
-// {0,1,0,0,1,3,3,1,0},
-// {0,1,1,1,1,1,1,1,0},
-// {0,0,0,0,0,0,0,0,0} };
-
-
-
-// int vs[8][9] = { {6,6,6,6,6,6,6,6,6},
-// {6,6,6,6,6,6,6,6,6},
-// {6,5,5,5,5,5,5,5,6},
-// {6,5,6,6,5,3,3,5,6},
-// {6,5,6,6,5,3,0,5,6},
-// {6,5,6,6,5,3,3,5,6},
-// {6,5,5,5,5,5,5,5,6},
-// {6,6,6,6,6,6,6,6,6} };
-
-// int vs[8][9] = { {2,2,2,2,2,2,2,2,2},
-// {2,2,2,2,2,2,2,2,2},
-// {2,1,1,1,1,1,1,1,2},
-// {2,1,2,2,1,0,0,1,2},
-// {2,1,2,2,1,0,0,1,2},
-// {2,1,2,2,1,0,0,1,2},
-// {2,1,1,1,1,1,1,1,2},
-// {2,2,2,2,2,2,2,2,2} };
-
-
- int vs[8][9] = { {2,2,2,2,2,2,2,2,2},
- {2,2,2,2,2,2,2,2,2},
- {2,1,1,1,1,1,1,1,2},
- {2,1,2,2,1,0,0,1,2},
- {2,1,2,2,1,0,4,1,2},
- {2,1,2,2,1,0,0,1,2},
- {2,1,1,1,1,1,1,1,2},
- {2,2,2,2,2,2,2,2,2} };
-
-// int vs[10][13] = { {1,1,1,1, 1,1,1,1, 1,1,1,1,1},
-// {1,2,2,2,2,2,2,2,2,2,2,2,1},
-// {1,2,2,2,2,2,2,2,2,2,2,2,1},
-// {1,2,2,2,3,3,3,3,3,3,3,2,1},
-// {1,2,2,2,3,3,3,2,2,2,3,2,1},
-// {1,2,2,2,3,4,3,2,4,4,3,2,1},
-
-// {1,2,2,2,3,3,3,2,2,2,3,2,1},
-// {1,2,2,2,3,3,3,3,3,3,3,2,1},
-// {1,2,2,2,2,2,2,2,2,2,2,2,1},
-// {1,1,1,1,1,1,1,1,1,1,1,1,1}};
-
-
-// image2d<int> lena_(make::image2d(vs));
-// image2d<int_u8> lena(lena_.domain());
-// data::fill(lena, lena_);
-
- tree_type tree = my::fllt(lena);
- compute_area(lena, tree);
-
- image2d<value::int_u8> output (lena.domain ());
-// area_filter_min(output, tree.root(), atoi(argv[2]), 0, 0);
- area_filter(output, tree.root(), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
- io::pgm::save(output, "out.pgm");
-
- // draw_tree(lena, tree);
-}
Index: geraud/fllt/connected_filters/area_filter.cc
--- geraud/fllt/connected_filters/area_filter.cc (revision 3151)
+++ geraud/fllt/connected_filters/area_filter.cc (working copy)
@@ -1,26 +0,0 @@
-#include "fllt.svg.7.hh"
-#include "fllt_tree_to_image.hh"
-#include "area_filter.hh"
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- typedef fllt_tree(point2d, int_u8) tree_type;
-
- if (argc != 4)
- {
- std::cerr << "usage: " << argv[0] << " input min_area output" << std::endl;
- return 1;
- }
-
- image2d<int_u8> ima;
- io::pgm::load(ima, argv[1]);
-
- tree_type tree = fllt(ima);
- compute_area(ima, tree);
-
- area_filter_min(tree.root(), atoi(argv[2]));
- io::pgm::save(fllt_tree_to_image(ima, tree), argv[3]);
-}
Index: geraud/fllt/connected_filters/canonize_tree.hh
--- geraud/fllt/connected_filters/canonize_tree.hh (revision 3151)
+++ geraud/fllt/connected_filters/canonize_tree.hh (working copy)
@@ -1,51 +0,0 @@
-#ifndef MLN_FLLT_CANONIZE_TREE_HH
-# define MLN_FLLT_CANONIZE_TREE_HH
-
-#include "fllt.svg.7.hh"
-#include "fllt_tree_to_image.hh"
-#include "area_filter.hh"
-
-namespace mln
-{
-
- template <typename P, typename V>
- void
- merge_node(fllt_node(P, V)* src, fllt_node(P, V)* dest)
- {
- for (typename std::vector<fllt_node(P, V)* >::iterator it = src->parent()->children().begin();
- it != src->parent()->children().end(); ++it)
- if ((*it) == src)
- {
- src->parent()->children().erase(it);
- break;
- }
-
- dest->elt().points.append(src->elt().points);
- while(!src->children().empty())
- dest->add_child(*src->children().begin());
- delete src;
- }
-
- template <typename P, typename V>
- bool
- canonize_tree(fllt_node(P, V)* node)
- {
- if (node->parent() && node->parent()->elt().value == node->elt().value)
- {
- merge_node(node, node->parent());
- return true;
- }
-
- bool change = true;
- while (change)
- {
- change = false;
- for (int i = 0; !change && i < node->children().size(); i++)
- change = canonize_tree(node->children()[i]);
- }
- return false;
- }
-
-}
-
-#endif // ! MLN_FLLT_CANONIZE_TREE_HH
Index: geraud/fllt/connected_filters/pseudo_flat_zones.cc
--- geraud/fllt/connected_filters/pseudo_flat_zones.cc (revision 3151)
+++ geraud/fllt/connected_filters/pseudo_flat_zones.cc (working copy)
@@ -1,44 +0,0 @@
-#include "fllt.svg.7.hh"
-#include "fllt_tree_to_image.hh"
-#include "area_filter.hh"
-#include "canonize_tree.hh"
-
-namespace mln
-{
- template <typename P, typename V>
- void flatten(fllt_node(P, V)* node,
- unsigned min_contrast)
- {
- for (int i = 0; i < node->children().size(); i++)
- {
- if (abs(node->children()[i]->elt().value - node->elt().value) < min_contrast)
- node->children()[i]->elt().value = node->elt().value;
- flatten(node->children()[i], min_contrast);
- }
- }
-}
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- typedef fllt_tree(point2d, int_u8) tree_type;
-
- if (argc != 5)
- {
- std::cerr << "usage: " << argv[0] << " input min_area min_contrast output" << std::endl;
- return 1;
- }
-
- image2d<int_u8> ima;
- io::pgm::load(ima, argv[1]);
-
- tree_type tree = fllt(ima);
- compute_area(ima, tree);
-
- area_filter_min(tree.root(), atoi(argv[2]));
- canonize_tree(tree.root());
- flatten(tree.root(), atoi(argv[3]));
- io::pgm::save(fllt_tree_to_image(ima, tree), argv[4]);
-}
Index: geraud/fllt/connected_filters/area_filter.hh
--- geraud/fllt/connected_filters/area_filter.hh (revision 3151)
+++ geraud/fllt/connected_filters/area_filter.hh (working copy)
@@ -1,69 +0,0 @@
-#ifndef MLN_FLLT_AREA_FILTER_HH
-# define MLN_FLLT_AREA_FILTER_HH
-
-#include "fllt.svg.7.hh"
-
-namespace mln
-{
-
- template <typename P, typename V, typename I>
- unsigned
- compute_area_rec(fllt_node(P, V)* node, I& ima)
- {
-
- if (!node)
- return 0;
-
- int area = 0;
-
- for (int i = 0; i < node->children().size();i++)
- area += compute_area_rec(node->children()[i], ima);
-
- mln_piter(p_array<P>) p(node->elt().points);
- for_all(p)
- if (!ima(P(p)))
- {
- ++area;
- ima(p) = true;
- }
-
- node->elt().nsites = area;
- return area;
- }
-
- template <typename P, typename V, typename I>
- void
- compute_area(const Image<I>& input_, fllt_tree(P, V)& tree)
- {
- const I& input = exact(input_);
-
- image2d<bool> ima(input.domain());
- data::fill(ima, false);
- compute_area_rec(tree.root(), ima);
- }
-
- void area_filter_min_(fllt_node(point2d, value::int_u8)* node,
- unsigned min_area,
- value::int_u8 g)
- {
- unsigned area = (*node).elt().nsites;
- if (area > min_area)
- g = (*node).elt().value;
-
- node->elt().value = g;
-
- for (int i = 0; i < node->children().size(); i++)
- area_filter_min_(node->children()[i], min_area, g);
- }
-
- template <typename P, typename V>
- void area_filter_min(fllt_node(P, V)* node,
- unsigned min_area)
- {
- area_filter_min_(node, min_area, (*node).elt().value);
- }
-
-}
-
-
-#endif // ! MLN_FLLT_AREA_FILTER_HH
Index: geraud/fllt/fllt_test.hh
--- geraud/fllt/fllt_test.hh (revision 3151)
+++ geraud/fllt/fllt_test.hh (working copy)
@@ -1,874 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <iomanip>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-#include <mln/core/image/sub_image.hh>
-#include <mln/core/site_set/p_queue_fast.hh>
-#include <mln/core/image/cast_image.hh>
-
-#include <mln/opt/at.hh>
-
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/level/compare.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/labeling/regional_maxima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-#include <mln/pw/all.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/util/tree.hh>
-#include <mln/util/branch_iter_ind.hh>
-#include <mln/util/branch_iter.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
-# define fllt_tree(P, V) mln::util::tree< fllt_node_elt<P, V> >
-# define fllt_node(P, V) mln::util::tree_node< fllt_node_elt<P, V> >
-# define fllt_tree_ptr(P, V) mln::util::tree< fllt_node_elt<P, V>* >
-# define fllt_node_ptr(P, V) mln::util::tree_node< fllt_node_elt<P, V>* >
-# define fllt_branch(P, V) mln::util::branch< fllt_node_elt<P, V> >
-# define fllt_branch_iter_ind(P, V) mln::util::branch_iter_ind< fllt_node_elt<P, V> >
-# define fllt_branch_iter(P, V) mln::util::branch_iter< fllt_node_elt<P, V> >
-
-# define stl_to_mln_iter(T) stl_iterator< T >
-
- //Fwd declarations.
- template <typename V> struct lower;
- template <typename V> struct upper;
-
- template <typename P, typename V>
- struct fllt_node_elt
- {
- V value;
- p_array<P> points;
- p_array<P> holes;
- std::vector<fllt_node(P, V)*> hole_shapes;
- /// Tell if his parent if brighter or not. Nb : if the parent
- /// if brighter, the node come from the lower level set
- bool brighter;
- unsigned nsites;
- bool tagged;
- bool set_id;
- char id;
-
- fllt_node_elt(bool set_id) : nsites(0), tagged(false), set_id(set_id)
- {
- static char id_ = 'A';
-
- id = id_;
- id_++;
- }
- };
-
-
- template <typename C>
- class stl_iterator
- {
- public:
- stl_iterator(C& c) : container_(c) {}
- void start(){ it_ = container_.begin(); }
- void next() { it_++; }
- bool is_valid() const{ return it_ != container_.end(); }
- typename C::value_type& operator*() { return *it_; }
-
- private:
- C& container_;
- typename C::iterator it_;
- };
-
- template <typename N_t, typename G, typename Set>
- void update_gN(const N_t& N, G& gN);
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, lower<V>)
- {
- for (unsigned g = 0; g < 256; ++g)
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, upper<V>)
- {
- for (int g = 255; g >= 0; --g)
- {
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- }
- // if N is empty, gN is the min value.
- gN = 0;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- {
- if (N[i]->nsites() == 0)
- continue;
- std::cout << i << ": " << *N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- N[i]->clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- opt::at(output, row, col) = opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- template <typename P>
- void save_u(const image2d<value::int_u8>& u,
- const image2d<int>& is,
- box2d R_box,
- int in_R,
- int in_N,
- p_array<P>* N[256])
- {
- static int id = 0;
- std::stringstream filename;
- filename << "fllt_trace_" << std::setw(5) << std::setfill('0')
- << std::right << id++ << ".ppm";
-
- image2d<value::int_u8> out = duplicate(cast_image<value::int_u8>(is));
-
-
- mln_assertion(R_box.nsites() > 0);
- mln_piter_(box2d) p(R_box);
- for_all(p)
- if (is(p) == in_R)
- out(p) = 255;
- else if (is(p) == in_N)
- out(p) = 100;
- // else if (is(p) == in_N)
- // out(p) = literal::green;
-
- for (unsigned i = 0; i < 256; ++i)
- {
- mln_piter(p_array<P>) p(*N[i]);
- for_all(p)
- out(p) = 100;
- }
- io::pgm::save(out, filename.str());
- //io::pgm::save(out, filename.str());
- }
-
- template <typename I>
- void save(const I& is, unsigned in_N, unsigned in_R, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- if (is(p) == in_R)
- temp(p) = literal::red;
- else if (is(p) == in_N) // N
- temp(p) = literal::green;
- else if (is(p) < in_N)
- temp(p) = literal::blue;
- else
- temp(p) = literal::white;
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
- template <typename I, typename P, typename V, typename Set>
- void blob(const Set&,
- const I& is,
- p_array<mln_point(I)>* N[256],
- unsigned in_N,
- const box2d& N_box,
- fllt_node(P, V)* current_cc)
- {
- typedef p_array<mln_point(I)> arr_t;
-
- // std::cout << ">>>>>>>enter blob. " << current_cc << std::endl;
- bool flower = true;
- unsigned ncc = 0;
- static image2d<unsigned> is_labeled(is.domain());
- static unsigned label = 0;
-
- if (label == 0)
- {
- data::fill(is_labeled, 0);
- label++;
- }
-
- P cur;
- mln_niter(neighb2d) n(Set::bdr_nbh(), cur);
- p_queue_fast<P> qu;
- p_array<P>& holes = current_cc->elt().holes;
-
- mln_piter(I) p(N_box);
- for_all(p)
- if (is(p) == in_N)
- break;
-
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
-
-
-
- for (unsigned i = 0; i < 256; ++i)
- //for (int i = 255; i >= 0; --i)
- {
- mln_piter(arr_t) p(*N[i]);
- for_all(p)
- {
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
- }
- }
-
- ++label;
-
- // if (holes.size() == 2)
- // std::cout << holes[0] << holes[1] << std::endl;
- // std::cout << " <<<<<<<exiting blob." << std::endl;
- }
-
- template <typename P, typename V>
- void
- move_A_to_R(p_array<P>& A,
- image2d<int>& deja_vu,
- fllt_node(P, V)* current_cc,
- image2d< fllt_node(P, V)* >& smallest_shapes,
- int in_R,
- int in_N,
- const V& g,
- unsigned& n_comps)
- {
- typedef p_array<P> arr_t;
-
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- mln_invariant(deja_vu(a) == in_N);
- mln_invariant(smallest_shapes(a) != current_cc);
- // if (smallest_shapes(a) == current_cc)
- // continue;
-
- deja_vu(a) = in_R;
- if (!smallest_shapes(a))
- {
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- if (!smallest_shapes(a)->parent())
- if (smallest_shapes(a)->elt().value == g)
- {
- fllt_node(P, V)* to_delete = smallest_shapes(a);
-
- // current_cc->elt().points.append(smallest_shapes(a)->elt().points);
- // A.append(smallest_shapes(a)->elt().points);
-
- mln_piter(arr_t) p(smallest_shapes(a)->elt().points);
- // Todo optimization here.
- for_all(p)
- {
- smallest_shapes(p) = 0;
- // deja_vu(p) = in_R;
- //smallest_shapes(p) = current_cc;
- }
-
- while(!to_delete->children().empty())
- current_cc->add_child(*to_delete->children().begin());
- delete to_delete;
- n_comps--;
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- smallest_shapes(a)->set_parent(current_cc);
- }
- }
-
- // LOWER LEVEL SET : region = c4, border = c8
- template <typename V>
- struct lower
- {
- typedef upper<V> opposite;
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- {
- return u < v;
- }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- {
- return labeling::regional_minima(input, nbh, nlabels);
- }
-
- static const bool parent_is_brighter = true;
- static const bool id = false;
-
- static const neighb2d& bdr_nbh() { return c8(); }
- static const neighb2d& reg_nbh() { return c4(); }
- };
-
-
- // UPPER LEVEL SET : region = c8, border = c4
- template <typename V>
- struct upper
- {
- typedef lower<V> opposite;
-
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- { return u > v; }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- { return labeling::regional_maxima(input, nbh, nlabels); }
-
- static const bool parent_is_brighter = false;
- static const bool id = true;
-
- static const neighb2d& bdr_nbh() { return c4(); }
- static const neighb2d& reg_nbh() { return c8(); }
- };
-
-
- template <typename P, typename V, typename I>
- void print_child_parent(fllt_node(P, V)* child,
- fllt_node(P, V)* parent,
- const I& input)
- {
- typedef fllt_tree(P, V) tree_type;
-
- std::cout << "child : " << child->elt().id
- << " parent : " << parent->elt().id << std::endl;
- p_array<P> tmp;
-
- image2d<bool> ima(input.domain().to_larger(1));
- data::fill(ima, false);
-
- fllt_branch_iter(P, V) n(*child);
- for_all(n)
- data::fill((ima | (*n).elt().points).rw(), true);
-
- tmp.append((*n).elt().points);
-
- debug::println(ima);
- }
-
- template <typename I, typename Set>
- fllt_tree(mln_point(I), mln_value(I))&
- level_set(const Image<I>& input_,
- image2d< fllt_node(mln_point(I), mln_value(I))* >& smallest_shapes)
- {
-
- typedef mln_point(I) P;
- typedef mln_value(I) V;
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
-
- const I& input = exact(input_);
-
- mln_assertion(input.domain() == smallest_shapes.domain());
-
- unsigned l = 0, l_max = 0;
- mln_ch_value(I, unsigned) reg_min = Set::regional_extremum(input, Set::reg_nbh(), l_max);
- std::vector<bool> tag(l_max + 1, false);
- tag[0] = true;
-
- // Variables.
- I u = mln::duplicate(input);
- P x0;
- V g, gN;
- mln_fwd_piter(I) p(input.domain());
- p.start();
- data::fill(smallest_shapes, 0);
- node_type* current_cc;
-
- unsigned in_N = 1, in_R = 2;
-
- image2d<int> deja_vu(input.domain().to_larger(1));
- data::fill(deja_vu, 0);
-
- typedef p_array<P> arr_t;
- arr_t* A = new arr_t();
- arr_t* N[256];
- for (unsigned i = 0; i < 256; ++i)
- N[i] = new arr_t();
- accu::bbox<P> N_box;
-
- bool touch_border_of_image = false;
- unsigned n_step_1 = 0, n_step_3 = 0, n_step_4c = 0, n_comps = 0, n_holes = 0;
-
- // Step 1.
- step_1:
- {
- while (tag[reg_min(p)] && p.is_valid())
- p.next();
- if (p.is_valid())
- tag[reg_min(p)] = true; // To be processed.
- else
- goto the_end;
-
- ++n_step_1;
- x0 = p;
- g = input(x0);
- ++n_comps;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- touch_border_of_image = false;
-
- }
-
- // Step 2.
- step_2:
- {
- in_N += 2;
- in_R = in_N + 1;
- // R <- 0 and N <- 0
- clear_N(N);
- N_box.init();
-
- // A <- { x0 }
- A->clear();
- A->append(x0);
- N_box.take(x0);
-
- deja_vu(x0) = in_R;
- smallest_shapes(x0) = current_cc;
- current_cc->elt().points.append(x0);
- current_cc->elt().nsites++;
-
- }
-
- // Step 3.
- step_3:
- {
- ++n_step_3;
-
- mln_piter(arr_t) a(*A);
- mln_niter(neighb2d) x(Set::reg_nbh(), a);
-
-
- // R <- R U A
- if (A->nsites() == 0)
- goto the_end;
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- {
- if (deja_vu.has(x) && deja_vu(x) < in_N)
- {
- if (u.has(x))
- {
- N[u(x)]->append(x);
- N_box.take(x);
- }
- else
- touch_border_of_image = true;
- deja_vu(x) = in_N;
- }
- }
- // gN = min u(x) for all x in N
- update_gN(N, gN, Set());
- save_u(u, deja_vu, N_box, in_R, in_N, N);
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (Set::compare(g, gN))
- {
- g = gN;
-
- ++n_comps;
-
- if (touch_border_of_image)
- blob(Set(), deja_vu, N, in_N, N_box.to_result().to_larger(1), current_cc);
- else
- blob(Set(), deja_vu, N, in_N, N_box, current_cc);
-
- n_holes += current_cc->elt().holes.nsites();
-
- node_type* child = current_cc;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- child->set_parent(current_cc);
-
- print_child_parent(child, current_cc, input);
-
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // c)
- else
- {
- // FIXME: IDEA: this change might be performed while R is constructed(?)
- n_step_4c++;
- mln_piter(I) r(N_box);
- for_all(r)
- if (deja_vu(r) == in_R)
- u(r) = g;
-
- goto step_1;
- }
- }
-
- the_end:
- std::cout << " n_step1 : " << n_step_1 << " n_step3 : " << n_step_3 << " n_step4c : " << n_step_4c << std::endl;
- std::cout << "n comps = " << n_comps << " n holes = " << n_holes << std::endl;
-
- return *new tree_type(current_cc);
- }
-
- // F is the set in which we get the node.
- template <typename P, typename V, typename F>
- fllt_node(P, V)*
- find_hole(fllt_node(P, V)& node,
- const P p,
- const image2d<fllt_node(P, V)*>& other_reg)
- {
- fllt_node(P, V)* s = other_reg(p);
- mln_assertion(s);
- while (s->parent() && F::compare(s->parent()->elt().value, node.elt().value))
- {
- mln_assertion(s);
- s = s->parent();
- mln_assertion(s);
- }
- // std::cout << " [Find the hole] of " << p
- // << " from " << &node
- // << " return " << s
- // << std::endl;
- return s;
- }
-
- template <typename P, typename V>
- bool shape_is_included(fllt_node(P, V)* A,
- fllt_node(P, V)* B)
- {
- return A->parent() == B || A == B;
- }
-
- template <typename P, typename V>
- void find_all_holes(fllt_tree(P, V)& lower_tree,
- fllt_tree(P, V)& upper_tree,
- const image2d<fllt_node(P, V)*>& low_reg,
- const image2d<fllt_node(P, V)*>& upp_reg)
- {
- typedef p_array<P> arr_t;
- typedef fllt_node(P, V) node_type;
-
- {
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,upper<V> >(node, P(hole), upp_reg));
- }
- }
-
- {
- fllt_branch_iter_ind(P, V) node_(upper_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,lower<V> >(node, P(hole), low_reg));
- }
- }
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- merge_trees(fllt_tree(mln_point(I), mln_value(I))& lower_tree,
- fllt_tree(mln_point(I), mln_value(I))& upper_tree,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& low_reg,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& upp_reg,
- const Image<I>& input_)
- {
-
- const I& input = exact(input_);
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
- typedef p_array<P> arr_t;
-
-
- find_all_holes(lower_tree, upper_tree, low_reg, upp_reg);
- std::vector<node_type*> to_fill;
-
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != lower<V>::id)
- continue;
-
- // std::cout << "Fill " << &node << std::endl;
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- // std::cout << "hole : " << hole << " " << hole->elt().points << " " << std::endl;
- // std::cout << "child hole : " << child_hole << " " << child_hole->elt().points << std::endl;
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
- if (!child_has_bigger_hole)
- {
- // // std::cout << "move " << hole << " as child of " << &node << std::endl;
- node.add_child(hole);
- to_fill.push_back(hole);
- }
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- for(typename std::vector<node_type*>::iterator node_ = to_fill.begin();
- node_ != to_fill.end();
- node_++)
- {
- node_type& node = **node_;
-
- fllt_branch_iter_ind(P, V) node_(fllt_branch(P, V)(upper_tree, node));
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != upper<V>::id)
- continue;
-
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- //if (hole->elt().points <= child_hole->elt().points)
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
-
- if (!child_has_bigger_hole)
- node.add_child(hole);
-
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- }
-
- return lower_tree;
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- fllt(const Image<I>& input_)
- {
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- const I& input = exact(input_);
-
- fllt_tree(P, V) upper_tree;
- fllt_tree(P, V) lower_tree;
- image2d<fllt_node(P, V)*> low_reg(input.domain());
- image2d<fllt_node(P, V)*> upp_reg(input.domain());
-
- std::cout << "1/ Compute the lower level set.----------------------------------------" << std::endl;
- lower_tree = level_set<I, lower<V> >(input, low_reg);
-
- std::cout << "2/ Compute the upper level set.----------------------------------------" << std::endl;
- upper_tree = level_set<I, upper<V> >(input, upp_reg);
-
- std::cout << "3/ Merge.---------------------------------------------------------------" << std::endl;
- fllt_tree(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, input);
-
- return result_tree;
- }
-
-} // end of namespace mln
Index: geraud/fllt.svg.7.hh
--- geraud/fllt.svg.7.hh (revision 3151)
+++ geraud/fllt.svg.7.hh (working copy)
@@ -1,838 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_FLLT_HH
-# define MLN_FLLT_HH
-
-#include <iomanip>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/image_if_value.hh>
-#include <mln/core/image/sub_image.hh>
-#include <mln/core/site_set/p_queue_fast.hh>
-#include <mln/core/image/cast_image.hh>
-
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/level/compare.hh>
-#include <mln/debug/println.hh>
-#include <mln/labeling/regional_minima.hh>
-#include <mln/labeling/regional_maxima.hh>
-#include <mln/accu/bbox.hh>
-#include <mln/geom/bbox.hh>
-#include <mln/pw/all.hh>
-
-#include <mln/literal/black.hh>
-#include <mln/literal/white.hh>
-#include <mln/literal/colors.hh>
-
-#include <mln/util/tree.hh>
-#include <mln/util/branch_iter_ind.hh>
-#include <mln/util/branch_iter.hh>
-#include <mln/opt/at.hh>
-
-#include <sstream>
-
-
-namespace mln
-{
-
-# define fllt_tree(P, V) mln::util::tree< fllt_node_elt<P, V> >
-# define fllt_node(P, V) mln::util::tree_node< fllt_node_elt<P, V> >
-# define fllt_tree_ptr(P, V) mln::util::tree< fllt_node_elt<P, V>* >
-# define fllt_node_ptr(P, V) mln::util::tree_node< fllt_node_elt<P, V>* >
-# define fllt_branch(P, V) mln::util::branch< fllt_node_elt<P, V> >
-# define fllt_branch_iter_ind(P, V) mln::util::branch_iter_ind< fllt_node_elt<P, V> >
-# define fllt_branch_iter(P, V) mln::util::branch_iter< fllt_node_elt<P, V> >
-
-# define stl_to_mln_iter(T) stl_iterator< T >
-
- //Fwd declarations.
- template <typename V> struct lower;
- template <typename V> struct upper;
-
- template <typename P, typename V>
- struct fllt_node_elt
- {
- V value;
- p_array<P> points;
- p_array<P> holes;
- std::vector<fllt_node(P, V)*> hole_shapes;
- /// Tell if his parent if brighter or not. Nb : if the parent
- /// if brighter, the node come from the lower level set
- bool brighter;
- unsigned nsites;
- bool tagged;
- bool set_id;
-
- fllt_node_elt(bool set_id) : nsites(0), tagged(false), set_id(set_id) {}
- };
-
-
- template <typename C>
- class stl_iterator
- {
- public:
- stl_iterator(C& c) : container_(c) {}
- void start(){ it_ = container_.begin(); }
- void next() { it_++; }
- bool is_valid() const{ return it_ != container_.end(); }
- typename C::value_type& operator*() { return *it_; }
-
- private:
- C& container_;
- typename C::iterator it_;
- };
-
- template <typename N_t, typename G, typename Set>
- void update_gN(const N_t& N, G& gN);
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, lower<V>)
- {
- for (unsigned g = 0; g < 256; ++g)
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- // if N is empty, gN is the max value.
- gN = 255;
- }
-
- template <typename N_t, typename G, typename V>
- void update_gN(const N_t& N, G& gN, upper<V>)
- {
- for (int g = 255; g >= 0; --g)
- {
- if (N[g]->nsites() != 0)
- {
- gN = g;
- return;
- }
- }
- // if N is empty, gN is the min value.
- gN = 0;
- }
-
-
- template <typename N_t>
- void print_N(const N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- {
- if (N[i]->nsites() == 0)
- continue;
- std::cout << i << ": " << *N[i] << std::endl;
- }
- }
-
- template <typename N_t>
- void clear_N(N_t& N)
- {
- for (unsigned i = 0; i < 256; ++i)
- N[i]->clear();
- }
-
-
-
- template <typename T>
- image2d<T> enlarge(const image2d<T>& input, unsigned coef)
- {
- unsigned
- nrows_ = coef * geom::nrows(input),
- ncols_ = coef * geom::ncols(input);
- image2d<T> output(nrows_, ncols_);
- for (int row = 0; row < nrows_; ++row)
- for (int col = 0; col < ncols_; ++col)
- opt::at(output, row, col) = opt::at(input, row / coef, col / coef);
- return output;
- }
-
-
- void save_u(const image2d<value::int_u8>& u,
- const image2d<int>& is,
- box2d R_box,
- int in_R,
- int in_N)
- {
- static int id = 0;
- std::stringstream filename;
- filename << "fllt_trace_" << std::setw(5) << std::setfill('0')
- << std::right << id++ << ".ppm";
-
- image2d<value::int_u8> out = duplicate(cast_image<value::int_u8>(is));
-
- mln_assertion(R_box.nsites() > 0);
- mln_piter_(box2d) p(R_box);
- for_all(p)
- if (is(p) == in_R)
- out(p) = 255;
- else if (is(p) == in_N)
- out(p) = 127;
- // else if (is(p) == in_N)
- // out(p) = literal::green;
-
- io::pgm::save(out, filename.str());
- //io::pgm::save(out, filename.str());
- }
-
- template <typename I>
- void save(const I& is, unsigned in_N, unsigned in_R, const std::string& name = "")
- {
- static unsigned counter = 0;
- using value::rgb8;
-
- image2d<rgb8> temp(is.domain());
- data::fill(temp, literal::black);
-
- mln_piter(I) p(is.domain());
- for_all(p)
- if (is(p) == in_R)
- temp(p) = literal::red;
- else if (is(p) == in_N) // N
- temp(p) = literal::green;
- else if (is(p) < in_N)
- temp(p) = literal::blue;
- else
- temp(p) = literal::white;
-
- if (name == "")
- {
- std::stringstream filename;
- filename << "./temp_" << ++counter << ".ppm";
- io::ppm::save(enlarge(temp, 10), filename.str());
- }
- else
- io::ppm::save(temp, name);
- }
-
-
- template <typename I, typename P, typename V, typename Set>
- void blob(const Set&,
- const I& is,
- p_array<mln_point(I)>* N[256],
- unsigned in_N,
- const box2d& N_box,
- fllt_node(P, V)* current_cc)
- {
- typedef p_array<mln_point(I)> arr_t;
-
- // std::cout << ">>>>>>>enter blob. " << current_cc << std::endl;
- bool flower = true;
- unsigned ncc = 0;
- static image2d<unsigned> is_labeled(is.domain());
- static unsigned label = 0;
-
- if (label == 0)
- {
- data::fill(is_labeled, 0);
- label++;
- }
-
- P cur;
- mln_niter(neighb2d) n(Set::bdr_nbh(), cur);
- p_queue_fast<P> qu;
- p_array<P>& holes = current_cc->elt().holes;
-
- mln_piter(I) p(N_box);
- for_all(p)
- if (is(p) == in_N)
- break;
-
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
-
-
-
- for (unsigned i = 0; i < 256; ++i)
- //for (int i = 255; i >= 0; --i)
- {
- mln_piter(arr_t) p(*N[i]);
- for_all(p)
- {
- mln_assertion(is(p) == in_N);
- if (is_labeled(p) != label)
- {
- if (flower == false)
- holes.append(p);
- else
- flower = false;
- qu.push(p);
- is_labeled(p) = label;
- do
- {
- cur = qu.front();
- qu.pop();
- for_all(n) if (is.has(n))
- if (is(n) == in_N && is_labeled(n) != label)
- {
- qu.push(n);
- is_labeled(n) = label;
- }
- }
- while (! qu.is_empty());
- }
- }
- }
-
- ++label;
-
- // if (holes.size() == 2)
- // std::cout << holes[0] << holes[1] << std::endl;
- // std::cout << " <<<<<<<exiting blob." << std::endl;
- }
-
- template <typename P, typename V>
- void
- move_A_to_R(p_array<P>& A,
- image2d<int>& deja_vu,
- fllt_node(P, V)* current_cc,
- image2d< fllt_node(P, V)* >& smallest_shapes,
- int in_R,
- int in_N,
- const V& g,
- unsigned& n_comps)
- {
- typedef p_array<P> arr_t;
-
- mln_piter(arr_t) a(A);
- for_all(a)
- {
- mln_invariant(deja_vu(a) == in_N);
- mln_invariant(smallest_shapes(a) != current_cc);
- // if (smallest_shapes(a) == current_cc)
- // continue;
-
- deja_vu(a) = in_R;
- if (!smallest_shapes(a))
- {
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- if (!smallest_shapes(a)->parent())
- if (smallest_shapes(a)->elt().value == g)
- {
- fllt_node(P, V)* to_delete = smallest_shapes(a);
-
- // current_cc->elt().points.append(smallest_shapes(a)->elt().points);
- // A.append(smallest_shapes(a)->elt().points);
-
- mln_piter(arr_t) p(smallest_shapes(a)->elt().points);
- // Todo optimization here.
- for_all(p)
- {
- smallest_shapes(p) = 0;
- // deja_vu(p) = in_R;
- //smallest_shapes(p) = current_cc;
- }
-
- while(!to_delete->children().empty())
- current_cc->add_child(*to_delete->children().begin());
- delete to_delete;
- n_comps--;
- smallest_shapes(a) = current_cc;
- current_cc->elt().points.append(a);
- }
- else
- smallest_shapes(a)->set_parent(current_cc);
- }
- }
-
- // LOWER LEVEL SET : region = c4, border = c8
- template <typename V>
- struct lower
- {
- typedef upper<V> opposite;
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- {
- return u < v;
- }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- {
- return labeling::regional_minima(input, nbh, nlabels);
- }
-
- static const bool parent_is_brighter = true;
- static const bool id = false;
-
- static const neighb2d& bdr_nbh() { return c8(); }
- static const neighb2d& reg_nbh() { return c4(); }
- };
-
-
- // UPPER LEVEL SET : region = c8, border = c4
- template <typename V>
- struct upper
- {
- typedef lower<V> opposite;
-
- // If compare(u,v) u root <- v <- u
- // else root <- u <- v
- static bool
- compare(const V& u, const V& v)
- { return u > v; }
-
- template <typename I, typename N, typename L>
- static mln_ch_value(I, L)
- regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels)
- { return labeling::regional_maxima(input, nbh, nlabels); }
-
- static const bool parent_is_brighter = false;
- static const bool id = true;
-
- static const neighb2d& bdr_nbh() { return c4(); }
- static const neighb2d& reg_nbh() { return c8(); }
- };
-
- template <typename I, typename Set>
- fllt_tree(mln_point(I), mln_value(I))&
- level_set(const Image<I>& input_,
- image2d< fllt_node(mln_point(I), mln_value(I))* >& smallest_shapes)
- {
-
- typedef mln_point(I) P;
- typedef mln_value(I) V;
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
-
- const I& input = exact(input_);
-
- mln_assertion(input.domain() == smallest_shapes.domain());
-
- unsigned l = 0, l_max = 0;
- mln_ch_value(I, unsigned) reg_min = Set::regional_extremum(input, Set::reg_nbh(), l_max);
- std::vector<bool> tag(l_max + 1, false);
- tag[0] = true;
-
- // Variables.
- I u = mln::duplicate(input);
- P x0;
- V g, gN;
- mln_fwd_piter(I) p(input.domain());
- p.start();
- data::fill(smallest_shapes, 0);
- node_type* current_cc;
-
- unsigned in_N = 1, in_R = 2;
-
- image2d<int> deja_vu(input.domain().to_larger(1));
- data::fill(deja_vu, 0);
-
- typedef p_array<P> arr_t;
- arr_t* A = new arr_t();
- arr_t* N[256];
- for (unsigned i = 0; i < 256; ++i)
- N[i] = new arr_t();
- accu::bbox<P> N_box;
-
- bool touch_border_of_image = false;
- unsigned n_step_1 = 0, n_step_3 = 0, n_step_4c = 0, n_comps = 0, n_holes = 0;
-
- // Step 1.
- step_1:
- {
- while (tag[reg_min(p)] && p.is_valid())
- p.next();
- if (p.is_valid())
- tag[reg_min(p)] = true; // To be processed.
- else
- goto the_end;
-
- ++n_step_1;
- x0 = p;
- g = input(x0);
- ++n_comps;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- touch_border_of_image = false;
-
- }
-
- // Step 2.
- step_2:
- {
- in_N += 2;
- in_R = in_N + 1;
- // R <- 0 and N <- 0
- clear_N(N);
- N_box.init();
-
- // A <- { x0 }
- A->clear();
- A->append(x0);
- N_box.take(x0);
-
- deja_vu(x0) = in_R;
- smallest_shapes(x0) = current_cc;
- current_cc->elt().points.append(x0);
- current_cc->elt().nsites++;
-
- }
-
- // Step 3.
- step_3:
- {
- // save_u(u, deja_vu, N_box, in_R, in_N);
- ++n_step_3;
-
- mln_piter(arr_t) a(*A);
- mln_niter(neighb2d) x(Set::reg_nbh(), a);
-
-
- // R <- R U A
- if (A->nsites() == 0)
- goto the_end;
-
- // N <- N U { x in nbh of A and not in R }
- for_all(a)
- for_all(x)
- {
- if (deja_vu.has(x) && deja_vu(x) < in_N)
- {
- if (u.has(x))
- {
- N[u(x)]->append(x);
- N_box.take(x);
- }
- else
- touch_border_of_image = true;
- deja_vu(x) = in_N;
- }
- }
- // gN = min u(x) for all x in N
- update_gN(N, gN, Set());
-
- // FIXME: update the number of CC of the border of R
- }
-
- // Step 4.
- step_4:
- {
- // a)
- if (Set::compare(g, gN))
- {
- g = gN;
-
- ++n_comps;
-
- if (touch_border_of_image)
- blob(Set(), deja_vu, N, in_N, N_box.to_result().to_larger(1), current_cc);
- else
- blob(Set(), deja_vu, N, in_N, N_box, current_cc);
-
- n_holes += current_cc->elt().holes.nsites();
-
- node_type* child = current_cc;
- current_cc = new node_type(Set::id);
- current_cc->elt().value = g;
- child->set_parent(current_cc);
-
-
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // b)
- else if (g == gN)
- {
- arr_t* tmp = A;
- A = N[g];
- N[g] = tmp;
- N[g]->clear();
- move_A_to_R(*A, deja_vu, current_cc, smallest_shapes, in_R, in_N, g, n_comps);
- goto step_3;
- }
- // c)
- else
- {
- // FIXME: IDEA: this change might be performed while R is constructed(?)
- n_step_4c++;
- mln_piter(I) r(N_box);
- for_all(r)
- if (deja_vu(r) == in_R)
- u(r) = g;
-
- goto step_1;
- }
- }
-
- the_end:
- std::cout << " n_step1 : " << n_step_1 << " n_step3 : " << n_step_3 << " n_step4c : " << n_step_4c << std::endl;
- std::cout << "n comps = " << n_comps << " n holes = " << n_holes << std::endl;
-
- return *new tree_type(current_cc);
- }
-
- // F is the set in which we get the node.
- template <typename P, typename V, typename F>
- fllt_node(P, V)*
- find_hole(fllt_node(P, V)& node,
- const P p,
- const image2d<fllt_node(P, V)*>& other_reg)
- {
- fllt_node(P, V)* s = other_reg(p);
- mln_assertion(s);
- while (s->parent() && F::compare(s->parent()->elt().value, node.elt().value))
- {
- mln_assertion(s);
- s = s->parent();
- mln_assertion(s);
- }
- // std::cout << " [Find the hole] of " << p
- // << " from " << &node
- // << " return " << s
- // << std::endl;
- return s;
- }
-
- template <typename P, typename V>
- bool shape_is_included(fllt_node(P, V)* A,
- fllt_node(P, V)* B)
- {
- return A->parent() == B || A == B;
- }
-
- template <typename P, typename V>
- void find_all_holes(fllt_tree(P, V)& lower_tree,
- fllt_tree(P, V)& upper_tree,
- const image2d<fllt_node(P, V)*>& low_reg,
- const image2d<fllt_node(P, V)*>& upp_reg)
- {
- typedef p_array<P> arr_t;
- typedef fllt_node(P, V) node_type;
-
- {
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,upper<V> >(node, P(hole), upp_reg));
- }
- }
-
- {
- fllt_branch_iter_ind(P, V) node_(upper_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- mln_piter(arr_t) hole(node.elt().holes);
- for_all(hole)
- node.elt().hole_shapes.push_back(find_hole<P,V,lower<V> >(node, P(hole), low_reg));
- }
- }
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- merge_trees(fllt_tree(mln_point(I), mln_value(I))& lower_tree,
- fllt_tree(mln_point(I), mln_value(I))& upper_tree,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& low_reg,
- const image2d<fllt_node(mln_point(I), mln_value(I))*>& upp_reg,
- const Image<I>& input_)
- {
-
- const I& input = exact(input_);
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- typedef fllt_node(P, V) node_type;
- typedef fllt_tree(P, V) tree_type;
- typedef p_array<P> arr_t;
-
-
- find_all_holes(lower_tree, upper_tree, low_reg, upp_reg);
- std::vector<node_type*> to_fill;
-
- fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != lower<V>::id)
- continue;
-
- // std::cout << "Fill " << &node << std::endl;
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- // std::cout << "hole : " << hole << " " << hole->elt().points << " " << std::endl;
- // std::cout << "child hole : " << child_hole << " " << child_hole->elt().points << std::endl;
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
- if (!child_has_bigger_hole)
- {
- // // std::cout << "move " << hole << " as child of " << &node << std::endl;
- node.add_child(hole);
- to_fill.push_back(hole);
- }
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- for(typename std::vector<node_type*>::iterator node_ = to_fill.begin();
- node_ != to_fill.end();
- node_++)
- {
- node_type& node = **node_;
-
- fllt_branch_iter_ind(P, V) node_(fllt_branch(P, V)(upper_tree, node));
- for_all(node_)
- {
- node_type& node = *node_;
- if (node.elt().set_id != upper<V>::id)
- continue;
-
- typename std::vector<fllt_node(P, V)*>::iterator hole_;
- for (hole_ = node.elt().hole_shapes.begin();
- hole_ != node.elt().hole_shapes.end();
- hole_++)
- {
- fllt_node(P, V)* hole = *hole_;
-
- bool child_has_bigger_hole = false;
- typename fllt_node(P, V)::children_t::iterator it;
- for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
- {
- // Browse the holes of each child.
- typename std::vector<fllt_node(P, V)*>::iterator child_hole_;
- for (child_hole_ = (*it)->elt().hole_shapes.begin();
- child_hole_ != (*it)->elt().hole_shapes.end();
- child_hole_++)
- {
- fllt_node(P, V)* child_hole = *child_hole_;
- //if (hole->elt().points <= child_hole->elt().points)
- if (shape_is_included(hole, child_hole))
- {
- child_has_bigger_hole = true;
- break;
- }
- } // end of browsing child's holes.
- } // end of browsing childs.
-
- if (!child_has_bigger_hole)
- node.add_child(hole);
-
- } // end of browsing holes of node.
- node.elt().holes.clear();
- } // end of browsing lower_tree.
-
- }
-
- return lower_tree;
- }
-
- template <typename I>
- fllt_tree(mln_point(I), mln_value(I))
- fllt(const Image<I>& input_)
- {
- typedef mln_point(I) P;
- typedef mln_value(I) V;
-
- const I& input = exact(input_);
-
- fllt_tree(P, V) upper_tree;
- fllt_tree(P, V) lower_tree;
- image2d<fllt_node(P, V)*> low_reg(input.domain());
- image2d<fllt_node(P, V)*> upp_reg(input.domain());
-
- std::cout << "1/ Compute the lower level set.----------------------------------------" << std::endl;
- lower_tree = level_set<I, lower<V> >(input, low_reg);
-
- std::cout << "2/ Compute the upper level set.----------------------------------------" << std::endl;
- upper_tree = level_set<I, upper<V> >(input, upp_reg);
-
- std::cout << "3/ Merge.---------------------------------------------------------------" << std::endl;
- fllt_tree(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, input);
-
- return result_tree;
- }
-
-} // end of namespace mln
-
-#endif // ! MLN_FLLT_HH
Index: geraud/win_fun.hh
--- geraud/win_fun.hh (revision 3151)
+++ geraud/win_fun.hh (working copy)
@@ -1,160 +0,0 @@
-// Copyright (C) 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 infun 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 MLN_WIN_FUN_HH
-# define MLN_WIN_FUN_HH
-
-/*! \file mln/win/fun.hh
- *
- * \brief Definition of the mln::win::fun window.
- */
-
-# include <mln/core/internal/window_base.hh>
-# include <mln/core/internal/site_relative_iterator_base.hh>
-
-
-namespace mln
-{
-
- namespace win
- {
-
- // Fwd decl.
- template <typename F> class fun_piter;
-
-
- /*! \brief Window defined by a function.
- */
- template <typename F>
- struct fun : public internal::window_base< mln_deduce(F, result, dpsite),
- fun<F> >
- {
-
- /// Site_Iterator type to browse a fun forward
- typedef fun_piter<F> fwd_qiter;
-
- /// Site_Iterator type to browse a fun backward
- typedef fun_piter<F> bkd_qiter;
-
- /// Same as fwd_qiter
- typedef fwd_qiter qiter;
-
- /// Constructor.
- fun(const F& f) : f(f) {}
-
- /// Test if the window is centered.
- bool is_centered() const { return false; }
-
- /// Test if the window is empty.
- bool is_empty() const { return false; }
-
- /// Test if the window is symmetric.
- bool is_symmetric() const { return false; }
-
- /// Give the maximum coordinate gap between the window
- unsigned delta() const { return 100; } // FIXME
-
- /// Apply a central symmetry to the target window.
- void sym() {}
-
- const F& f;
- };
-
-
- template <typename F>
- class fun_piter
- : public internal::site_relative_iterator_base< fun<F>,
- fun_piter<F> >
- {
- public:
-
- typedef mln_result(F) W;
-
- /// Constructor.
- template <typename P>
- fun_piter(const fun<F>& win, const P& c)
- : f_(win.f)
- {
- q_.center_at(c);
- this->change_target(win);
- this->center_at(c);
- }
-
- /// Test the iterator validity.
- bool is_valid_() const
- {
- return this->c_ != 0 && q_.is_valid();
- }
-
- /// Invalidate the iterator.
- void invalidate_()
- {
- q_.invalidate();
- }
-
- /// Start an iteration.
- void do_start_()
- {
- q_.change_target(f_(*this->c_));
- q_.start();
- }
-
- /// Go to the next point.
- void do_next_()
- {
- q_.next();
- }
-
- /// Compute the current psite.
- mln_psite(W) compute_p_() const
- {
- return q_;
- }
-
- protected:
-
- const F& f_;
- mln_fwd_qiter(W) q_;
- };
-
-
-# ifndef MLN_INCLUDE_ONLY
-
- // FIXME: Move code here.
-
- // MEMO: mln_fwd_qiter(mln_result(F))
-
-
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace mln::win
-
-} // end of namespace mln
-
-
-
-#endif // ! MLN_WIN_FUN_HH
Index: geraud/Rd/hybrid.hh
--- geraud/Rd/hybrid.hh (revision 3151)
+++ geraud/Rd/hybrid.hh (working copy)
@@ -1,117 +0,0 @@
-// Copyright (C) 2007, 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_MORPHO_RD_HYBRID_HH
-# define MLN_MORPHO_RD_HYBRID_HH
-
-# include <queue>
-# include "utils.hh"
-
-
-namespace mln
-{
-
- namespace morpho
- {
-
- namespace Rd
- {
-
-
- template <typename I, typename N>
- I hybrid(const I& f, const I& g, const N& nbh,
- bool echo = false)
- {
- typedef mln_site(I) point;
- std::queue<point> q;
-
- // initialisation
- I o = duplicate(f);
-
- unsigned n_init_pushs = 0, n_body_pushs = 0, n_pops = 0;
-
- // sequence
- {
- mln_bkd_piter(I) p(f.domain());
- for_all(p)
- o(p) = min( max_Nminus(o, p,nbh), g(p) );
- }
- {
- mln_fwd_piter(I) p(f.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- o(p) = min( max_Nplus(o, p,nbh), g(p) );
- for_all(n)
- if (f.has(n) &&
- util::ord_strict(n.to_site(), p.to_site())) // N+
- if (o(n) < o(p) && o(n) < g(n))
- {
- q.push(p);
- ++n_init_pushs;
- }
- }
- }
-
- // propagation
- {
- point p;
- mln_niter(N) n(nbh, p);
- while (not q.empty())
- {
- p = q.front();
- if (echo) std::cout << std::endl << "pop " << p << " :";
- q.pop();
- ++n_pops;
- for_all(n) if (f.has(n))
- if (o(n) < o(p) && o(n) != g(n))
- {
- o(n) = min(o(p), g(n));
- if (echo) std::cout << " push " << n;
- q.push(n);
- ++n_body_pushs;
- }
- }
- if (echo) std::cout << std::endl;
- }
-
- if (echo)
- std::cout << "n_init_pushs = " << n_init_pushs << std::endl
- << "n_body_pushs = " << n_body_pushs << std::endl
- << "n_pops = " << n_pops << std::endl;
-
- return o;
- }
-
- } // end of namespace mln::morpho::Rd
-
- } // end of namespace mln::morpho
-
-} // end of namespace mln
-
-
-#endif // ! MLN_MORPHO_RD_HYBRID_HH
Index: geraud/Rd/queue_based.hh
--- geraud/Rd/queue_based.hh (revision 3151)
+++ geraud/Rd/queue_based.hh (working copy)
@@ -1,124 +0,0 @@
-// Copyright (C) 2007, 2008 EPITA Research && 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, 51 Franklin Street, Fifth Floor,
-// 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 && 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 MLN_MORPHO_RD_QUEUE_BASED_HH
-# define MLN_MORPHO_RD_QUEUE_BASED_HH
-
-# include <queue>
-# include "utils.hh"
-
-
-namespace mln
-{
-
- namespace morpho
- {
-
- namespace Rd
- {
-
- template <typename I, typename N>
- I queue_based(const I& f, const I& g, const N& nbh,
- bool echo = false)
- {
-
- mln_ch_value(I, bool) que(f.domain());
- data::fill(que, false);
-
-
- if (echo) std::cout << std::endl;
-
- typedef mln_site(I) point;
- std::queue<point> q;
- I o;
-
- unsigned n_init_pushs = 0, n_body_pushs = 0, n_pops = 0;
-
- // initialisation
- {
- o = regional_maxima(f, nbh);
- // p in M <=> o(p) != 0
- if (echo) debug::println(o);
-
- mln_piter(I) p(f.domain());
- mln_niter(N) n(nbh, p);
-
- for_all(p) if (o(p) != 0u) // p in M
- for_all(n) if (f.has(n) && o(n) == 0u) // n not in M
- {
- q.push(p);
- que(p) = true;
- ++n_init_pushs;
- break;
- }
- }
-
- // propagation
- {
- point p;
- mln_niter(N) n(nbh, p);
- while (not q.empty())
- {
- p = q.front();
- if (echo) std::cout << std::endl << "pop " << p << " :";
- q.pop();
- que(p) = false;
- ++n_pops;
- for_all(n) if (f.has(n))
- {
- if (o(n) < o(p) && o(n) != g(n))
- {
- o(n) = min(o(p), g(n));
- if (echo) std::cout << " push " << n;
- if (que(n) == false)
- {
- q.push(n);
- que(n) = true;
- ++n_body_pushs;
- }
- }
- }
- }
- if (echo) std::cout << std::endl;
- }
-
- if (echo)
- std::cout << "n_init_pushs = " << n_init_pushs << std::endl
- << "n_body_pushs = " << n_body_pushs << std::endl
- << "n_pops = " << n_pops << std::endl;
-
- return o;
- }
-
- } // end of namespace mln::morpho::Rd
-
- } // end of namespace mln::morpho
-
-} // end of namespace mln
-
-
-#endif // ! MLN_MORPHO_RD_QUEUE_BASED_HH
Index: geraud/Rd/parallel.cc
--- geraud/Rd/parallel.cc (revision 3151)
+++ geraud/Rd/parallel.cc (working copy)
@@ -1,54 +0,0 @@
-#include <iostream>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/value/int_u8.hh>
-
-#include <mln/debug/println.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-#include "parallel.hh"
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " f.pgm g.pgm c output.pgm" << std::endl
- << "reconstruction by dilation (parallel version; sep 2008)" << std::endl
- << "f = marker (to be dilated)" << std::endl
- << "g = mask (constraint >= f)" << std::endl
- << "c: 4 or 8" << std::endl;
- exit(1);
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 5)
- usage(argv);
-
- using namespace mln;
- using value::int_u8;
-
- border::thickness = 0; // Safety.
-
- typedef image2d<int_u8> I;
-
- int c = atoi(argv[3]);
- if (c != 4 and c != 8)
- usage(argv);
-
- I f, g;
- io::pgm::load(f, argv[1]);
- io::pgm::load(g, argv[2]);
-
- if (! (f <= g))
- {
- std::cerr << "error: the precondition 'f <= g' is not true" << std::endl;
- return 1;
- }
-
- I o = morpho::Rd::parallel(f, g,
- (c == 4 ? c4() : c8()));
- io::pgm::save(o, argv[4]);
-}
Index: geraud/Rd/parallel_wo.cc
--- geraud/Rd/parallel_wo.cc (revision 3151)
+++ geraud/Rd/parallel_wo.cc (working copy)
@@ -1,46 +0,0 @@
-#include <iostream>
-
-#include <mln/core/image2d.hh>
-#include <mln/core/neighb2d.hh>
-#include <mln/value/int_u8.hh>
-
-#include <mln/debug/println.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-#include "parallel.hh"
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " f.pgm g.pgm c output.pgm" << std::endl
- << "reconstruction by dilation (parallel version; may 2007)" << std::endl
- << "f = marker (to be dilated)" << std::endl
- << "g = mask (constraint >= f)" << std::endl
- << "c: 4 or 8" << std::endl;
- exit(1);
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 5)
- usage(argv);
-
- using namespace mln;
- using value::int_u8;
-
- typedef image2d<int_u8> I;
-
- int c = atoi(argv[3]);
- if (c != 4 and c != 8)
- usage(argv);
-
- I f = io::pgm::load<int_u8>(argv[1]);
- I g = io::pgm::load<int_u8>(argv[2]);
-
- io::pgm::save(morpho::Rd::parallel(f, g,
- (c == 4 ? c4() : c8()),
- false),
- argv[4]);
-}
Index: geraud/Rd/union_find.hh
--- geraud/Rd/union_find.hh (revision 3151)
+++ geraud/Rd/union_find.hh (working copy)
@@ -1,166 +0,0 @@
-// Copyright (C) 2007, 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_MORPHO_RD_UNION_FIND_HH
-# define MLN_MORPHO_RD_UNION_FIND_HH
-
-# include "utils.hh"
-
-
-namespace mln
-{
-
- namespace morpho
- {
-
- namespace Rd
- {
-
-
- template <typename I, typename N>
- struct union_find_t
- {
- typedef mln_site(I) point;
- typedef mln_value(I) value;
-
- // in:
- const I f, g;
- N nbh;
-
- // out:
- I o;
-
- // aux:
- std::vector<point> S;
- mln_ch_value(I, bool) deja_vu;
- mln_ch_value(I, point) parent;
-
- union_find_t(const I& f, const I& g, const N& nbh)
- : f(f), g(g), nbh(nbh)
- {
- initialize(o, f);
- initialize(parent, f);
- initialize(deja_vu, f);
-
- // init
-
- data::fill(deja_vu, false);
- S = histo_reverse_sort(g);
- data::paste(f, o); // Replace: for all p, make_set(p) { data(p) = f(p) }
-
- // first pass
-
- for (unsigned i = 0; i < S.size(); ++i)
- {
- point p = S[i];
- make_set(p);
- mln_niter(N) n(nbh, p);
- for_all(n)
- {
- if (f.has(n))
- mln_invariant(deja_vu(n) == is_proc(n, p));
- if (f.has(n) && deja_vu(n))
- do_union(n, p);
- }
- deja_vu(p) = true;
- }
-
- // second pass
-
- for (int i = S.size() - 1; i >= 0; --i)
- {
- point p = S[i];
- if (parent(p) == p)
- {
- if (o(p) == mln_max(value))
- o(p) = g(p);
- }
- else
- o(p) = o(parent(p));
- }
-
- }
-
- bool is_proc(const point& n, const point& p) const
- {
- return g(n) > g(p) or (g(n) == g(p) &&
- util::ord_strict(n, p));
- }
-
- void make_set(const point& p)
- {
- parent(p) = p;
- // was: data(p) = f(p);
- // now: in "initialization"
- }
-
- point find_root(const point& x)
- {
- if (parent(x) == x)
- return x;
- else
- return parent(x) = find_root(parent(x));
- }
-
- void do_union(const point& n, const point& p)
- {
- point r = find_root(n);
- if (r != p)
- {
- // NEW: o replaces data
-
- if (g(r) == g(p) or g(p) >= o(r)) // equiv test
- {
- parent(r) = p;
- if (o(r) > o(p))
- o(p) = o(r); // increasing criterion
- }
- else
- o(p) = mln_max(value);
- }
- }
-
- };
-
-
- template <typename I, typename N>
- I union_find(const I& f, const I& g, const N& nbh)
- {
- mln_precondition(f <= g);
- union_find_t<I, N> run(f, g, nbh);
- return run.o;
- }
-
-
- } // end of namespace mln::morpho::Rd
-
- } // end of namespace mln::morpho
-
-} // end of namespace mln
-
-
-#endif // ! MLN_MORPHO_RD_UNION_FIND_HH
Index: geraud/Rd/parallel.hh
--- geraud/Rd/parallel.hh (revision 3151)
+++ geraud/Rd/parallel.hh (working copy)
@@ -1,85 +0,0 @@
-// Copyright (C) 2007, 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_MORPHO_RD_PARALLEL_HH
-# define MLN_MORPHO_RD_PARALLEL_HH
-
-# include "utils.hh"
-
-
-namespace mln
-{
-
- namespace morpho
- {
-
- namespace Rd
- {
-
-
- template <typename I, typename N>
- I parallel(const I& f, const I& g, const N& nbh,
- bool test = true)
- {
- if (test)
- mln_precondition(f <= g);
-
- I o_(f.domain());
- mln_piter(I) p(f.domain());
-
- // initialisation
- I o = duplicate(f);
-
- bool stability;
- do
- {
- data::paste(o, o_); // memorisation
-
- // opere
- for_all(p)
- o(p) = max_N(o_, p, nbh);
- // conditionne
- for_all(p)
- o(p) = min(o(p), g(p));
-
- stability = (o == o_);
- }
- while (not stability);
-
- if (test)
- mln_postcondition(o <= g);
- return o;
- }
-
- } // end of namespace mln::morpho::Rd
-
- } // end of namespace mln::morpho
-
-} // end of namespace mln
-
-
-#endif // ! MLN_MORPHO_RD_PARALLEL_HH
Index: geraud/Rd/diff.cc
--- geraud/Rd/diff.cc (revision 3151)
+++ geraud/Rd/diff.cc (working copy)
@@ -1,28 +0,0 @@
-#include <oln/core/2d/image2d.hh>
-#include <oln/io/load_pgm.hh>
-#include <oln/level/compare.hh>
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " 1.pgm 2.pgm" << std::endl
- << "(may 2007)" << std::endl;
- exit(1);
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 3)
- usage(argv);
-
- using namespace oln;
- typedef image2d<unsigned char> I;
-
- I ima1 = io::load_pgm(argv[1]);
- I ima2 = io::load_pgm(argv[2]);
-
- if (ima1 != ima2)
- std::cout << "images differ" << std::endl;
- return 0;
-}
Index: geraud/Rd/sequential_bench.cc
--- geraud/Rd/sequential_bench.cc (revision 3151)
+++ geraud/Rd/sequential_bench.cc (working copy)
@@ -1,51 +0,0 @@
-#include <mln/core/image2d.hh>
-#include <mln/core/neighb2d.hh>
-
-#include <mln/debug/println.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-#include "sequential_bench.hh"
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " f.pgm g.pgm c output.pgm" << std::endl
- << "reconstruction by dilation (sequential version; may 2007)" << std::endl
- << "f = marker (to be dilated)" << std::endl
- << "g = mask (constraint >= f)" << std::endl
- << "c: 4 or 8" << std::endl;
- exit(1);
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 5)
- usage(argv);
-
- using namespace mln;
- using value::int_u8;
-
- typedef image2d<int_u8> I;
-
- int c = atoi(argv[3]);
- if (c != 4 and c != 8)
- usage(argv);
-
- I f = io::pgm::load<int_u8>(argv[1]);
- f.name_it("main.f");
-
- I g = io::pgm::load<int_u8>(argv[2]);
- g.name_it("main.g");
-
- if (not (f <= g))
- {
- std::cerr << "pb" << std::endl;
- return 1;
- }
-
- io::pgm::save(morpho::Rd::sequential(f, g,
- (c == 4 ? c4() : c8())),
- argv[4]);
-}
Index: geraud/Rd/sequential.cc
--- geraud/Rd/sequential.cc (revision 3151)
+++ geraud/Rd/sequential.cc (working copy)
@@ -1,50 +0,0 @@
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-
-#include <mln/debug/println.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-#include "sequential.hh"
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " f.pgm g.pgm c output.pgm" << std::endl
- << "reconstruction by dilation (sequential version; sep 2008)" << std::endl
- << "f = marker (to be dilated)" << std::endl
- << "g = mask (constraint >= f)" << std::endl
- << "c: 4 or 8" << std::endl;
- exit(1);
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 5)
- usage(argv);
-
- using namespace mln;
- using value::int_u8;
-
- border::thickness = 0; // Safety.
-
- typedef image2d<int_u8> I;
-
- int c = atoi(argv[3]);
- if (c != 4 and c != 8)
- usage(argv);
-
- I f, g;
- io::pgm::load(f, argv[1]);
- io::pgm::load(g, argv[2]);
-
- if (not (f <= g))
- {
- std::cerr << "error: the precondition 'f <= g' is not true" << std::endl;
- return 1;
- }
-
- I o = morpho::Rd::sequential(f, g, (c == 4 ? c4() : c8()));
- io::pgm::save(o, argv[4]);
-}
Index: geraud/Rd/deco.cc
--- geraud/Rd/deco.cc (revision 3151)
+++ geraud/Rd/deco.cc (working copy)
@@ -1,71 +0,0 @@
-// Copyright (C) 2007 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/*! \file tests/decorated_image.cc
- *
- * \brief Tests on mln::decorated_image.
- * \todo Make this test work.
- */
-
-#include <mln/core/image2d.hh>
-#include <mln/core/decorated_image.hh>
-
-
-unsigned count_read = 0, count_write = 0;
-
-template <typename I>
-struct counter
-{
- void reading(const I&, const mln_psite(I)&) const
- {
- ++count_read;
- }
- void writing(I&, const mln_psite(I)&, const mln_value(I)&)
- {
- ++count_write;
- }
-};
-
-
-int main()
-{
- using namespace mln;
-
- typedef image2d<int> I;
- I ima(1, 1);
- point2d p = make::point2d(0, 0);
-
- decorated_image< I, counter<I> > ima_ = decorate(ima, counter<I>());
- ima_(p) = ima_(p) = 51;
-
- std::cout << count_read << ' ' << count_write << std::endl;
-
- mln_assertion(count_read == 1 && count_write == 2);
-
- const I& imac = ima;
- decorated_image< const I, counter<I> > cima_ = decorate(imac, counter<I>());
-}
Index: geraud/Rd/utils.hh
--- geraud/Rd/utils.hh (revision 3151)
+++ geraud/Rd/utils.hh (working copy)
@@ -1,269 +0,0 @@
-// Copyright (C) 2007, 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_MORPHO_RD_UTILS_HH
-# define MLN_MORPHO_RD_UTILS_HH
-
-# include <vector>
-
-# include <mln/core/concept/image.hh>
-# include <mln/core/routine/duplicate.hh>
-
-# include <mln/util/ord.hh>
-
-# include <mln/data/fill_with_value.hh>
-# include <mln/data/paste.hh>
-# include <mln/level/compare.hh>
-
-
-
-namespace mln
-{
-
- namespace morpho
- {
-
- namespace Rd
- {
-
-
- template <typename T>
- T min(T v1, T v2)
- {
- return v1 < v2 ? v1 : v2;
- }
-
-
- template <typename I>
- I minimun(const I& ima1, const I& ima2)
- {
- mln_precondition(ima1.is_valid() && ima2.is_valid());
- mln_precondition(ima1.domain() == ima2.domain());
- I out(ima1.domain());
- mln_piter(I) p(ima1.domain());
- for_all(p)
- out(p) = ima1(p) < ima2(p) ? ima1(p) : ima2(p);
- return out;
- }
-
-
- template <typename I, typename P, typename N>
- mln_value(I) max_N(const I& ima, const P& p, const N& nbh)
- {
- mln_value(I) v = ima(p);
- mln_niter(N) n(nbh, p);
- for_all(n)
- if (ima.has(n) && ima(n) > v)
- v = ima(n);
- return v;
- }
-
-
- template <typename I, typename P, typename N>
- mln_value(I) max_Nminus(const I& ima, const P& p, const N& nbh)
- {
- mln_value(I) v = ima(p);
- mln_niter(N) n(nbh, p);
- for_all(n)
- if (ima.has(n) &&
- util::ord_strict(p.to_site(), n.to_site()) &&
- ima(n) > v)
- v = ima(n);
- return v;
- }
-
- template <typename I, typename P, typename N>
- mln_value(I) max_Nplus(const I& ima, const P& p, const N& nbh)
- {
- mln_value(I) v = ima(p);
- mln_niter(N) n(nbh, p);
- for_all(n)
- if (ima.has(n) &&
- util::ord_strict(n.to_site(), p.to_site()) &&
- ima(n) > v)
- v = ima(n);
- return v;
- }
-
-
- template <typename I>
- std::vector<unsigned> compute_histo(const I& ima)
- {
- std::vector<unsigned> h(256, 0);
- mln_piter(I) p(ima.domain());
- for_all(p)
- ++h[ima(p)];
- return h;
- }
-
-
-// template <typename I>
-// std::vector<mln_site(I)> histo_sort(const I& ima)
-// {
-// std::vector<unsigned> h = compute_histo(ima);
-// // preparing output data
-// std::vector<int> loc(256);
-// loc[0] = 0;
-// for (int l = 1; l < 256; ++l)
-// loc[l] = loc[l-1] + h[l-1];
-// std::vector<mln_site(I)> vec(ima.nsites());
-// // storing output data
-// mln_piter(I) p(ima.domain());
-// for_all(p)
-// vec[loc[ima(p)]++] = p;
-// return vec;
-// }
-
-
- template <typename I>
- std::vector<mln_site(I)> histo_reverse_sort(const I& ima)
- {
- std::vector<unsigned> h = compute_histo(ima);
- // preparing output data
- std::vector<int> loc(256);
- loc[255] = 0;
- for (int l = 254; l >= 0; --l)
- loc[l] = loc[l+1] + h[l+1];
- std::vector<mln_site(I)> vec(ima.nsites());
- // storing output data
- mln_piter(I) p(ima.domain());
- for_all(p)
- vec[loc[ima(p)]++] = p;
- return vec;
- }
-
-
-
- template <typename I, typename N>
- struct regional_maxima_t
- {
- typedef mln_site(I) point;
- typedef mln_ch_value(I, bool) image_bool;
- typedef mln_ch_value(I, point) image_point;
-
- // in:
- I f;
- N nbh;
-
- // out:
- I o;
-
- // aux:
- std::vector<point> S;
- image_bool deja_vu;
- image_bool attr;
- image_point parent;
-
- regional_maxima_t(const I& f, const N& nbh)
- : f(f), nbh(nbh)
- {
- initialize(o, f);
- initialize(parent, f);
- initialize(attr, f);
- initialize(deja_vu, f);
-
- // init
-
- data::fill_with_value(deja_vu, false);
- S = histo_reverse_sort(f);
-
- // first pass
-
- for (unsigned i = 0; i < S.size(); ++i)
- {
- point p = S[i];
-
- make_set(p);
- mln_niter(N) n(nbh, p);
- for_all(n)
- if (f.has(n) && deja_vu(n))
- {
- if (f(n) == f(p))
- do_union(n, p);
- else // f(n) > f(p)
- attr(p) = false;
- }
- deja_vu(p) = true;
- }
-
- // second pass
-
- const mln_value(I) zero = 0;
- for (int i = S.size() - 1; i >= 0; --i)
- {
- point p = S[i];
- if (parent(p) == p)
- o(p) = attr(p) ? f(p) : zero;
- else
- o(p) = o(parent(p));
- }
- }
-
- void make_set(const point& p)
- {
- parent(p) = p;
- attr(p) = true;
- }
-
- point find_root(const point& x)
- {
- if (parent(x) == x)
- return x;
- else
- return parent(x) = find_root(parent(x));
- }
-
- void do_union(const point& n, const point& p)
- {
- point r = find_root(n);
- if (r != p)
- {
- parent(r) = p;
- attr(p) = attr(p) && attr(r);
- }
- }
-
- };
-
-
- template <typename I, typename N>
- I
- regional_maxima(const I& f, const N& nbh)
- {
- regional_maxima_t<I, N> run(f, nbh);
- return run.o;
- }
-
-
- } // end of namespace mln::morpho::Rd
-
- } // end of namespace mln::morpho
-
-} // end of namespace mln
-
-
-#endif // ! MLN_MORPHO_RD_UTILS_HH
Index: geraud/Rd/diff_pgm.cc
--- geraud/Rd/diff_pgm.cc (revision 3151)
+++ geraud/Rd/diff_pgm.cc (working copy)
@@ -1,43 +0,0 @@
-#include <mln/core/image/image2d.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/level/compare.hh>
-#include <mln/value/int_u8.hh>
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " 1.pgm 2.pgm out.pgm" << std::endl
- << "(october 2008)" << std::endl;
- exit(1);
-}
-
-
-unsigned char diff_abs(unsigned char c1,
- unsigned char c2)
-{
- return c1 > c2 ? c1 - c2 : c2 - c1;
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 4)
- usage(argv);
-
- using namespace mln;
- typedef image2d<value::int_u8> I;
-
- I ima1;
- io::pgm::load(ima1, argv[1]);
- I ima2;
- io::pgm::load(ima2, argv[2]);
-
- I out(ima1.domain());
- mln_piter_(I) p(ima1.domain());
- for_all(p)
- out(p) = diff_abs(ima1(p), ima2(p));
-
- io::pgm::save(out, argv[3]);
- return 0;
-}
Index: geraud/Rd/hybrid.cc
--- geraud/Rd/hybrid.cc (revision 3151)
+++ geraud/Rd/hybrid.cc (working copy)
@@ -1,53 +0,0 @@
-#include <iostream>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/value/int_u8.hh>
-
-#include <mln/debug/println.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-#include "hybrid.hh"
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " f.pgm g.pgm c output.pgm" << std::endl
- << "reconstruction by dilation (hybrid version; sep 2008)" << std::endl
- << "f = marker (to be dilated)" << std::endl
- << "g = mask (constraint >= f)" << std::endl
- << "c: 4 or 8" << std::endl;
- exit(1);
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 5)
- usage(argv);
-
- using namespace mln;
- using value::int_u8;
-
- border::thickness = 0; // Safety.
-
- typedef image2d<int_u8> I;
-
- int c = atoi(argv[3]);
- if (c != 4 and c != 8)
- usage(argv);
-
- I f, g;
- io::pgm::load(f, argv[1]);
- io::pgm::load(g, argv[2]);
-
- if (not (f <= g))
- {
- std::cerr << "error: the precondition 'f <= g' is not true" << std::endl;
- return 1;
- }
-
- I o = morpho::Rd::hybrid(f, g, (c == 4 ? c4() : c8()));
- io::pgm::save(o, argv[4]);
-}
Index: geraud/Rd/queue_based.cc
--- geraud/Rd/queue_based.cc (revision 3151)
+++ geraud/Rd/queue_based.cc (working copy)
@@ -1,51 +0,0 @@
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/value/int_u8.hh>
-
-#include <mln/debug/println.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-#include "queue_based.hh"
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " f.pgm g.pgm c output.pgm" << std::endl
- << "reconstruction by dilation (queue_based version; sep 2008)" << std::endl
- << "f = marker (to be dilated)" << std::endl
- << "g = mask (constraint >= f)" << std::endl
- << "c: 4 or 8" << std::endl;
- exit(1);
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 5)
- usage(argv);
-
- using namespace mln;
- using value::int_u8;
-
- border::thickness = 0; // Safety.
-
- typedef image2d<int_u8> I;
-
- int c = atoi(argv[3]);
- if (c != 4 and c != 8)
- usage(argv);
-
- I f, g;
- io::pgm::load(f, argv[1]);
- io::pgm::load(g, argv[2]);
-
- if (! (f <= g))
- {
- std::cerr << "error: the precondition 'f <= g' is not true" << std::endl;
- return 1;
- }
-
- I o = morpho::Rd::queue_based(f, g, (c == 4 ? c4() : c8()));
- io::pgm::save(o, argv[4]);
-}
Index: geraud/Rd/sequential_bench.hh
--- geraud/Rd/sequential_bench.hh (revision 3151)
+++ geraud/Rd/sequential_bench.hh (working copy)
@@ -1,100 +0,0 @@
-// Copyright (C) 2007 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_MORPHO_RD_SEQUENTIAL_HH
-# define MLN_MORPHO_RD_SEQUENTIAL_HH
-
-# include "utils.hh"
-
-
-namespace mln
-{
-
- namespace morpho
- {
-
- namespace Rd
- {
-
- template <typename I, typename N>
- I sequential(const I& f, const I& g, const N& nbh)
- {
- mln_precondition(f <= g);
-
- f.name_it("f");
- g.name_it("g");
-
- I o_(f.domain());
- o_.name_it("o_");
-
- unsigned nloops = 0;
-
- // initialisation
- I o = duplicate(f);
- o.name_it("o");
-
- bool stability;
- do
- {
- ++nloops;
-
- data::paste(o, o_); // memorisation
-
- // passe 1
- {
- mln_bkd_piter(I) p(f.domain());
- for_all(p)
- o(p) = min( max_Nminus(o, p, nbh), g(p) );
- }
-
- // passe 2
- {
- mln_fwd_piter(I) p(f.domain());
- for_all(p)
- o(p) = min( max_Nplus(o, p, nbh), g(p) );
- }
-
- stability = (o == o_);
- }
- while (not stability);
-
- std::cout << "nloops = " << nloops << std::endl;
-
- print_counts();
-
- mln_postcondition(o <= g);
- return o;
- }
-
- } // end of namespace mln::morpho::Rd
-
- } // end of namespace mln::morpho
-
-} // end of namespace mln
-
-
-#endif // ! MLN_MORPHO_RD_SEQUENTIAL_HH
Index: geraud/Rd/min.cc
--- geraud/Rd/min.cc (revision 3151)
+++ geraud/Rd/min.cc (working copy)
@@ -1,42 +0,0 @@
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " 1.pgm 2.pgm out.pgm" << std::endl
- << "(sep 2008)" << std::endl;
- exit(1);
-}
-
-
-template <typename I>
-I min(const I& ima1, const I& ima2)
-{
- mln_precondition(ima1.is_valid() and ima2.is_valid());
- mln_precondition(ima1.domain() == ima2.domain());
- I out(ima1.domain());
- mln_piter(I) p(ima1.domain());
- for_all(p)
- out(p) = ima1(p) < ima2(p) ? ima1(p) : ima2(p);
- return out;
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 4)
- usage(argv);
-
- using namespace mln;
- using value::int_u8;
-
- typedef image2d<int_u8> I;
-
- I ima1 = io::pgm::load<int_u8>(argv[1]);
- I ima2 = io::pgm::load<int_u8>(argv[2]);
-
- io::pgm::save(min(ima1, ima2), argv[3]);
-}
Index: geraud/Rd/sequential.hh
--- geraud/Rd/sequential.hh (revision 3151)
+++ geraud/Rd/sequential.hh (working copy)
@@ -1,87 +0,0 @@
-// Copyright (C) 2007, 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_MORPHO_RD_SEQUENTIAL_HH
-# define MLN_MORPHO_RD_SEQUENTIAL_HH
-
-# include "utils.hh"
-
-
-namespace mln
-{
-
- namespace morpho
- {
-
- namespace Rd
- {
-
- template <typename I, typename N>
- I sequential(const I& f, const I& g, const N& nbh)
- {
- mln_precondition(f <= g);
-
- I o_(f.domain());
-
- // initialisation
- I o = duplicate(f);
-
- bool stability;
- do
- {
- data::paste(o, o_); // memorisation
-
- // passe 1
- {
- mln_bkd_piter(I) p(f.domain());
- for_all(p)
- o(p) = min( max_Nminus(o, p, nbh), g(p) );
- }
-
- // passe 2
- {
- mln_fwd_piter(I) p(f.domain());
- for_all(p)
- o(p) = min( max_Nplus(o, p, nbh), g(p) );
- }
-
- stability = (o == o_);
- }
- while (not stability);
-
- mln_postcondition(o <= g);
- return o;
- }
-
- } // end of namespace mln::morpho::Rd
-
- } // end of namespace mln::morpho
-
-} // end of namespace mln
-
-
-#endif // ! MLN_MORPHO_RD_SEQUENTIAL_HH
Index: geraud/Rd/debase.union_find.hh
--- geraud/Rd/debase.union_find.hh (revision 3151)
+++ geraud/Rd/debase.union_find.hh (working copy)
@@ -1,165 +0,0 @@
-// Copyright (C) 2007, 2008 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, 51 Franklin Street, Fifth Floor,
-// 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 OLN_MORPHO_RD_UNION_FIND_HH
-# define OLN_MORPHO_RD_UNION_FIND_HH
-
-# include <oln/morpho/Rd/utils.hh>
-
-
-namespace oln
-{
-
- namespace morpho
- {
-
- namespace Rd
- {
-
-
- template <typename I, typename N>
- struct union_find_t
- {
- typedef oln_point(I) point;
-
- // in:
- I f, g;
- N nbh;
-
- // out:
- I o;
-
- // aux:
- std::vector<point> S;
- I data;
- oln_plain_value(I, bool) is_proc;
- oln_plain_value(I, point) parent;
-
- union_find_t(const I& f, const I& g, const N& nbh)
- : f(f), g(g), nbh(nbh)
- {
- prepare(o, with, f);
- prepare(parent, with, f);
- prepare(is_proc, with, f);
- prepare(data, with, f);
-
- // init
-
- std::cout << "0 ";
- data::fill(is_proc, false);
- S = histo_reverse_sort(g);
-
- // first pass
-
- std::cout << "1 ";
- for (unsigned i = 0; i < S.size(); ++i)
- {
- point p = S[i];
-
- make_set(p);
- oln_niter(N) n(nbh, p);
- for_all(n)
- if (f.has(n) and is_proc(n))
- do_union(n, p);
- is_proc(p) = true;
- }
-
- // second pass
-
- std::cout << "2 ";
- data::fill(is_proc, false);
- for (int i = S.size() - 1; i >= 0; --i)
- {
- point p = S[i];
- assert(is_proc(p) == false);
- if (parent(p) == p)
- o(p) = data(p) == 255 ? g(p) : data(p);
- else
- {
- assert(is_proc(parent(p)) == true);
- o(p) = o(parent(p));
- }
- is_proc(p) = true;
- }
-
- }
-
- void make_set(const point& p)
- {
- parent(p) = p;
- data(p) = f(p);
- }
-
- point find_root(const point& x)
- {
- if (parent(x) == x)
- return x;
- else
- return parent(x) = find_root(parent(x));
- }
-
- bool equiv(const point& r, const point& p)
- {
- return g(r) == g(p) or g(p) >= data(r);
- }
-
- void do_union(const point& n, const point& p)
- {
- point r = find_root(n);
- if (r != p)
- {
- if (equiv(r, p))
- {
- parent(r) = p;
- if (data(r) > data(p))
- data(p) = data(r); // increasing criterion
- }
- else
- data(p) = 255;
- }
- }
-
- };
-
-
- template <typename I, typename N>
- I union_find(const I& f, const I& g, const N& nbh)
- {
- precondition(f <= g);
- union_find_t<I, N> run(f, g, nbh);
- return run.o;
- }
-
-
- } // end of namespace oln::morpho::Rd
-
- } // end of namespace oln::morpho
-
-} // end of namespace oln
-
-
-#endif // ! OLN_MORPHO_RD_UNION_FIND_HH
Index: geraud/Rd/union_find.cc
--- geraud/Rd/union_find.cc (revision 3151)
+++ geraud/Rd/union_find.cc (working copy)
@@ -1,52 +0,0 @@
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/value/int_u8.hh>
-
-#include <mln/debug/println.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-#include "union_find.hh"
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " f.pgm g.pgm c output.pgm" << std::endl
- << "reconstruction by dilation (union_find version; sep 2008)" << std::endl
- << "f = marker (to be dilated)" << std::endl
- << "g = mask (constraint >= f)" << std::endl
- << "c: 4 or 8" << std::endl;
- exit(1);
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 5)
- usage(argv);
-
- using namespace mln;
- using value::int_u8;
-
- border::thickness = 0; // Safety.
-
- typedef image2d<int_u8> I;
-
- int c = atoi(argv[3]);
- if (c != 4 and c != 8)
- usage(argv);
-
- I f, g;
- io::pgm::load(f, argv[1]);
- io::pgm::load(g, argv[2]);
-
- if (! (f <= g))
- {
- std::cerr << "error: the precondition 'f <= g' is not true" << std::endl;
- return 1;
- }
-
- I o = morpho::Rd::union_find(f, g, (c == 4 ? c4() : c8()));
- io::pgm::save(o, argv[4]);
-}
Index: geraud/Rd/svg.queue_based.hh
--- geraud/Rd/svg.queue_based.hh (revision 3151)
+++ geraud/Rd/svg.queue_based.hh (working copy)
@@ -1,118 +0,0 @@
-// Copyright (C) 2007 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_MORPHO_RD_QUEUE_BASED_HH
-# define MLN_MORPHO_RD_QUEUE_BASED_HH
-
-# include <queue>
-# include "utils.hh"
-
-
-namespace mln
-{
-
- namespace morpho
- {
-
- namespace Rd
- {
-
- template <typename I, typename N>
- I queue_based(const I& f, const I& g, const N& nbh,
- bool echo = false)
- {
- if (echo) std::cout << std::endl;
-
- f.name_it("f");
- g.name_it("g");
-
- typedef mln_point(I) point;
- std::queue<point> q;
- I o;
- o.name_it("o");
-
- unsigned n_init_pushs = 0, n_body_pushs = 0, n_pops = 0;
-
- // initialisation
- {
- o = regional_maxima(f, nbh);
- // p in M <=> o(p) != 0
- if (echo) debug::println(o);
-
- mln_piter(I) p(f.domain());
- mln_niter(N) n(nbh, p);
-
- for_all(p) if (o(p) != 0) // p in M
- for_all(n) if (f.has(n) and o(n) == 0) // n not in M
- {
- q.push(p);
- ++n_init_pushs;
- break;
- }
- }
-
- // propagation
- {
- point p;
- mln_niter(N) n(nbh, p);
- while (not q.empty())
- {
- p = q.front();
- if (echo) std::cout << std::endl << "pop " << p << " :";
- q.pop();
- ++n_pops;
- for_all(n) if (f.has(n))
- {
- if (o(n) < o(p) and o(n) != g(n))
- {
- o(n) = min(o(p), g(n));
- if (echo) std::cout << " push " << n;
- q.push(n);
- ++n_body_pushs;
- }
- }
- }
- if (echo) std::cout << std::endl;
- }
-
- std::cout << "n_init_pushs = " << n_init_pushs << std::endl
- << "n_body_pushs = " << n_body_pushs << std::endl
- << "n_pops = " << n_pops << std::endl;
-
- print_counts();
-
- return o;
- }
-
- } // end of namespace mln::morpho::Rd
-
- } // end of namespace mln::morpho
-
-} // end of namespace mln
-
-
-#endif // ! MLN_MORPHO_RD_QUEUE_BASED_HH
Index: geraud/dmap.cc
--- geraud/dmap.cc (revision 3151)
+++ geraud/dmap.cc (working copy)
@@ -1,131 +0,0 @@
-#include <vector>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/w_window2d_int.hh>
-#include <mln/debug/println.hh>
-#include <mln/data/fill.hh>
-#include <mln/level/stretch.hh>
-#include <mln/accu/max.hh>
-#include <mln/io/pbm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/opt/at.hh>
-
-
-namespace mln
-{
-
- template<typename I, typename W>
- mln_ch_value(I, unsigned) dmap(const Image<I>& input_,
- const Weighted_Window<W>& win_)
- {
- const I& input = exact(input_);
- const W& win = exact(win_);
- mln_precondition(input.is_valid());
-
- typedef std::vector<mln_site(I)> bucket_t;
-
- // Initialization of distance.
- mln_ch_value(I, unsigned) distance;
- initialize(distance, input);
-
- // Mod determination.
- accu::max<unsigned> max;
- for (unsigned i = 0; i < win.size(); ++i)
- max.take(win.w(i));
- unsigned mod = unsigned(max) + 1;
-
- // Aux data.
- std::vector<bucket_t> bucket(mod);
- unsigned bucket_size = 0;
-
- // Initialization.
- {
- mln_piter(I) p(input.domain());
- mln_qiter(W) q(win, p);
- for_all(p)
- if (input(p))
- {
- distance(p) = literal::zero;
- for_all(q)
- if (input.has(q) && ! input(q))
- {
- bucket[0].push_back(p);
- ++bucket_size;
- break;
- }
- }
- else
- distance(p) = mln_max(unsigned);
- }
-
- // Propagation.
- {
- mln_site(I) p;
- mln_qiter(W) q(win, p);
-
- for (unsigned d = 0; bucket_size != 0; ++d)
- {
- bucket_t& bucket_d = bucket[d % mod];
- for (unsigned i = 0; i < bucket_d.size(); ++i)
- {
- p = bucket_d[i];
-
- if (distance(p) < d)
- // p has already been processed, having a distance less than d.
- continue;
-
- for_all(q)
- if (distance.has(q) && distance(q) > d)
- {
- unsigned d_ = d + q.w();
-
- if (d_ < distance(q))
- {
- distance(q) = d_;
- bucket[d_ % mod].push_back(q);
- ++bucket_size;
- }
- }
- }
- bucket_size -= bucket_d.size();
- bucket_d.clear();
- }
-
- } // end of propagation.
-
- return distance;
- }
-
-} // end of namespace mln
-
-
-
-int main()
-{
- using namespace mln;
- using value::int_u8;
-
- const unsigned n = 9;
- image2d<bool> ima(n, n);
- data::fill(ima, false);
- opt::at(ima, n / 2, n / 2) = true;
-
-// int ws[] = { 3, 2, 3,
-// 2, 0, 2,
-// 3, 2, 3 };
-
- int ws[] = { 0, 9, 0, 9, 0,
- 9, 6, 4, 6, 9,
- 0, 4, 0, 4, 0,
- 9, 6, 4, 6, 9,
- 0, 9, 0, 9, 0 }; // coef = 4.1203
-
- w_window2d_int win = make::w_window2d(ws);
-
- image2d<unsigned> d = dmap(ima, win);
- debug::println(d);
-
-// image2d<int_u8> out;
-// level::stretch(d, out);
-// io::pgm::save(out, "out.pgm");
-}
Index: geraud/compute_parent_more.hh
--- geraud/compute_parent_more.hh (revision 3151)
+++ geraud/compute_parent_more.hh (working copy)
@@ -1,191 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_MORPHO_TREE_COMPUTE_PARENT_HH
-# define MLN_MORPHO_TREE_COMPUTE_PARENT_HH
-
-/// \file mln/morpho/tree/compute_parent.hh
-///
-/// Compute a canonized tree from an image.
-///
-/// \todo Specialize for low quant (and try fastest).
-
-# include <mln/core/concept/image.hh>
-# include <mln/core/concept/neighborhood.hh>
-# include <mln/data/fill.hh>
-
-
-namespace mln
-{
-
- namespace morpho
- {
-
- namespace tree
- {
-
-
- template <typename T>
- inline
- mln_psite(T)
- zfind_root(T& zpar, const mln_psite(T)& x)
- {
- mlc_equal(mln_value(T), mln_psite(T))::check();
- if (zpar(x) == x)
- return x;
- else
- return zpar(x) = zfind_root(zpar, zpar(x));
- }
-
-
-
- template <typename I, typename N, typename S>
- inline
- mln_ch_value(I, mln_psite(I))
- compute_parent_more(const Image<I>& f_,
- const Neighborhood<N>& nbh_,
- const Site_Set<S>& s_)
- {
- typedef mln_psite(I) P;
-
- const I& f = exact(f_);
- const N& nbh = exact(nbh_);
- const S& s = exact(s_);
-
- // Auxiliary data.
- mln_ch_value(I, bool) deja_vu;
- mln_ch_value(I, P) parent;
- mln_ch_value(I, P) zpar;
-
- initialize(deja_vu, f);
- initialize(parent, f);
- initialize(zpar, f);
-
- typedef mln_vset(S) Vs;
- typedef mln_pset(S) Ps;
- S roots;
-
- // Initialization.
- data::fill(deja_vu, false);
- unsigned nnodes = 0;
-
- // Body.
- mln_bkd_viter(Vs) v(s.values());
- for_all(v)
- {
- if (s(v).is_empty())
- continue;
-
- mln_bkd_piter(Ps) p(s(v));
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- // Make-Set.
- parent(p) = p;
- zpar(p) = p;
-
- for_all(n)
- if (f.domain().has(n) && deja_vu(n))
- {
- // Do-Union.
- P r = internal::zfind_root(zpar, n);
- if (r != p)
- {
- parent(r) = p;
- zpar(r) = p;
- }
- }
- deja_vu(p) = true;
- }
-
-
- /*
-
- // Canonization on the-fly.
- {
- // Intra-v:
- mln_fwd_piter(Ps) p(s(v));
- for_all(p)
- parent(p) = parent(parent(p));
-
- // Inter "previous v and current v":
- mln_piter(Ps) r(v_roots);
- for_all(r)
- parent(r) = parent(parent(r));
- v_roots.clear();
-
- {
- // New roots:
- mln_piter(Ps) p(s(v));
- for_all(p)
- if (parent(p) == p)
- v_roots.insert(p);
- nnodes += v_roots.nsites();
- }
- }
-
- */
-
- // Storing roots.
- {
- mln_piter(Ps) p(s(v));
- for_all(p)
- if (parent(p) == p)
- roots(v).insert(p);
- nnodes += roots(v).nsites();
- }
-
- } // end of "for_all(v)"
-
-
- // Canonization.
- {
- mln_fwd_piter(S) p(s);
- for_all(p)
- {
- P q = parent(p);
- if (f(parent(q)) == f(q))
- parent(p) = parent(q);
- }
- }
-
- std::cout << "roots = " << roots << std::endl;
- std::cout << "nnodes = " << nnodes << std::endl;
-
-
- return parent;
- }
-
-
- } // end of namespace mln::morpho::tree
-
- } // end of namespace mln::morpho
-
-} // end of namespace mln
-
-
-#endif // ! MLN_MORPHO_TREE_COMPUTE_PARENT_HH
Index: geraud/tufa_2008/steps.0.cc
--- geraud/tufa_2008/steps.0.cc (revision 3151)
+++ geraud/tufa_2008/steps.0.cc (working copy)
@@ -1,171 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/steps.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/morpho/tree/data.hh>
-
-#include <mln/accu/count.hh>
-
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/morpho/closing_area.hh>
-#include <mln/data/fill.hh>
-#include <mln/opt/at.hh>
-
-
-namespace mln
-{
-
- template <typename I>
- void println_par(const I& par)
- {
- int nr = par.nrows(), nc = par.ncols();
- for (int r = 0; r < nr; ++r)
- {
- for (int c = 0; c < nc; ++c)
- if (opt::at(par, r,c) == point2d(r,c))
- std::cout << "( ) ";
- else
- std::cout << opt::at(par, r,c) << ' ';
- std::cout << std::endl;
- }
- }
-
- template <typename P>
- inline
- mln_value(P) find_root__(P& par, const mln_value(P)& x)
- {
- if (par(x) == x)
- return x;
- else
- return par(x) = find_root__(par, par(x));
- }
-
-
- template <typename I, typename A, typename N>
- mln_concrete(I) filtering(const I& f, const A& a, const N& nbh, mln_value(A) lambda)
- {
- typedef p_array<mln_psite(I)> S;
- S s = level::sort_psites_increasing(a);
-
- // s maps increasing attributes.
-
- mln_concrete(I) out;
- initialize(out, f);
-
- mln_ch_value(I, mln_site(I)) par;
- mln_ch_value(I, bool) deja_vu;
- {
- initialize(par, f);
- mln_piter(A) p(par.domain());
- for_all(p)
- par(p) = p;
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
- }
-
- // First pass.
- {
- mln_site(I) r;
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- for_all(n)
- if (a.domain().has(n) && deja_vu(n))
- {
- r = find_root__(par, n);
- if (r != p)
- if (f(r) == f(p) || a(r) < lambda)
- par(r) = p; // Union.
- }
- deja_vu(p) = true;
- }
- }
-
- // Second pass.
- {
- mln_bkd_piter(S) p(s);
- for_all(p)
- if (par(p) == p)
- out(p) = f(p);
- else
- out(p) = out(par(p));
- }
- return out;
- }
-
-
-} // mln
-
-
-
-
-int main()
-{
- using namespace mln;
- using value::int_u8;
-
- int_u8 n;
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, "../../../img/fly.pgm");
- debug::println("f =", f);
-
- debug::println("ref =", morpho::closing_area(f, c4(), 10));
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- // Children go towards lower levels so leafs are regional minima.
- // We get a min-tree so that we can perform morphological closings.
-
- morpho::tree::data<I,S> t(f, s, c4());
- accu::count< util::pix<I> > attr;
-
- image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
- I g = filtering(f, a, c4(), 10);
- debug::println("g =", g);
-
- {
- S s = level::sort_psites_decreasing(g);
- morpho::tree::data<I,S> t(g, s, c4());
- image2d<unsigned> a_g = morpho::tree::compute_attribute_image(attr, t);
- debug::println("a(f) =", a);
- debug::println("a(g) =", a_g);
- }
-
-}
Index: geraud/tufa_2008/steps.1.cc
--- geraud/tufa_2008/steps.1.cc (revision 3151)
+++ geraud/tufa_2008/steps.1.cc (working copy)
@@ -1,274 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/steps.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/morpho/tree/data.hh>
-
-#include <mln/accu/count.hh>
-#include <mln/util/set.hh>
-
-#include <mln/labeling/regional_minima.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/morpho/closing_area.hh>
-#include <mln/data/fill.hh>
-#include <mln/opt/at.hh>
-
-
-namespace mln
-{
-
- template <typename I>
- void println_par(const I& par)
- {
- int nr = par.nrows(), nc = par.ncols();
- for (int r = 0; r < nr; ++r)
- {
- for (int c = 0; c < nc; ++c)
- if (opt::at(par, r,c) == point2d(r,c))
- std::cout << "( ) ";
- else
- std::cout << opt::at(par, r,c) << ' ';
- std::cout << std::endl;
- }
- }
-
- template <typename P>
- inline
- mln_value(P) find_root__(P& par, const mln_value(P)& x)
- {
- if (par(x) == x)
- return x;
- else
- return par(x) = find_root__(par, par(x));
- }
-
-
- template <typename I, typename A, typename N>
- void run_run(const I& f, const A& a, const N& nbh)
- {
- typedef p_array<mln_psite(I)> S;
- S s = level::sort_psites_increasing(a);
- // s maps increasing attributes.
-
- mln_ch_value(I, mln_site(I)) par;
- mln_ch_value(I, bool) deja_vu;
- mln_ch_value(I, util::set<unsigned>) labels;
- unsigned nbassins, current_n;
-
-
- // Initialization.
- {
- mln_piter(A) p(f.domain());
-
- // parent
- initialize(par, f);
- for_all(p)
- par(p) = p;
-
- // deja_vu
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
-
- // labels
- mln_ch_value(I, unsigned) regmin = labeling::regional_minima(a, nbh,
- nbassins);
- debug::println(regmin);
- initialize(labels, f);
- for_all(p)
- if (regmin(p) != 0) // p in a reg min of the attribute image
- labels(p).insert(regmin(p));
- }
-
- current_n = nbassins;
-
- // First pass.
- {
- mln_site(I) r;
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- for_all(n)
- if (a.domain().has(n) && deja_vu(n))
- {
- r = find_root__(par, n);
- if (r != p)
- {
- par(r) = p; // Union.
-
- // logging the different cases
- if (labels(p).is_empty() && labels(r).is_empty())
- {
- std::cout << "x";
-
- // It can happen with:
- // M M m
- // (m a min, M a flat zone)
- // During the pass:
- // M M {m}
- // then the 1st point is processed
- // {} M {m}
- // and when processing the 2nd point
- // r={} p={} {m}
- // the (left) neighbor of p has an empty set such as p.
-
-// // Extra log.
-// std::cout << std::endl
-// << "p = " << p << " "
-// << "r = " << r << std::endl;
-// debug::println(labels);
- }
- else
- if (labels(p).is_empty() || labels(r).is_empty())
- {
- std::cout << (labels(p).is_empty() ? 'p' : 'r');
- }
- else
- if (labels(p) == labels(r))
- {
- std::cout << "=";
-// // Extra log.
-// std::cout << std::endl
-// << "p = " << p << " "
-// << "r = " << r << std::endl;
-// debug::println(labels);
- }
- else
- std::cout << ".";
- // end of log
-
- // The invariants below are erroneous.
-// mln_invariant(! (labels(p).is_empty() && labels(r).is_empty()));
-// mln_invariant(labels(p) != labels(r));
-
- // Either:
- // one of the two label sets is empty (and the other is not)
- // or:
- // both label sets are not empty then they differ.
-
- // More restrictively:
-// mln_invariant(! labels(r).is_empty());
-
- if (labels(p).is_empty())
- {
- labels(p).insert(labels(r));
- }
- else
- {
-
-// std::cout << std::endl
-// << "at " << p << std::endl
-// << "before:" << std::endl;
-// debug::println(labels);
-
- unsigned
- np = labels(p).nelements(),
- nr = labels(r).nelements();
- labels(p).insert(labels(r));
- unsigned
- n = labels(p).nelements(),
- dnp = n - np,
- dnr = n - nr,
- delta_n = std::min(dnp, dnr);
-
- // The invariant below is erroneous.
-// mln_invariant(delta_n != 0);
-
-
-// std::cout << "delta = " << delta_n << std::endl
-// << "after: " << std::endl;
-// debug::println(labels);
-
-
- // We can have the three cases below:
- if (dnr > dnp)
- std::cout << '>';
- else
- if (dnr < dnp)
- std::cout << '<';
- else
- std::cout << '~';
- std::cout << '(' << delta_n << ')';
- }
- }
- }
- deja_vu(p) = true;
- }
- }
-
- std::cout << std::endl;
-// debug::println(labels);
- }
-
-
-} // mln
-
-
-
-
-int main()
-{
- using namespace mln;
- using value::int_u8;
-
- int_u8 n;
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, "../../../img/tiny.pgm");
-// debug::println("f =", f);
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- // Children go towards lower levels so leafs are regional minima.
- // We get a min-tree so that we can perform morphological closings.
-
- morpho::tree::data<I,S> t(f, s, c4());
- accu::count< util::pix<I> > attr;
-
- image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
- run_run(f, a, c4());
-
-// {
-// S s = level::sort_psites_decreasing(g);
-// morpho::tree::data<I,S> t(g, s, c4());
-// image2d<unsigned> a_g = morpho::tree::compute_attribute_image(attr, t);
-// debug::println("a(f) =", a);
-// debug::println("a(g) =", a_g);
-// }
-
-}
Index: geraud/tufa_2008/gradient.cc
--- geraud/tufa_2008/gradient.cc (revision 3151)
+++ geraud/tufa_2008/gradient.cc (working copy)
@@ -1,60 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/gradient.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/core/alias/neighb2d.hh>
-
-#include <mln/morpho/elementary/gradient.hh>
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm output.pgm" << std::endl;
- std::cerr << "elementary gradient with c4" << std::endl;
- std::abort();
-}
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 3)
- usage(argv);
-
- image2d<int_u8> f;
- io::pgm::load(f, argv[1]);
- io::pgm::save(morpho::elementary::gradient(f, c4()),
- argv[2]);
-}
Index: geraud/tufa_2008/closing.cc
--- geraud/tufa_2008/closing.cc (revision 3151)
+++ geraud/tufa_2008/closing.cc (working copy)
@@ -1,64 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/closing.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/core/alias/neighb2d.hh>
-
-#include <mln/morpho/elementary/gradient.hh>
-#include <mln/morpho/closing_volume.hh>
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm lambda output.pgm" << std::endl;
- std::abort();
-}
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 4)
- usage(argv);
-
- image2d<int_u8> f;
- io::pgm::load(f, argv[1]);
- unsigned lambda = std::atoi(argv[2]);
- io::pgm::save(morpho::closing_volume(f,
- c4(),
- lambda),
- argv[3]);
-}
Index: geraud/tufa_2008/steps.2.cc
--- geraud/tufa_2008/steps.2.cc (revision 3151)
+++ geraud/tufa_2008/steps.2.cc (working copy)
@@ -1,259 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/steps.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/morpho/tree/data.hh>
-
-#include <mln/accu/count.hh>
-#include <mln/util/set.hh>
-
-#include <mln/labeling/regional_minima.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/morpho/closing_area.hh>
-#include <mln/data/fill.hh>
-#include <mln/opt/at.hh>
-
-
-namespace mln
-{
-
- template <typename I>
- void println_par(const I& par)
- {
- int nr = par.nrows(), nc = par.ncols();
- for (int r = 0; r < nr; ++r)
- {
- for (int c = 0; c < nc; ++c)
- if (opt::at(par, r,c) == point2d(r,c))
- std::cout << "( ) ";
- else
- std::cout << opt::at(par, r,c) << ' ';
- std::cout << std::endl;
- }
- }
-
- template <typename P>
- inline
- mln_value(P) find_root__(P& par, const mln_value(P)& x)
- {
- if (par(x) == x)
- return x;
- else
- return par(x) = find_root__(par, par(x));
- }
-
-
- template <typename I, typename A, typename N>
- mln_ch_value(I, util::set<unsigned>)
- compute_labels(const I& f, const A& a, const N& nbh,
- unsigned n_objects,
- bool echo = false)
- {
- if (echo)
- debug::println("f =", f);
-
- typedef p_array<mln_psite(I)> S;
- S s = level::sort_psites_increasing(a);
- // s maps increasing attributes.
-
- mln_ch_value(I, mln_site(I)) par;
- mln_ch_value(I, bool) deja_vu;
- mln_ch_value(I, util::set<unsigned>) labels;
- unsigned nbassins, current_n;
-
- // Initialization.
- {
- mln_piter(A) p(f.domain());
-
- // parent
- initialize(par, f);
- for_all(p)
- par(p) = p;
-
- // deja_vu
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
-
- // labels
- mln_ch_value(I, unsigned) regmin = labeling::regional_minima(a, nbh,
- nbassins);
- if (n_objects >= nbassins)
- {
- std::cerr << "The number of expected objects is higher than the number of regional minima!" << std::endl;
- std::abort();
- }
-
- if (echo)
- debug::println("regmin(f) =", regmin);
-
- initialize(labels, f);
- for_all(p)
- if (regmin(p) != 0) // p in a reg min of the attribute image
- labels(p).insert(regmin(p));
- }
-
- current_n = nbassins;
-
- // First pass.
- {
- mln_site(I) r;
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- for_all(n)
- if (a.domain().has(n) && deja_vu(n))
- {
- r = find_root__(par, n);
- if (r != p)
- {
- par(r) = p; // Union.
-
- if (labels(r).is_empty())
- // No-op.
- ;
- else
- if (labels(p).is_empty())
- labels(p) = labels(r);
- else
- if (labels(p) == labels(r))
- // No-op.
- ;
- else
- {
- labels(p).insert(labels(r));
- --current_n;
- if (current_n == n_objects && echo)
- {
- // Filtering.
- mln_concrete(I) g;
- initialize(g, f);
- mln_bkd_piter(S) p(s);
- for_all(p)
- if (par(p) == p)
- g(p) = f(p);
- else
- g(p) = g(par(p));
- debug::println("g =", g);
-
- // Testing.
- unsigned n_result;
- mln_ch_value(I, unsigned) g_regmin;
- g_regmin = labeling::regional_minima(g, nbh, n_result);
- debug::println("regmin(g) =", g_regmin);
-
- mln_invariant(n_result == n_objects);
- }
- }
- }
- }
- deja_vu(p) = true;
- }
- }
-
- mln_invariant(current_n == 1); // All labels are merged into a single set.
-
- return labels;
- }
-
-
-} // mln
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm n echo" << std::endl;
- std::cerr << "n: number of expected objects (n > 0)" << std::endl;
- std::cerr << "echo: 0 (silent) or 1 (verbose)" << std::endl;
- std::cerr << "merge using sets of labels from regional minima and save the highest label image" << std::endl;
- std::abort();
-}
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 4)
- usage(argv);
-
- typedef image2d<int_u8> I;
- I f;
- // input image
- io::pgm::load(f, argv[1]);
-
- // n
- int n = std::atoi(argv[2]);
- if (n <= 0)
- usage(argv);
-
- // echo
- int echo = std::atoi(argv[3]);
- if (echo != 0 && echo != 1)
- usage(argv);
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- // Children go towards lower levels so leafs are regional minima.
- // We get a min-tree so that we can perform morphological closings.
-
- morpho::tree::data<I,S> t(f, s, c4());
- accu::count< util::pix<I> > attr;
-
- image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
-
-
- image2d< util::set<unsigned> > labels = compute_labels(f, a, c4(), n, echo);
- if (echo)
- debug::println("labels =", labels);
-
- {
- image2d<unsigned> lab(f.domain());
- mln_piter_(I) p(f.domain());
- for_all(p)
- {
- mln_assertion(! labels(p).is_empty());
- lab(p) = labels(p).last_element();
- }
- if (echo)
- debug::println("max of labels (clearly NOT the objects image!) =", lab);
-
- // We can observe that we do NOT get objects this way...
- }
-
-}
Index: geraud/tufa_2008/opening.cc
--- geraud/tufa_2008/opening.cc (revision 3151)
+++ geraud/tufa_2008/opening.cc (working copy)
@@ -1,63 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/opening.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/core/alias/neighb2d.hh>
-
-#include <mln/morpho/opening_volume.hh>
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm lambda output.pgm" << std::endl;
- std::abort();
-}
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 4)
- usage(argv);
-
- image2d<int_u8> f, g;
- io::pgm::load(f, argv[1]);
- unsigned lambda = std::atoi(argv[2]);
- initialize(g, f);
- morpho::opening_volume(f, c4(), lambda, g);
- io::pgm::save(g,
- argv[3]);
-}
Index: geraud/tufa_2008/steps.3.cc
--- geraud/tufa_2008/steps.3.cc (revision 3151)
+++ geraud/tufa_2008/steps.3.cc (working copy)
@@ -1,186 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/steps.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/morpho/tree/data.hh>
-
-#include <mln/accu/count.hh>
-#include <mln/util/set.hh>
-
-#include <mln/labeling/regional_minima.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/morpho/closing_area.hh>
-#include <mln/data/fill.hh>
-
-#include <mln/opt/at.hh>
-
-
-namespace mln
-{
-
- template <typename I>
- void println_par(const I& par)
- {
- int nr = par.nrows(), nc = par.ncols();
- for (int r = 0; r < nr; ++r)
- {
- for (int c = 0; c < nc; ++c)
- if (opt::at(par, r,c) == point2d(r,c))
- std::cout << "( ) ";
- else
- std::cout << opt::at(par, r,c) << ' ';
- std::cout << std::endl;
- }
- }
-
- template <typename P>
- inline
- mln_value(P) find_root__(P& par, const mln_value(P)& x)
- {
- if (par(x) == x)
- return x;
- else
- return par(x) = find_root__(par, par(x));
- }
-
-
- template <typename I, typename A, typename N>
- void run_run(const I& f, const A& a, const N& nbh)
- {
- typedef p_array<mln_psite(I)> S;
- S s = level::sort_psites_increasing(a);
- // s maps increasing attributes.
-
- mln_ch_value(I, mln_site(I)) par;
- mln_ch_value(I, bool) deja_vu;
- mln_ch_value(I, util::set<unsigned>) labels;
- unsigned nbassins, current_n;
-
-
- // Initialization.
- {
- mln_piter(A) p(f.domain());
-
- // parent
- initialize(par, f);
- for_all(p)
- par(p) = p;
-
- // deja_vu
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
-
- // labels
- mln_ch_value(I, unsigned) regmin = labeling::regional_minima(a, nbh,
- nbassins);
- initialize(labels, f);
- for_all(p)
- if (regmin(p) != 0) // p in a reg min of the attribute image
- labels(p).insert(regmin(p));
- }
-
- current_n = nbassins;
-
- // First pass.
- {
- mln_site(I) r;
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- for_all(n)
- if (a.domain().has(n) && deja_vu(n))
- {
- r = find_root__(par, n);
- if (r != p)
- {
- par(r) = p; // Union.
-
- if (labels(r).is_empty())
- // No-op.
- ;
- else
- if (labels(p).is_empty())
- labels(p) = labels(r);
- else
- if (labels(p) == labels(r))
- // No-op.
- ;
- else
- {
- labels(p).insert(labels(r));
- --current_n;
- }
- }
- }
- deja_vu(p) = true;
- }
- }
-
- std::cout << std::endl;
- std::cout << "end = " << current_n << std::endl;
- }
-
-
-} // mln
-
-
-
-
-int main(int, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- int_u8 n;
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, argv[1]);
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- // Children go towards lower levels so leafs are regional minima.
- // We get a min-tree so that we can perform morphological closings.
-
- morpho::tree::data<I,S> t(f, s, c4());
- accu::count< util::pix<I> > attr;
-
- image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
- run_run(f, a, c4());
-
-}
Index: geraud/tufa_2008/steps.2b.cc
--- geraud/tufa_2008/steps.2b.cc (revision 3151)
+++ geraud/tufa_2008/steps.2b.cc (working copy)
@@ -1,185 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/steps.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/morpho/tree/data.hh>
-
-#include <mln/accu/count.hh>
-#include <set>
-
-#include <mln/labeling/regional_minima.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/morpho/closing_area.hh>
-#include <mln/data/fill.hh>
-#include <mln/opt/at.hh>
-
-
-namespace mln
-{
-
- template <typename I>
- void println_par(const I& par)
- {
- int nr = par.nrows(), nc = par.ncols();
- for (int r = 0; r < nr; ++r)
- {
- for (int c = 0; c < nc; ++c)
- if (opt::at(par, r,c) == point2d(r,c))
- std::cout << "( ) ";
- else
- std::cout << opt::at(par, r,c) << ' ';
- std::cout << std::endl;
- }
- }
-
- template <typename P>
- inline
- mln_value(P) find_root__(P& par, const mln_value(P)& x)
- {
- if (par(x) == x)
- return x;
- else
- return par(x) = find_root__(par, par(x));
- }
-
-
- template <typename I, typename A, typename N>
- void run_run(const I& f, const A& a, const N& nbh)
- {
- typedef p_array<mln_psite(I)> S;
- S s = level::sort_psites_increasing(a);
- // s maps increasing attributes.
-
- mln_ch_value(I, mln_site(I)) par;
- mln_ch_value(I, bool) deja_vu;
- mln_ch_value(I, std::set<unsigned>) labels;
- unsigned nbassins, current_n;
-
-
- // Initialization.
- {
- mln_piter(A) p(f.domain());
-
- // parent
- initialize(par, f);
- for_all(p)
- par(p) = p;
-
- // deja_vu
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
-
- // labels
- mln_ch_value(I, unsigned) regmin = labeling::regional_minima(a, nbh,
- nbassins);
- initialize(labels, f);
- for_all(p)
- if (regmin(p) != 0) // p in a reg min of the attribute image
- labels(p).insert(regmin(p));
- }
-
- current_n = nbassins;
-
- // First pass.
- {
- mln_site(I) r;
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- for_all(n)
- if (a.domain().has(n) && deja_vu(n))
- {
- r = find_root__(par, n);
- if (r != p)
- {
- par(r) = p; // Union.
-
- if (labels(r).empty())
- // No-op.
- ;
- else
- if (labels(p).empty())
- labels(p) = labels(r);
- else
- if (labels(p) == labels(r))
- // No-op.
- ;
- else
- {
- labels(p).insert(labels(r).begin(), labels(r).end());
- --current_n;
- }
- }
- }
- deja_vu(p) = true;
- }
- }
-
- std::cout << std::endl;
- std::cout << "end = " << current_n << std::endl;
- }
-
-
-} // mln
-
-
-
-
-int main(int, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- int_u8 n;
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, argv[1]);
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- // Children go towards lower levels so leafs are regional minima.
- // We get a min-tree so that we can perform morphological closings.
-
- morpho::tree::data<I,S> t(f, s, c4());
- accu::count< util::pix<I> > attr;
-
- image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
- run_run(f, a, c4());
-
-}
Index: geraud/tufa_2008/filter_n.cc
--- geraud/tufa_2008/filter_n.cc (revision 3151)
+++ geraud/tufa_2008/filter_n.cc (working copy)
@@ -1,341 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/soluce.cc
-
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/morpho/tree/data.hh>
-
-#include <mln/accu/count.hh>
-#include <mln/util/set.hh>
-
-#include <mln/labeling/regional_minima.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/morpho/closing_area.hh>
-#include <mln/data/fill.hh>
-#include <mln/opt/at.hh>
-
-
-
-namespace mln
-{
-
- template <typename I>
- void println_par(const I& par)
- {
- int nr = par.nrows(), nc = par.ncols();
- for (int r = 0; r < nr; ++r)
- {
- for (int c = 0; c < nc; ++c)
- if (opt::at(par, r,c) == point2d(r,c))
- std::cout << "( ) ";
- else
- std::cout << opt::at(par, r,c) << ' ';
- std::cout << std::endl;
- }
- }
-
- template <typename I>
- struct my_less_
- {
- const I& ima_;
-
- inline
- my_less_(const I& ima)
- : ima_(ima)
- {
- }
-
- inline
- bool operator()(const mln_site(I)& lhs,
- const mln_site(I)& rhs) const
- {
- return util::ord_strict(ima_(lhs), ima_(rhs))
- || (ima_(lhs) == ima_(rhs)
- &&
- util::ord_strict(lhs, rhs));
- }
- };
-
-
- template <typename I, typename S>
- p_array<mln_site(I)> my_sort_increasing(const I& ima, const S& s)
- {
- p_array<mln_site(I)> v;
- convert::from_to(s, v);
- std::sort(v.hook_std_vector_().begin(), v.hook_std_vector_().end(),
- my_less_<I>(ima));
- return v;
- }
-
-
-
- // FIXME: HERE
-
- template <typename A, typename T, typename N>
- inline
- mln_concrete(typename T::function)
- get_attribute_image(const A& a, const T& t, const N& nbh,
- unsigned n_objects,
- bool echo = false)
- {
- typedef typename T::function I;
-
-
- unsigned n_regmins_f;
- mln_ch_value(I, unsigned) regmins_f = labeling::regional_minima(t.f(), nbh, n_regmins_f);
- if (echo)
- {
- debug::println("f =", t.f());
- debug::println("regmins(f) =", regmins_f);
- debug::println("par on nodes = ", t.parent_image() | t.nodes());
- std::cout << "n regmins(f) = " << n_regmins_f << std::endl
- << std::endl;
- }
- if (n_objects >= n_regmins_f)
- {
- std::cout << "warning: number of expected objects is greater than number of regmins!" << std::endl;
- std::cout << "aborting..." << std::endl;
- return duplicate(t.f());
- }
-
- // Compute attribute on nodes.
- // ---------------------------
-
-
- mln_ch_value(I, A) acc;
- initialize(acc, t.f());
-
-
- mln_ch_value(I, unsigned) nchildren;
- initialize(nchildren, t.f());
- data::fill(nchildren, 0);
-
- {
- // Transmit "dynamic data" (state) of 'a' to every values of
- // 'acc'. It is usually a no-op (so useless) except for a
- // few accumulators, e.g., for accu::rank which has the 'k'
- // attribute.
- data::fill(acc, a);
- }
- {
- // Initialize every attribute with the corresponding pixel.
- mln_piter(I) p(t.f().domain());
- for_all(p)
- acc(p).take_as_init(make::pix(t.f(), p));
- }
- {
- mln_fwd_piter(T) p(t.domain());
- // Propagate attribute from a site to its parent.
- for_all(p)
- if (! t.is_root(p))
- {
- acc(t.parent(p)).take(acc(p));
- if (t.is_a_node(p))
- ++nchildren(t.parent(p)); // so parent(p) is a node
- }
- // Back-propagate attribute from a node to sites of its
- // component. Below, p is a non-node component site and
- // parent(p) is a node, that is, the site representative of
- // the component p belongs to.
- for_all(p)
- if (! t.is_a_node(p))
- {
- mln_assertion(t.is_a_node(t.parent(p)));
- acc(p) = acc(t.parent(p));
- }
- }
-
- if (echo)
- debug::println("nchildren =", nchildren | t.nodes());
-
- typedef typename T::function I;
- mln_ch_value(I, mln_result(A)) attr;
- {
- // Change accumulator into its result.
- initialize(attr, acc);
- mln_piter(I) p(t.f().domain());
- for_all(p)
- if (t.is_a_node(p))
- attr(p) = acc(p).to_result();
- }
-
- if (echo)
- debug::println("attr on nodes = ", attr | t.nodes());
-
-
-
- // ...
- // ---------------------------
-
-
- unsigned lambda = mln_max(unsigned);
-
-
- typedef p_array<mln_site(I)> S;
- S s = my_sort_increasing(attr, t.nodes());
-
- const typename T::parent_t& par = t.parent_image();
-
- unsigned
- count = n_regmins_f,
- less = 0;
- mln_fwd_piter(S) p(s);
- for_all(p)
- {
- if (attr(p) < lambda && par(p) != p)
- {
- mln_assertion(nchildren(par(p)) > 0);
- --nchildren(par(p));
- if (nchildren(par(p)) != 0)
- {
- if (count <= n_objects)
- {
- ++less; // minus 1 object wrt the expected number!
- }
- --count;
- if (count == n_objects)
- {
- lambda = attr(p) + 1;
- std::cout << "lambda = " << lambda << std::endl
- << std::endl;
- // break; // Stop iterations.
- }
- }
- }
- }
-
- if (less != 0)
- std::cerr << "WARNING: less objects (" << less << ") than expected..." << std::endl
- << std::endl;
-
- if (echo)
- debug::println("nchildren =", nchildren | t.nodes());
-
-
- // Filtering.
- mln_concrete(I) g;
- {
- initialize(g, t.f());
- mln_bkd_piter(T) p(t.domain());
- for_all(p)
- if (t.is_a_node(p) && attr(p) >= lambda)
- g(p) = t.f(p);
- else
- g(p) = g(par(p));
-
- if (echo)
- debug::println("g =", g);
- }
-
- // Test!
- {
- mln_concrete(I) g_ref = morpho::closing_area(t.f(), nbh, lambda);
- if (echo)
- debug::println("g_ref =", g_ref);
-
- unsigned n_regmins_g_ref;
- mln_ch_value(I, unsigned) regmin_g = labeling::regional_minima(g_ref, nbh, n_regmins_g_ref);
- if (echo)
- std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
- << std::endl;
-
- if (g != g_ref)
- std::cerr << "OOPS: g DIFFERS FROM ref!" << std::endl
- << std::endl;
-
- bool consistency = (n_regmins_g_ref + less == n_objects);
- if (consistency == false)
- std::cerr << "OOPS: INCONSISTENCY (BUG...)!" << std::endl
- << std::endl;
- }
-
- return g;
- }
-
-
-} // mln
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm n output.pgm echo" << std::endl;
- std::cerr << "n: number of expected objects (n > 0)" << std::endl;
- std::cerr << "echo: 0 (silent) or 1 (verbose)" << std::endl;
- std::cerr << "filter" << std::endl;
- std::abort();
-}
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 5)
- usage(argv);
-
- typedef image2d<int_u8> I;
- I f;
- // input image
- io::pgm::load(f, argv[1]);
-
- // n
- int n = std::atoi(argv[2]);
- if (n <= 0)
- usage(argv);
-
- // echo
- int echo = std::atoi(argv[4]);
- if (echo != 0 && echo != 1)
- usage(argv);
-
- neighb2d nbh = c4();
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- // Children go towards lower levels so leafs are regional minima.
- // We get a min-tree so that we can perform morphological closings.
-
- typedef morpho::tree::data<I,S> tree_t;
- tree_t t(f, s, nbh);
-
- accu::count< util::pix<I> > attr;
- I g = get_attribute_image(attr, t, nbh, n, echo);
- io::pgm::save(g, argv[3]);
-}
Index: geraud/tufa_2008/wst_f_equal_wst_a.cc
--- geraud/tufa_2008/wst_f_equal_wst_a.cc (revision 3151)
+++ geraud/tufa_2008/wst_f_equal_wst_a.cc (working copy)
@@ -1,140 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/steps.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/pw/all.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/ppm/save.hh>
-#include <mln/io/pbm/save.hh>
-#include <mln/literal/black.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/level/transform.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/morpho/tree/data.hh>
-
-#include <mln/accu/volume.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/morpho/meyer_wst.hh>
-
-#include <mln/labeling/regional_minima.hh>
-
-#include <mln/core/var.hh>
-
-
-namespace mln
-{
-
- struct colorize : Function_v2v< colorize >
- {
- typedef value::rgb8 result;
- colorize(unsigned max)
- : lut(max + 1)
- {
- lut[0] = literal::black;
- for (unsigned i = 1; i <= max; ++i)
- lut[i] = result(100 + std::rand() % 150,
- 100 + std::rand() % 150,
- 100 + std::rand() % 150);
- }
- result operator()(unsigned i) const
- {
- return lut[i];
- }
- std::vector<result> lut;
- };
-
-} // mln
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm" << std::endl;
- std::abort();
-}
-
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 2)
- usage(argv);
-
- unsigned nref, n;
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, argv[1]);
-
- labeling::regional_minima(f, c4(), nref);
- std::cout << nref << std::endl;
-
-
- image2d<unsigned> wst_f = morpho::meyer_wst(f, c4(), n);
- mln_assertion(n == nref);
-
- io::ppm::save(level::transform(wst_f, colorize(n)),
- "wst_f.ppm");
- mln_VAR(WST_f, (pw::value(wst_f) == pw::cst(0u)) | f.domain());
- io::pbm::save(WST_f, "wst_f.pbm");
-
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- // Children go towards lower levels so leafs are regional minima.
- // We get a min-tree so that we can perform morphological closings.
-
- morpho::tree::data<I,S> t(f, s, c4());
- accu::volume<I> vol;
- image2d<unsigned> a = morpho::tree::compute_attribute_image(vol, t);
-
- labeling::regional_minima(a, c4(), n);
- mln_assertion(n == nref);
-
-
- image2d<unsigned> wst_a = morpho::meyer_wst(a, c4(), n);
- mln_assertion(n == nref);
-
- io::ppm::save(level::transform(wst_a, colorize(n)),
- "wst_a.ppm");
- mln_VAR(WST_a, (pw::value(wst_a) == pw::cst(0u)) | f.domain());
- io::pbm::save(WST_a, "wst_a.pbm");
-
-
- io::pbm::save((pw::value(WST_a) != pw::value(WST_f)) | f.domain(),
- "diff.pbm");
-}
Index: geraud/tufa_2008/compute_a.cc
--- geraud/tufa_2008/compute_a.cc (revision 3151)
+++ geraud/tufa_2008/compute_a.cc (working copy)
@@ -1,412 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/compute_a.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/image/image_if.hh>
-#include <mln/pw/all.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/data/fill.hh>
-#include <mln/data/paste.hh>
-#include <mln/level/compare.hh>
-
-#include <mln/morpho/tree/data.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/labeling/regional_minima.hh>
-
-#include <mln/accu/count.hh>
-#include <mln/opt/at.hh>
-
-
-
-namespace mln
-{
-
- template <typename I>
- void println_par(const I& par)
- {
- int nr = par.nrows(), nc = par.ncols();
- for (int r = 0; r < nr; ++r)
- {
- for (int c = 0; c < nc; ++c)
- if (opt::at(par, r,c) == point2d(r,c))
- std::cout << "( ) ";
- else
- std::cout << opt::at(par, r,c) << ' ';
- std::cout << std::endl;
- }
- }
-
-
- template <typename P>
- inline
- mln_value(P) find_root__(P& par, const mln_value(P)& x)
- {
- if (par(x) == x)
- return x;
- else
- return par(x) = find_root__(par, par(x));
- }
-
-
-
- //------------------------------- compute_a
-
-
-
- template <typename I, typename N, typename A>
- mln_ch_value(I, mln_result(A))
- compute_a(const I& f, const N& nbh, A, unsigned& n_regmins)
- {
- typedef p_array<mln_psite(I)> S;
- S s = level::sort_psites_increasing(f);
- // s maps increasing attributes.
-
- mln_ch_value(I, mln_site(I)) par;
- mln_ch_value(I, mln_site(I)) zpar;
- mln_ch_value(I, bool) deja_vu, flag;
- mln_ch_value(I, A) attr;
-
- n_regmins = f.domain().nsites();
-
-
- // Initialization.
- {
- // parent
- initialize(par, f);
- initialize(zpar, f);
-
- // deja_vu
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
-
- // flag
- initialize(flag, f);
- data::fill(flag, true);
-
- // attr
- initialize(attr, f);
- }
-
-
- // First Pass.
- {
- mln_site(I) r;
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- // Make-Set.
- par(p) = p;
- zpar(p) = p;
- attr(p).take_as_init(p);
-
- for_all(n)
- if (f.domain().has(n) && deja_vu(n))
- {
- r = find_root__(zpar, n);
- if (r != p)
- {
- // Fully compressed union.
- zpar(r) = p;
- attr(p).take(attr(r));
-
- if (f(r) == f(p))
- {
- // Weak-Union; only for flat zones.
- par(r) = p;
-
- if (flag(p) == false && flag(r) == false)
- {
- // Two non-reg-min components merge (same flat
- // zone) so we had an extra invalidation.
- ++n_regmins;
- }
- flag(p) = flag(p) && flag(r);
- --n_regmins; // So we get the number of flat zones
- // minus the non-reg-min flat zones.
- }
- else
- {
- mln_invariant(f(r) < f(p));
- if (flag(p) == true)
- --n_regmins; // Invalidation.
- flag(p) = false;
- }
- }
- }
- deja_vu(p) = true;
- }
- } // end of First Pass.
-
-
- std::cout << "n reg min = " << n_regmins << std::endl;
-
-
- {
- unsigned n = 0;
- mln_fwd_piter(S) p(s);
- for_all(p)
- if (par(p) == p && flag(p))
- ++n;
- mln_assertion(n == n_regmins);
- }
-
-
- // The attr image is not correct on flat zones since there is
- // no back-propagation of the attribute value of the component
- // root. For instance with f="v v v" we get attr="1 2 3"
- // instead of "3 3 3". So a finalization is required.
-
- mln_ch_value(I, mln_result(A)) a;
- initialize(a, f);
- data::paste(attr, a);
-
- // Finalization.
- {
- mln_bkd_piter(S) p(s); // Reverse.
-
- unsigned n_non_compressed_par = 0;
- for_all(p)
- {
- a(p) = a(par(p));
- if (par(par(p)) != par(p))
- ++ n_non_compressed_par;
- }
- std::cout << "n_non_compressed_par = " << n_non_compressed_par << std::endl;
- }
-
- // TODO: compress at least the reg minima!
-
-
- {
- image2d<unsigned> regmin;
- initialize(regmin, f);
- {
- unsigned i_regmin = 0;
- mln_bkd_piter(S) p(s);
- for_all(p)
- {
- if (par(p) == p)
- {
- if (flag(p))
- regmin(p) = ++i_regmin;
- else
- regmin(p) = 0;
- }
- else
- regmin(p) = regmin(par(p));
- }
- }
-
- debug::println("f", f);
-
- debug::println("flag", flag);
- // We can see that some point are at true for components that
- // are not reg min; flag is a candidate to be compressed...
-
- debug::println("regmin", regmin);
-
-
-
- // TODO:
-
- // On veut tester ici dans quel ordre on voit les
- // reg min lorsque a croit. Pour tous les points d'un reg min,
- // est-ce que le root est vu en premier ?
-
-
-
- image2d<bool> seen;
- initialize(seen, f);
- data::fill(seen, false);
-
- s = level::sort_psites_increasing(a);
- mln_bkd_piter(S) p(s);
- for_all(p)
- {
- if (regmin(p) == 0)
- continue;
- // p is in a regional minimum.
- if (par(p) != p) // A non-root point.
- {
- mln_assertion(regmin(par(p)) != 0); // Root in a regional minimum.
- mln_assertion(regmin(par(p)) == regmin(p)); // and the same as p.
- mln_assertion(seen(par(p)));
- }
- seen(p) = true;
- }
- debug::println(seen);
-
-// if (flag(p))
-// std::cout << a(p) << ' ' << p << ' ' << (par(p) == p) << std::endl;
-
- }
-
- return a;
- }
-
-
-
- //------------------------------- filtering
-
-
-
-// template <typename I, typename A, typename N>
-// mln_concrete(I) filtering(const I& f, const A& a, const N& nbh,
-// unsigned n_regmins, unsigned n_wanted)
-// {
-// typedef p_array<mln_psite(I)> S;
-// S s = level::sort_psites_increasing(a);
-
-// // s maps increasing attributes.
-
-// mln_concrete(I) out;
-// initialize(out, f);
-
-// mln_ch_value(I, mln_site(I)) par;
-// mln_ch_value(I, bool) deja_vu, flag;
-
-// // Initialization.
-// {
-// initialize(par, f);
-// mln_piter(A) p(par.domain());
-// for_all(p)
-// par(p) = p;
-// initialize(deja_vu, f);
-// data::fill(deja_vu, false);
-
-// // flag
-// initialize(flag, f);
-// data::fill(flag, true);
-// }
-
-
-// int counter = 0;
-// // We are trying to count the number of merges of regional minima...
-
-
-// // First Pass.
-// {
-// mln_site(I) r;
-// mln_fwd_piter(S) p(s);
-// mln_niter(N) n(nbh, p);
-// for_all(p)
-// {
-// for_all(n)
-// if (a.domain().has(n) && deja_vu(n))
-// {
-// r = find_root__(par, n);
-// if (r != p)
-// if (a(r) == a(p))
-// {
-// par(r) = p; // Union.
-// if (flag(r) == true && flag(p) == true)
-// --counter;
-// flag(p) = flag(p) && flag(r);
-// }
-// else // a(r) != a(p)
-// {
-// if (flag(r) == true && flag(p) == true)
-// ++counter;
-// mln_invariant(a(p) > a(r));
-// flag(p) = false;
-// }
-// }
-// deja_vu(p) = true;
-// }
-// std::cout << counter << std::endl;
-// }
-
-// // // Second Pass.
-// // {
-// // mln_bkd_piter(S) p(s);
-// // for_all(p)
-// // if (par(p) == p)
-// // out(p) = f(p);
-// // else
-// // out(p) = out(par(p));
-// // }
-
-// return out;
-// }
-
-
-
-
-} // mln
-
-
-
-
-int main(int, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, argv[1]);
- // debug::println(f);
-
- accu::count<point2d> area;
- unsigned n_regmins;
- image2d<unsigned> a = compute_a(f, c4(), area, n_regmins);
- // debug::println(a);
-
-// {
-// // Test of 'n_regmins'.
-// unsigned ref;
-// labeling::regional_minima(f, c4(), ref);
-// mln_assertion(n_regmins == ref);
-// }
-
-// {
-// // Test of 'a'.
-// typedef p_array<point2d> S;
-// S s = level::sort_psites_decreasing(f);
-// morpho::tree::data<I,S> t(f, s, c4());
-// accu::count< util::pix<I> > area;
-// image2d<unsigned> ref = morpho::tree::compute_attribute_image(area, t);
-// mln_assertion(a == ref);
-// }
-
-
-
-
-
-// unsigned n_wanted = 10;
-// I g = filtering(f, a, c4(), n_regmins, n_wanted);
-
-}
Index: geraud/tufa_2008/wst.cc
--- geraud/tufa_2008/wst.cc (revision 3151)
+++ geraud/tufa_2008/wst.cc (working copy)
@@ -1,69 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file wst.cc
-
-#include <iostream>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/var.hh>
-
-#include <mln/value/int_u8.hh>
-
-#include <mln/data/fill.hh>
-#include <mln/level/replace.hh>
-#include <mln/morpho/meyer_wst.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm output.pgm" << std::endl;
- std::abort();
-}
-
-
-int main(int argc, char* argv [])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 3)
- usage(argv);
-
-
- image2d<int_u8> input;
- io::pgm::load(input, argv[1]);
-
- int_u8 nbasins;
- image2d<int_u8> output = morpho::meyer_wst(input, c4(), nbasins);
- std::cout << "n basins = " << nbasins << std::endl;
- io::pgm::save(output, argv[2]);
-}
Index: geraud/tufa_2008/experiment.cc
--- geraud/tufa_2008/experiment.cc (revision 3151)
+++ geraud/tufa_2008/experiment.cc (working copy)
@@ -1,138 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/experiment.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/literal/black.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/morpho/tree/data.hh>
-
-#include <mln/accu/volume.hh>
-#include <mln/win/disk2d.hh>
-
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/morpho/meyer_wst.hh>
-#include <mln/morpho/opening.hh>
-#include <mln/morpho/closing_area.hh>
-
-#include <mln/data/fill.hh>
-
-#include <mln/level/transform.hh>
-#include <mln/level/stretch.hh>
-
-
-
-namespace mln
-{
-
- struct colorize : Function_v2v< colorize >
- {
- typedef value::rgb8 result;
- colorize(unsigned max)
- : lut(max + 1)
- {
- lut[0] = literal::black;
- for (unsigned i = 1; i <= max; ++i)
- lut[i] = result(100 + std::rand() % 150,
- 100 + std::rand() % 150,
- 100 + std::rand() % 150);
- }
- result operator()(unsigned i) const
- {
- return lut[i];
- }
- std::vector<result> lut;
- };
-
-} // mln
-
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm" << std::endl;
- std::abort();
-}
-
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 2)
- usage(argv);
-
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, argv[1]);
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- // Children go towards lower levels so leafs are regional minima.
- // We get a min-tree so that we can perform morphological closings.
-
- morpho::tree::data<I,S> t(f, s, c4());
- accu::volume<I> attr;
-
- image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
- io::pgm::save(level::stretch(int_u8(), a),
- "a.pgm");
-
- unsigned n;
- image2d<unsigned> wst_a = morpho::meyer_wst(a, c4(), n);
- io::ppm::save(level::transform(wst_a, colorize(n)),
- "wst_a.ppm");
- std::cout << "n(a) = " << n << std::endl;
-
- // FIXME: ça n'a pas de sens de faire ce qui est dessous... :-(
-
-
- image2d<unsigned> aa = morpho::closing_area(a, c4(), 100);
- io::pgm::save(level::stretch(int_u8(), aa),
- "aa.pgm");
-
- image2d<unsigned> wst_aa = morpho::meyer_wst(aa, c4(), n);
- io::ppm::save(level::transform(wst_aa, colorize(n)),
- "wst_aa.ppm");
- std::cout << "n(aa) = " << n << std::endl;
-}
Index: geraud/tufa_2008/n_cmpt.cc
--- geraud/tufa_2008/n_cmpt.cc (revision 3151)
+++ geraud/tufa_2008/n_cmpt.cc (working copy)
@@ -1,263 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/neighb2d.hh>
-
-#include <mln/value/int_u8.hh>
-#include <mln/value/int_u16.hh>
-#include <mln/io/pgm/load.hh>
-
-#include <mln/debug/println.hh>
-#include <mln/debug/iota.hh>
-
-#include <mln/labeling/regional_minima.hh>
-#include <mln/data/fill.hh>
-
-#include <mln/morpho/tree/data.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-
-#include <mln/accu/volume.hh>
-#include <mln/accu/count.hh>
-
-
-namespace mln
-{
-
- template <typename I>
- inline
- mln_psite(I) find_root__(I& parent, const mln_psite(I)& x)
- {
- if (parent(x) == x)
- return x;
- else
- return parent(x) = find_root__(parent, parent(x));
- }
-
-
- template <typename A, typename I, typename N>
- mln_concrete(I)
- n_cmpt(A a, const I& f, const N& nbh, unsigned lambda)
- {
- // Compute attribute image.
- //-------------------------
-
- typedef p_array<mln_psite(I)> S;
- typedef mln_ch_value(I, mln_result(A)) Attr;
-
- S s = level::sort_psites_decreasing(f);
- morpho::tree::data<I,S> t(f, s, nbh);
- Attr attr = morpho::tree::compute_attribute_image(a, t);
- s = level::sort_psites_increasing(attr);
- debug::println("attr =", attr);
-
-
- // Compute regional minima of attribute image.
- //--------------------------------------------
-
- unsigned label;
- mln_ch_value(I, unsigned) min_v = labeling::regional_minima(attr, nbh, label);
- debug::println("regmin =", min_v);
-
- // number of minima
- unsigned cmpts = label;
- if (lambda > cmpts)
- std::cout << "Warning: lambda value is too high!" << std::endl;
-
- std::cout << cmpts << std::endl;
-
-
- // two pass algo
- //--------------
-
- // init fused image
- mln_ch_value(I, bool) fused;
- initialize(fused, attr);
- mln::data::fill(fused, false);
-
- // prepare union find
- typedef mln_psite(I) P;
-
- //deja_vu
- mln_ch_value(I, bool) deja_vu;
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
-
- //parent
- mln_ch_value(I, P) parent(attr.domain());
- {
- mln_fwd_piter(S) p(s);
- for_all(p)
- {
- parent(p) = p;
-
- // Mandatory since we propagate fused
- if (min_v(p) != 0) // p in a reg min of the attribute image
- fused(p) = true; // ok
- }
- }
-
- // UNION FIND ON ATTR
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- // std::cout << p << std::endl;
- for_all(n)
- {
- if (attr.domain().has(n) && deja_vu(n))
- {
- P r = find_root__(parent, n);
- if (r != p)
- {
- // std::cout << "neighb: " << n << std::endl;
- // std::cout << "v(r): " << attr(r) << " v(p): "
- // << attr(p) << " f(p): " << fused(p) << std::endl;
-
- //if (attr(r) != attr(p)) // r and p have different attrs
- // This check was wrong.
- // you just fused with a minima.
- // then you fuse with a neighbor already fused that has the same attr as you
- // a) 1 50 1
- // 2 2 2
- // we don't have ( attr(r) == attr(p) ) => not fused(r)
- // even if r and p are not minima
-
- // problem :
- // - when fusing minima : same level, both fused. NOT DEC
- // - when fusing cmpts (a) : same level, both fused. DEC
-
- // One cmpt less if
-
-// if (fused(r) && min_v(p) == 0) // p is not a minima
-// if (fused(p)) // p already belong to a cmpt (fused for an another n)
-// if (cmpts >= lambda) // union is still allowed
-
- if (fused(r) && min_v(p) == 0 // p is not a minima
- && fused(p) // p already belong to a cmpt (fused for an another n)
- && cmpts >= lambda) // union is still allowed
- {
- --cmpts;
- // std::cout << "dec" << std::endl;
- }
-
- mln_invariant(fused(r) || attr(r) == attr(p));
-
- // Union made if
- if (cmpts >= lambda || // union is still allowed or
- ! fused(r) || // r not fused or
- ! fused(p) || // p not fused or
- min_v(p) != 0) // p is a minima
- {
- // std::cout << "fusing " << p << " with " << n << std::endl;
- parent(r) = p;
-
- // This test is mandatory. Sometimes (--_) points are fused
- // tough none of these points belongs to a component (attached
- // to a local minima). In this case fused(p) must not be true
- // since it can be fused again without removing a component.
- // looking if r is fused should be enough.
- // This test force minima to be initialized fused.
- if (fused(r))
- fused(p) = true;
-
-
- // If I try to fuse with something never fused I am on a plateau.
- // not fused(r) => ( attr(r) == attr(p) )
- mln_invariant(fused(r) || attr(r) == attr(p));
- // fused(r) and ( attr(r) == attr(p) ) happen on minima plateau.
-
- // fused(n) = true; // useless ? probably yes because when we
- // want to know that we really fuse component, we look at
- // fused(r) not n.
- // fused(n) is not an invariant: --_. And it is ok (I think).
- // We don't have to retro-propagate fused.
-
-
- // std::cout << "attr " << attr(p) << " - " << cmpts << std::endl;
- //debug::println(fused);
- }
- }
- }
- }
- deja_vu(p) = true;
- }
-
- mln_ch_value(I,value::int_u<16>) iota(f.domain());
- debug::iota(iota);
-
- std::cout << std::endl;
- std::cout << "cmpts: " << cmpts << std::endl;
-
- // second pass
- mln_concrete(I) output;
- initialize(output, f);
- {
- mln_bkd_piter(S) p(s);
- for_all(p)
- if (parent(p) == p) // p is root.
- output(p) = iota(p);
- else
- output(p) = output(parent(p));
- }
-
- return output;
- }
-
-} // end of namespace mln
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm n" << std::endl;
- std::cerr << "n: expected number of basins" << std::endl;
- std::abort();
-}
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 3)
- usage(argv);
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, argv[1]);
- debug::println("f =", f);
-
- unsigned n = std::atoi(argv[2]);
-
- accu::count< util::pix<I> > acc;
- // accu::volume<I> acc;
-
- image2d<int_u8> g = n_cmpt(acc, f, c4(), n + 1);
- debug::println(g);
-}
Index: geraud/tufa_2008/filter.cc
--- geraud/tufa_2008/filter.cc (revision 3151)
+++ geraud/tufa_2008/filter.cc (working copy)
@@ -1,169 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/filter.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/literal/black.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/save.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/data/fill.hh>
-
-#include <mln/morpho/tree/data.hh>
-#include <mln/morpho/tree/compute_attribute_image.hh>
-#include <mln/morpho/closing_volume.hh>
-
-
-
-namespace mln
-{
-
- template <typename P>
- inline
- mln_value(P) find_root__(P& par, const mln_value(P)& x)
- {
- if (par(x) == x)
- return x;
- else
- return par(x) = find_root__(par, par(x));
- }
-
-
- template <typename I, typename A, typename N>
- mln_concrete(I) filtering(const I& f, const A& a, const N& nbh, mln_value(A) lambda)
- {
- typedef p_array<mln_psite(I)> S;
- S s = level::sort_psites_increasing(a);
-
- // s maps increasing attributes.
-
- mln_concrete(I) out;
- initialize(out, f);
-
- mln_ch_value(I, mln_site(I)) par;
- mln_ch_value(I, bool) deja_vu;
- {
- initialize(par, f);
- mln_piter(A) p(par.domain());
- for_all(p)
- par(p) = p;
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
- }
-
- // First pass.
- {
- mln_site(I) r;
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- for_all(n)
- if (a.domain().has(n) && deja_vu(n))
- {
- r = find_root__(par, n);
- if (r != p)
- if (f(r) == f(p) || a(r) < lambda)
- par(r) = p; // Union.
- }
- deja_vu(p) = true;
- }
- }
-
- // Second pass.
- {
- mln_bkd_piter(S) p(s);
- for_all(p)
- if (par(p) == p)
- out(p) = f(p);
- else
- out(p) = out(par(p));
- }
- return out;
- }
-
-
-} // mln
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm lambda output.pgm" << std::endl;
- std::abort();
-}
-
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 4)
- usage(argv);
-
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, argv[1]);
-
- unsigned lambda = std::atoi(argv[2]);
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- // Children go towards lower levels so leafs are regional minima.
- // We get a min-tree so that we can perform morphological closings.
-
- morpho::tree::data<I,S> t(f, s, c4());
- accu::volume<I> attr;
-
- image2d<unsigned> a = morpho::tree::compute_attribute_image(attr, t);
-
- I g = filtering(f, a, c4(), lambda);
-
- {
- I ref = morpho::closing_volume(f, c4(), lambda);
- if (g != ref)
- {
- io::pgm::save(ref, "ref.pgm");
- std::cerr << "oops!" << std::endl;
- }
- }
-
- io::pgm::save(g, argv[3]);
-}
Index: geraud/tufa_2008/closed_gradient.cc
--- geraud/tufa_2008/closed_gradient.cc (revision 3151)
+++ geraud/tufa_2008/closed_gradient.cc (working copy)
@@ -1,64 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/closed_gradient.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/core/alias/neighb2d.hh>
-
-#include <mln/morpho/elementary/gradient.hh>
-#include <mln/morpho/closing_volume.hh>
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm lambda output.pgm" << std::endl;
- std::abort();
-}
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 4)
- usage(argv);
-
- image2d<int_u8> f;
- io::pgm::load(f, argv[1]);
- unsigned lambda = std::atoi(argv[2]);
- io::pgm::save(morpho::closing_volume(morpho::elementary::gradient(f, c4()),
- c4(),
- lambda),
- argv[3]);
-}
Index: geraud/tufa_2008/fz_count.cc
--- geraud/tufa_2008/fz_count.cc (revision 3151)
+++ geraud/tufa_2008/fz_count.cc (working copy)
@@ -1,160 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/fz_count.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/core/alias/neighb2d.hh>
-
-#include <mln/labeling/regional_minima.hh>
-#include <mln/labeling/flat_zones.hh>
-#include <mln/data/fill.hh>
-#include <mln/opt/at.hh>
-
-
-namespace mln
-{
-
- template <typename I>
- void println_par(const I& par)
- {
- int nr = par.nrows(), nc = par.ncols();
- for (int r = 0; r < nr; ++r)
- {
- for (int c = 0; c < nc; ++c)
- if (opt::at(par, r,c) == point2d(r,c))
- std::cout << "( ) ";
- else
- std::cout << opt::at(par, r,c) << ' ';
- std::cout << std::endl;
- }
- }
-
- template <typename P>
- inline
- mln_value(P) find_root__(P& par, const mln_value(P)& x)
- {
- if (par(x) == x)
- return x;
- else
- return par(x) = find_root__(par, par(x));
- }
-
-
- template <typename I, typename N>
- unsigned fz_count(const I& f, const N& nbh)
- {
- typedef p_array<mln_psite(I)> S;
- S s = level::sort_psites_increasing(f);
- // s maps increasing attributes.
-
- mln_ch_value(I, mln_site(I)) par;
- mln_ch_value(I, bool) deja_vu;
-
- unsigned counter = f.domain().nsites();
-
- // Initialization.
- {
- mln_piter(I) p(f.domain());
-
- // parent
- initialize(par, f);
- for_all(p)
- par(p) = p;
-
- // deja_vu
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
- }
-
- // First pass.
- {
- mln_site(I) r;
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- for_all(n)
- if (f.domain().has(n) && deja_vu(n))
- {
- r = find_root__(par, n);
- if (r != p) // not already merged
- {
- if (f(r) == f(p))
- {
-
- // Moving the line below out of this test
- // (either before the test or after the block)
- // makes the algorithm fail.
- // The erroneous result is less than the ref
- // result => we want this current block too many
- // times. Since we merge (thru "par(r) = p")
- // whatever "f(r) == f(p)" is true or not, we
- // have more often "f(r) == f(p)" than expected.
- par(r) = p;
-
- --counter;
- }
- }
- }
-
- deja_vu(p) = true;
- }
- }
-
- return counter;
- }
-
-
-} // mln
-
-
-
-
-int main(int, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, argv[1]);
-
- unsigned ref, n = fz_count(f, c4());
- labeling::flat_zones(f, c4(), ref);
-
- if (n == ref)
- std::cout << "success: n flat zones = " << n << std::endl;
- else
- std::cout << "FAILURE: found = " << n << " v. ref = " << ref << std::endl;
-}
Index: geraud/tufa_2008/regmin_count.cc
--- geraud/tufa_2008/regmin_count.cc (revision 3151)
+++ geraud/tufa_2008/regmin_count.cc (working copy)
@@ -1,175 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file sandbox/geraud/tufa/regmin_count.cc
-
-#include <mln/core/image/image2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/debug/println.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/core/alias/neighb2d.hh>
-
-#include <mln/labeling/regional_minima.hh>
-#include <mln/labeling/flat_zones.hh>
-#include <mln/data/fill.hh>
-
-#include <mln/opt/at.hh>
-
-
-namespace mln
-{
-
- template <typename I>
- void println_par(const I& par)
- {
- int nr = par.nrows(), nc = par.ncols();
- for (int r = 0; r < nr; ++r)
- {
- for (int c = 0; c < nc; ++c)
- if (opt::at(par, r,c) == point2d(r,c))
- std::cout << "( ) ";
- else
- std::cout << opt::at(par, r,c) << ' ';
- std::cout << std::endl;
- }
- }
-
- template <typename P>
- inline
- mln_value(P) find_root__(P& par, const mln_value(P)& x)
- {
- if (par(x) == x)
- return x;
- else
- return par(x) = find_root__(par, par(x));
- }
-
-
- template <typename I, typename N>
- unsigned regmin_count(const I& f, const N& nbh)
- {
- typedef p_array<mln_psite(I)> S;
- S s = level::sort_psites_increasing(f);
- // s maps increasing attributes.
-
- mln_ch_value(I, mln_site(I)) par;
- mln_ch_value(I, bool) deja_vu, flag;
-
- unsigned counter = f.domain().nsites();
-
-
- // Initialization.
- {
- mln_piter(I) p(f.domain());
-
- // parent
- initialize(par, f);
- for_all(p)
- par(p) = p;
-
- // flag
- initialize(flag, f);
- data::fill(flag, true);
-
- // deja_vu
- initialize(deja_vu, f);
- data::fill(deja_vu, false);
- }
-
- // First pass.
- {
- mln_site(I) r;
- mln_fwd_piter(S) p(s);
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- unsigned loc = 0;
- for_all(n)
- if (f.domain().has(n) && deja_vu(n))
- {
- r = find_root__(par, n);
- if (r != p)
- {
- if (f(r) == f(p))
- {
- par(r) = p; // Union.
- if (flag(p) == false && flag(r) == false)
- {
- // Two non-reg-min components merge (same flat
- // zone) so we had an extra invalidation.
- ++counter;
- }
- flag(p) = flag(p) && flag(r);
- --counter; // So we get the number of flat zones
- // minus the non-reg-min flat zones.
- }
- else
- {
- mln_invariant(f(r) < f(p));
- if (flag(p) == true)
- {
- ++loc;
- --counter; // Invalidation.
- }
- flag(p) = false;
- }
- }
- }
- mln_invariant(loc == 0 || loc == 1);
- deja_vu(p) = true;
- }
- }
-
- return counter;
- }
-
-
-} // mln
-
-
-
-
-int main(int, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- typedef image2d<int_u8> I;
- I f;
- io::pgm::load(f, argv[1]);
-
- unsigned ref, n = regmin_count(f, c4());
- labeling::regional_minima(f, c4(), ref);
-
- if (n == ref)
- std::cout << "success: n regional minima = " << n << std::endl;
- else
- std::cout << "FAILURE: found = " << n << " v. ref = " << ref << std::endl;
-}
Index: geraud/estimate.hh
--- geraud/estimate.hh (revision 3151)
+++ geraud/estimate.hh (working copy)
@@ -1,90 +0,0 @@
-// Copyright (C) 2007 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_LABELING_ESTIMATE_HH
-# define MLN_LABELING_ESTIMATE_HH
-
-/*! \file mln/labeling/estimate.hh
- *
- * \brief Compute the estimate pixel value.
- */
-
-# include <mln/core/concept/image.hh>
-# include <mln/core/concept/neighborhood.hh>
-# include <mln/canvas/labeling.hh>
-
-# include <mln/accu/compute.hh>
-// # include <mln/core/image_if_value.hh>
-
-
-
-namespace mln
-{
-
- namespace labeling
- {
-
- /*! \brief Label a binary image and compute some estimations over
- * the components.
- *
- * \param[in] input The image.
- *
- * The free parameter \c A is a type of accumulator.
- *
- * FIXME: Not yet impled.
- */
- template <typename A, typename I>
- void
- estimate(const Image<I>& input);
-
-
-# ifndef MLN_INCLUDE_ONLY
-
- template <typename A, typename I>
- void
- estimate(const Image<I>& input)
- {
- trace::entering("labeling::estimate");
- mlc_equal(mln_trait_image_kind(I), mln::trait::image::kind::binary)::check();
- mln_precondition(exact(input).is_valid());
-
- std::cerr << "Sorry: mln::labeling::estimate is not yet implemented!" << std::endl;
-
- // FIXME: Was:
- // mln_accu_with(A, util::pix<I>)::result res = accu::compute<A>(input | val);
-
- trace::exiting("labeling::estimate");
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace mln::labeling
-
-} // end of namespace mln
-
-
-#endif // ! MLN_LABELING_ESTIMATE_HH
Index: geraud/laurent/wst_edge.cc
--- geraud/laurent/wst_edge.cc (revision 3151)
+++ geraud/laurent/wst_edge.cc (working copy)
@@ -1,409 +0,0 @@
-# include <mln/core/var.hh>
-
-# include <mln/core/image/image2d.hh>
-# include <mln/core/image/image_if.hh>
-# include <mln/core/image/extended.hh>
-# include <mln/core/routine/extend.hh>
-
-# include <mln/core/alias/window2d.hh>
-# include <mln/core/alias/neighb2d.hh>
-# include <mln/make/double_neighb2d.hh>
-# include <mln/core/site_set/p_centered.hh>
-
-# include <mln/literal/origin.hh>
-# include <mln/literal/black.hh>
-# include <mln/literal/white.hh>
-
-# include <mln/value/int_u8.hh>
-# include <mln/io/pgm/load.hh>
-# include <mln/io/pgm/save.hh>
-
-# include <mln/value/rgb8.hh>
-# include <mln/io/ppm/save.hh>
-
-# include <mln/accu/min_max.hh>
-# include <mln/accu/mean.hh>
-
-# include <mln/fun/i2v/array.hh>
-# include <mln/fun/p2v/iota.hh>
-
-# include <mln/data/paste.hh>
-# include <mln/data/fill.hh>
-# include <mln/level/transform.hh>
-# include <mln/extension/fill.hh>
-
-# include <mln/morpho/meyer_wst.hh>
-# include <mln/morpho/closing_volume.hh>
-
-# include <mln/opt/at.hh>
-
-# include <mln/debug/println.hh>
-
-
-
-// Functions
-
-inline
-bool is_row_odd(const mln::point2d& p)
-{
- return p.row() % 2;
-}
-
-inline
-bool is_cell(const mln::point2d& p)
-{
- return p.row() % 2 == 0 && p.col() % 2 == 0;
-}
-
-inline
-bool is_edge(const mln::point2d& p)
-{
- return p.row() % 2 + p.col() % 2 == 1;
-}
-
-inline
-bool is_point(const mln::point2d& p)
-{
- return p.row() % 2 && p.col() % 2;
-}
-
-
-inline
-bool is_not_edge(const mln::point2d& p)
-{
- return ! is_edge(p);
-}
-
-
-
-namespace mln
-{
-
- namespace border
- {
-
- template <typename I>
- void
- fill(I& ima, const mln_value(I)& v)
- {
- const int nrows = ima.nrows();
- const int ncols = ima.ncols();
- for (int r = -1; r <= nrows; ++r)
- {
- opt::at(ima, r, -1) = v;
- opt::at(ima, r, ncols) = v;
- }
- for (int c = -1; c <= ncols; ++c)
- {
- opt::at(ima, -1, c) = v;
- opt::at(ima, nrows, c) = v;
- }
- }
-
- } // mln::border
-
- namespace accu
- {
-
- template <typename I, typename L, typename A, typename V>
- inline
- void
- compute(const Image<I>& input_,
- const Image<L>& label_,
- const Accumulator<A>&,
- V& v)
- {
- trace::entering("accu::compute");
-
- const I& input = exact(input_);
- const L& label = exact(label_);
-
- const unsigned n = v.size();
- std::vector<A> a(n);
-
- mln_piter(I) p(input.domain());
- for_all(p)
- a[label(p)].take(input(p));
-
- for (unsigned l = 1; l < n; ++l)
- v(l) = a[l].to_result();
-
- trace::exiting("accu::compute");
- }
-
- } // mln::accu
-
- namespace morpho
- {
-
- template <typename I, typename N>
- mln_concrete(I)
- gradient(const I& input, const N& nbh)
- {
- mln_concrete(I) output;
- initialize(output, input);
- accu::min_max<mln_value(I)> mm;
-
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- mm.init();
- for_all(n) if (input.has(n))
- mm.take(input(n));
- output(p) = mm.second() - mm.first();
- }
- return output;
- }
-
- template <typename I, typename N>
- mln_concrete(I)
- dilation(const I& input, const N& nbh)
- {
- typedef mln_value(I) V;
- // FIXME: extension::fill(input, mln_min(V));
-
- mln_concrete(I) output;
- initialize(output, input);
- accu::max<V> m;
-
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- m.init();
- for_all(n) if (input.has(n))
- m.take(input(n));
- output(p) = m;
- }
- return output;
- }
-
- } // mln::morpho
-
-
- struct colorize : Function_v2v< colorize >
- {
- typedef value::rgb8 result;
- colorize(unsigned max)
- : lut(max + 1)
- {
- lut[0] = literal::black;
- for (unsigned i = 1; i <= max; ++i)
- lut[i] = result(100 + std::rand() % 150,
- 100 + std::rand() % 150,
- 100 + std::rand() % 150);
- }
- result operator()(unsigned i) const
- {
- return lut[i];
- }
- std::vector<result> lut;
- };
-
-
- template <typename I>
- I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
- {
- unsigned nrows = ima.nrows() / 2 + 1;
- unsigned ncols = ima.ncols() / 2 + 1;
- I output(nrows * (zoom + 1) - 1,
- ncols * (zoom + 1) - 1);
- data::fill(output, bg);
- mln_VAR( edge, ima | is_edge );
- mln_piter(edge_t) p(edge.domain());
- for_all(p)
- if (p.row() % 2) // horizontal edge
- {
- unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
- unsigned col = (p.col() / 2) * (zoom + 1);
- for (unsigned i = 0; i < zoom; ++i)
- opt::at(output, row, col + i) = ima(p);
- }
- else // vertical edge
- {
- unsigned row = (p.row() / 2) * (zoom + 1);
- unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
- for (unsigned i = 0; i < zoom; ++i)
- opt::at(output, row + i, col) = ima(p);
- }
- return output;
- }
-
-} // mln
-
-
-
-template <typename T>
-mln::image2d<T>
-image2cells(const mln::image2d<T>& input)
-{
- mln::image2d<T> output(2 * input.nrows() - 1,
- 2 * input.ncols() - 1);
- for (int row = 0; row < input.nrows(); ++row)
- for (int col = 0; col < input.ncols(); ++col)
- mln::opt::at(output, 2 * row, 2 * col) = mln::opt::at(input, row, col);
- return output;
-}
-
-
-template <typename T>
-mln::image2d<T>
-cells2image(const mln::image2d<T>& input)
-{
- mln::image2d<T> output((input.nrows() + 1) / 2,
- (input.ncols() + 1) / 2);
- for (int row = 0; row < input.nrows(); row += 2)
- for (int col = 0; col < input.ncols(); col += 2)
- mln::opt::at(output, row / 2, col / 2) =
- mln::opt::at(input, row, col);
- return output;
-}
-
-
-
-
-template <typename I>
-void
-do_it(I& ima, int lambda, const std::string& filename, unsigned& nbasins)
-{
- using namespace mln;
-
- // e2c
-
- bool e2c_h[] = { 0, 1, 0,
- 0, 0, 0,
- 0, 1, 0 };
-
- bool e2c_v[] = { 0, 0, 0,
- 1, 0, 1,
- 0, 0, 0 };
-
- mln_VAR( e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v) );
-
- bool e2e_h[] = { 0, 0, 1, 0, 0,
- 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 0,
- 0, 0, 1, 0, 0 };
-
- bool e2e_v[] = { 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 0,
- 1, 0, 0, 0, 1,
- 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0 };
-
- mln_VAR( e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v) );
-
- // cell
- mln_VAR(cell, ima | is_cell);
-
- // edge
- mln_VAR(edge, extend((ima | is_edge).rw(),
- pw::value(ima)));
-
- data::paste(morpho::gradient(edge, e2c), edge);
- // ^^^
- // edge -> neighboring cells
-
- // 'edge' looks like:
- //
- // 1 1
- // 3 3 3
- // 1 1
-
- {
- io::pgm::save(display_edge(ima, 0, 3),
- "temp_edge.pgm");
- }
-
-
- data::paste( morpho::closing_volume(edge, e2e, lambda), edge );
-
-
- image2d<unsigned> label(ima.bbox(), 0);
- // mln_ch_value(I, unsigned) label;
- // initialize(label, ima);
-
-
- mln_VAR(wst, label | is_edge);
-
- data::fill(wst, morpho::meyer_wst(edge, e2e, nbasins));
- // ^^^
- // edge -> neighboring edges
-
- // 'wst' looks like:
- //
- // 2 2
- // 0 0 0
- // 1 1
-
- colorize colors(nbasins);
-
- {
- image2d<value::rgb8> temp(label.domain());
- data::fill(temp, literal::white);
-
- data::paste( level::transform(label | is_edge,
- colors),
- temp );
-
- io::ppm::save(display_edge(temp, literal::white, 3),
- "temp_label.ppm");
- }
-
- // YET THOSE VALUES ARE ON EDGES, NOT ON CELLS...
-
-
- mln_VAR(lab, label | is_cell);
-
- data::paste(morpho::dilation(extend(lab, label),
- c4()),
- label);
-
- // 'lab' looks like:
- //
- // 2 2 2
- //
- // 1 1 1
-
- io::ppm::save(level::transform(cells2image(label),
- colors),
- filename);
-}
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm lambda output.ppm" << std::endl;
- std::cerr << " lambda >= 0" << std::endl;
- abort();
-}
-
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
-
- if (argc != 4)
- usage(argv);
-
- image2d<int_u8> temp;
- io::pgm::load(temp, argv[1]);
-
- image2d<int_u8> ima = image2cells(temp);
-
-
- int lambda = atoi(argv[2]);
- if (lambda < 0)
- usage(argv);
-
- std::string filename(argv[3]);
-
- unsigned nbasins;
- do_it(ima, lambda, filename, nbasins);
- std::cout << "nbasins = " << nbasins << std::endl;
-}
Index: geraud/laurent/wst2d.cc
--- geraud/laurent/wst2d.cc (revision 3151)
+++ geraud/laurent/wst2d.cc (working copy)
@@ -1,154 +0,0 @@
-# include <cstdlib>
-
-# include <mln/value/int_u8.hh>
-# include <mln/value/rgb8.hh>
-
-# include <mln/io/pgm/load.hh>
-# include <mln/io/ppm/save.hh>
-
-# include <mln/core/var.hh>
-# include <mln/core/image/image2d.hh>
-# include <mln/core/alias/neighb2d.hh>
-# include <mln/make/double_neighb2d.hh>
-
-# include <mln/level/transform.hh>
-# include <mln/literal/black.hh>
-# include <mln/debug/println.hh>
-
-# include <mln/morpho/closing_area.hh>
-# include <mln/morpho/gradient.hh>
-# include <mln/accu/min_max.hh>
-# include <mln/morpho/meyer_wst.hh>
-
-
-using namespace mln;
-using value::int_u8;
-
-
-template <typename I, typename N>
-mln_concrete(I)
-morpho_gradient(const Image<I>& input_, const Neighborhood<N>& nbh_)
-{
- const I& input = exact(input_);
- const N& nbh = exact(nbh_);
-
- mln_concrete(I) output;
- initialize(output, input);
- accu::min_max<mln_value(I)> mm;
-
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
-
- for_all(p)
- {
- mm.take_as_init(input(p));
- for_all(n)
- mm.take(input(n));
- output(p) = mm.second() - mm.first();
- }
-
- return output;
-}
-
-struct colorize : Function_v2v< colorize >
-{
- typedef value::rgb8 result;
- colorize(unsigned max)
- : lut(max + 1)
- {
- lut[0] = literal::black;
- for (unsigned i = 1; i <= max; ++i)
- lut[i] = result(100 + std::rand() % 150,
- 100 + std::rand() % 150,
- 100 + std::rand() % 150);
- }
- result operator()(unsigned i) const
- {
- return lut[i];
- }
- std::vector<result> lut;
-};
-
-
-bool is_chess(const point2d& p)
-{
- return p.col() % 2 == p.row() % 2;
-}
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.pgm nbh lambda output.ppm" << std::endl;
- std::cerr << " nbh in {4, 6, 8}; lambda >= 0" << std::endl;
- abort();
-}
-
-
-template <typename I, typename N>
-void do_it(const I& ima,
- const N& nbh,
- int lambda,
- const std::string& filename)
-{
- I grad = morpho_gradient(ima, nbh);
-
- I clo;
- if (lambda > 1)
- clo = morpho::closing_area(grad, nbh, lambda);
- else
- clo = grad;
-
- unsigned l;
- mln_ch_value(I, unsigned) wst = morpho::meyer_wst(clo, nbh, l);
-
- std::cout << "nbasins = " << l << std::endl;
-// debug::println(labeling::regional_minima(clo, nbh, l));
-// debug::println(wst);
-
- io::ppm::save(level::transform(wst, colorize(l)), filename);
-}
-
-
-int main(int argc, char* argv[])
-{
- if (argc != 5)
- usage(argv);
-
- image2d<int_u8> ima;
-
- io::pgm::load(ima, argv[1]);
-
- int nbh_ = atoi(argv[2]);
- if (! (nbh_ == 4 || nbh_ == 6 || nbh_ == 8))
- usage(argv);
-
- int lambda = atoi(argv[3]);
- if (lambda < 0)
- usage(argv);
-
- std::string filename(argv[4]);
-
- if (nbh_ == 4)
- {
- mln_VAR(nbh, c4());
- do_it(ima, nbh, lambda, filename);
- }
- else if (nbh_ == 8)
- {
- mln_VAR(nbh, c8());
- do_it(ima, nbh, lambda, filename);
- }
- else if (nbh_ == 6)
- {
- bool vert[] = { 1, 1, 0,
- 1, 0, 1,
- 0, 1, 1 };
-
- bool hori[] = { 0, 1, 1,
- 1, 0, 1,
- 1, 1, 0 };
-
- mln_VAR(nbh, make::double_neighb2d(is_chess, vert, hori));
- do_it(ima, nbh, lambda, filename);
- }
-}
Index: geraud/laurent/classif.cc
--- geraud/laurent/classif.cc (revision 3151)
+++ geraud/laurent/classif.cc (working copy)
@@ -1,419 +0,0 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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.
-
-/// \file tests/core/image/complex_image_swt.cc
-/// \brief Testing Meyer's Watershed Transform on mln::complex_image.
-
-#include <iostream>
-
-#include <vector>
-#include <mln/core/image/image2d.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/site_set/p_queue_fast.hh>
-#include <mln/labeling/blobs.hh>
-#include <mln/io/pbm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/debug/println.hh>
-#include <mln/draw/line.hh>
-#include <mln/pw/all.hh>
-
-
-#include <mln/value/int_u8.hh>
-#include <mln/core/alias/point2d.hh>
-
-#include <mln/core/site_set/p_faces.hh>
-#include <mln/core/image/complex_image.hh>
-
-// FIXME: Include these elsewhere? (In complex_image.hh?)
-#include <mln/core/image/complex_neighborhoods.hh>
-#include <mln/core/image/complex_neighborhood_piter.hh>
-
-#include <mln/debug/iota.hh>
-#include <mln/data/fill.hh>
-#include <mln/norm/l2.hh>
-
-#include <mln/morpho/closing_area.hh>
-#include <mln/morpho/closing_volume.hh>
-#include <mln/morpho/closing_height.hh>
-#include <mln/morpho/meyer_wst.hh>
-
-
-namespace mln
-{
-
- template <typename I, typename N>
- mln_concrete(I)
- influence_zones(const I& input, const N& nbh)
- {
- mln_concrete(I) output = duplicate(input);
-
- p_queue_fast<mln_site(I)> q;
-
- {
- // Initialization.
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- if (input(p) != 0)
- for_all(n) if (input.has(n))
- if (input(n) == 0)
- {
- q.push(p);
- break;
- }
- }
- {
- // Body.
- mln_site(I) p;
- mln_niter(N) n(nbh, p);
- while (! q.is_empty())
- {
- p = q.pop_front();
- mln_invariant(output(p) != 0);
- for_all(n) if (input.has(n))
- if (output(n) == 0)
- {
- output(n) = output(p);
- q.push(n);
- }
- }
- }
-
- return output;
-
- } // IZ
-
-
- template <typename I>
- void
- mk_graph(const I& iz, unsigned nlabels)
- {
- }
-
-}
-
-
-void usage(char* argv[])
-{
- std::cerr << argv[0] << " lambda" << std::endl;
- abort();
-}
-
-int main(int argc, char* argv[])
-{
- if (argc != 2)
- usage(argv);
-
- using namespace mln;
- using mln::value::int_u8;
-
- /*----------------------------------------.
- | Complex + complex geometry (location). |
- `----------------------------------------*/
-
- /* A (simplicial) 1-complex and its adjacency graph.
-
- c 0 1 2 3
- r .------------------------
- | v0 e3 v3
- 0 | o-----------o v0----e3----v3
- | / \ / / \ /
- | / \ / / \ /
- 1 | e0 / e1 / e4 e0 e1 e4
- | / \ / / \ /
- | / \ / / \ /
- 2 | o-----------o v1----e2----v2
- | v1 e2 v2
-
- v = vertex
- e = edge
- */
-
-
-
-
- border::thickness = 0;
-
- image2d<bool> seeds;
- io::pbm::load(seeds, "+seeds.pbm");
-
-// debug::println(seeds);
-
- unsigned nlabels;
- image2d<unsigned> label = labeling::blobs(seeds, c4(), nlabels);
-
- std::cout << "n seeds = " << nlabels << std::endl;
- {
- image2d<int_u8> lab(label.domain());
- data::paste(label, lab);
- io::pgm::save(lab, "label.pgm");
- }
-
- image2d<unsigned> iz = influence_zones(label, c4());
- {
- image2d<int_u8> IZ(iz.domain());
- data::paste(iz, IZ);
- io::pgm::save(IZ, "iz.pgm");
- }
-// debug::println( (pw::value(iz) - pw::cst(1)) | iz.domain() );
-
-
- // mk_graph
-
- std::vector< std::vector<bool> > adj(nlabels + 1);
- for (unsigned l = 1; l <= nlabels; ++l)
- adj[l].resize(nlabels + 1, false);
-
- {
- box2d::piter p(iz.domain());
- for_all(p)
- {
- point2d r = p + right, b = p + down;
- if (iz.has(r) && iz(p) != iz(r))
- {
- if (iz(p) <= iz(r))
- adj[iz(p)][iz(r)] = true;
- else
- adj[iz(r)][iz(p)] = true;
- }
- if (iz.has(b) && iz(p) != iz(b))
- {
- if (iz(p) <= iz(b))
- adj[iz(p)][iz(b)] = true;
- else
- adj[iz(b)][iz(p)] = true;
- }
- }
- }
-
- // end of mk_graph
-
-
- const unsigned D = 1;
-
- topo::complex<D> c;
-
- typedef point2d P;
- typedef geom::complex_geometry<D, P> G;
- G geom;
-
- // Convenience typedefs.
- typedef topo::n_face<0, D> vertex;
- typedef topo::n_face<1, D> edge;
-
- {
-
- // 0-faces (vertices).
- std::vector<vertex> v;
- {
- box2d::piter p(label.domain());
- for_all(p)
- if (label(p) != 0)
- {
- geom.add_location(p);
- v.push_back(c.add_face());
- }
- }
-
- std::cout << "v size = " << v.size() << std::endl;
-
- // 1-faces (edges).
- std::vector<edge> e;
- {
- for (unsigned l = 1; l <= nlabels; ++l)
- for (unsigned ll = l + 1; ll <= nlabels; ++ll)
- if (adj[l][ll])
- e.push_back( c.add_face(-v[l-1] + v[ll-1]) );
- }
-
- std::cout << "e size = " << e.size() << std::endl;
-
- }
-
-
-// {
-// for (unsigned l = 1; l <= nlabels; ++l)
-// for (unsigned ll = l + 1; ll <= nlabels; ++ll)
-// if (adj[l][ll])
-// std::cout << l-1 << ' ' << ll-1 << std::endl;
-// }
-
-
-
-// std::cout << c << std::endl;
-
-
- image2d<int_u8> canvas(seeds.domain());
- data::fill(canvas, 0);
-
-
- /*---------------------.
- | Complex-based pset. |
- `---------------------*/
-
- p_complex<D, G> pc(c, geom);
-
- /*----------------------.
- | Complex-based image. |
- `----------------------*/
-
- // An image type built on a 1-complex with unsigned values on each
- // face (both vertices and edges).
- typedef complex_image<D, G, unsigned> dist_ima_t;
-
- // Create and initialize an image based on PC.
- dist_ima_t dist_ima(pc);
- data::fill(dist_ima, 0u);
-
- /*--------------------------------.
- | Complex-based image iterators. |
- `--------------------------------*/
-
- accu::max<unsigned> dist_max;
-
- // For each edge (1-face), compute the distance between the two
- // adjacent vertices (0-faces).
- p_n_faces_fwd_piter<D, G> e(dist_ima.domain(), 1);
- typedef complex_lower_neighborhood<D, G> v_nbh_t;
- v_nbh_t v_nbh;
- mln_niter_(v_nbh_t) v(v_nbh, e);
- for_all(e)
- {
- v.start();
- point2d p1 = v.to_site().front();
- v.next();
- point2d p2 = v.to_site().front();
- v.next();
- mln_invariant(!v.is_valid());
-
- dist_ima(e) = norm::l2_distance(p1.to_vec(), p2.to_vec()) / 2;
- dist_max.take(dist_ima(e));
-
- draw::line(canvas, p1, p2, dist_ima(e));
- canvas(p1) = 255;
- canvas(p2) = 255;
- }
-
- std::cout << "distance max = " << dist_max << std::endl;
-
-
- io::pgm::save(canvas, "canvas.pgm");
-
-
-// // Initialize 0-faces to a dummy value, to prevent the watershed from
-// // finding minima on 0-faces.
-// p_n_faces_fwd_piter<D, G> v_(dist_ima.domain(), 0);
-// for_all(v_)
-// {
-// // FIXME: canvas(v_.to_site().front()) = 255;
-// dist_ima(v_) = mln_max(mln_value_(dist_ima_t));
-// }
-
-
-
-
-// // For all edges, iterate on adjacent edges (i.e., on edges sharing
-// // an adjacent vertex).
- typedef complex_lower_dim_connected_n_face_neighborhood<D, G> nbh_t;
- nbh_t nbh;
-// // Neighbor edge.
-// mln_niter_(nbh_t) ne(nbh, e);
-// for_all(e)
-// {
-// std::cout << "dist_ima(" << e << ") = " << dist_ima(e)
-// << " -- adjacent edges :" << std::endl;
-// for_all(ne)
-// std::cout << " " << ne << std::endl;
-// }
-
-
-
- /*-----------------.
- | Simplification. |
- `-----------------*/
-
- // Currently, does nothing (lambda = 1).
- dist_ima_t closed_dist_ima (dist_ima.domain());
- morpho::closing_height(dist_ima, nbh, atoi(argv[1]), closed_dist_ima);
-
- /*------.
- | WST. |
- `------*/
-
- // Perform a Watershed Transform.
- typedef unsigned wst_val_t;
- wst_val_t nbasins;
- typedef complex_image<D, G, wst_val_t> wst_ima_t;
- wst_ima_t wshed = morpho::meyer_wst(closed_dist_ima, nbh, nbasins);
- /* Note that since the image is based not only on the 1-faces but
- also on the 0-faces of the complex, and given the above
- neighborhood, the domain seen by the WST is not connected! It is
- actually composed of five components :
-
- - a component containing all the 1-faces (egdes) which are all
- connected through
- mln::complex_lower_dim_connected_n_face_neighborhood;
-
- - four (singleton) components corresponding to the 0-faces
- (vertices), connected to no other part of the complex according to
- mln::complex_lower_dim_connected_n_face_neighborhood.
-
- Since the component made of the edges contains two local minima,
- the number of basins is equal to 6:
-
- 2 minima for the edges' component
- + 4 * 1 minima for the vertices's components
- --------------------------------------------
- 6 basins.
-
- Hence the result.
-
-
- We definitely need a complex_image that can accept a subset of a
- complex as domain (or at least a p_face<N, D, P>. */
- std::cout << "nbasins = " << nbasins - c.nfaces(0) << std::endl;
-
-
- image2d<int_u8> canvas_wst(seeds.domain());
- data::fill(canvas_wst, 255);
-
- for_all(e)
- {
- v.start();
- point2d p1 = v.to_site().front();
- v.next();
- point2d p2 = v.to_site().front();
- v.next();
- mln_invariant(!v.is_valid());
-
- draw::line(canvas_wst, p1, p2, wshed(e));
- }
-
- io::pgm::save(canvas_wst, "canvas_wst.pgm");
-
-}
Index: geraud/laurent/wst3d.cc
--- geraud/laurent/wst3d.cc (revision 3151)
+++ geraud/laurent/wst3d.cc (working copy)
@@ -1,79 +0,0 @@
-# include <cstdlib>
-# include <cstdio>
-
-# include <mln/value/int_u16.hh>
-# include <mln/value/int_u8.hh>
-# include <mln/level/stretch.hh>
-
-# include <mln/io/pgm/load.hh>
-# include <mln/io/ppm/save.hh>
-
-# include <mln/core/var.hh>
-# include <mln/core/image/image3d.hh>
-# include <mln/core/alias/neighb3d.hh>
-
-# include <mln/morpho/meyer_wst.hh>
-# include <mln/morpho/closing_area.hh>
-# include <mln/morpho/closing_volume.hh>
-
-
-
-using namespace mln;
-using value::int_u8;
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.raw lambda output.ppm" << std::endl;
- std::cerr << " lambda >= 0" << std::endl;
- abort();
-}
-
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
- using value::int_u16;
-
- if (argc != 3)
- usage(argv);
-
- trace::quiet = false;
-
- image3d<int_u16> ima16(256, 256, 256, 0);
- int size = 256 * 256 * 256 * 2;
-
- std::FILE* file = std::fopen(argv[1], "r");
- std::fread(ima16.buffer(), size, 1, file);
-
-// typedef image3d<int_u16> I;
-// mln_piter_(I) p(ima16.domain());
-// for_all(p)
-// if (ima16(p) != 0)
-// std::cout << ima16(p) << std::endl;
-
-// abort();
-
- int_u16 min_, max_;
- estim::min_max(ima16, min_, max_);
- std::cout << min_ << ' ' << max_ << std::endl;
-
- abort();
-
- image3d<int_u8> ima(ima16.domain());
- level::stretch(ima16, ima);
- ima16.destroy();
-
- int lambda = atoi(argv[2]);
- if (lambda < 0)
- usage(argv);
-
- image3d<int_u8> clo(ima.domain());
- morpho::closing_volume(ima, c6(), lambda, clo);
-
- unsigned nbasins;
- image3d<unsigned> wst = morpho::meyer_wst(clo, c6(), nbasins);
- std::cout << "nbasins = " << nbasins << std::endl;
-}
Index: geraud/laurent/segmentation.hh
--- geraud/laurent/segmentation.hh (revision 3151)
+++ geraud/laurent/segmentation.hh (working copy)
@@ -1,14 +0,0 @@
-
-
-template <typename I, typename N>
-mln_ch_value(I, rgb8) segmentation(const I& ima,
- const N& nbh,
- unsigned area)
-{
- mln_concrete(I) filtered = morpho::closing_area(ima, nbh, area);
-
- unsigned nbasins;
- mln_ch_value(I, unsigned) wst = morpho::wst_meyer(filtered, nbh, nbasins);
-
- return level::transform(wst, colorize(nbasins));
-}
Index: geraud/irm.cc
--- geraud/irm.cc (revision 3151)
+++ geraud/irm.cc (working copy)
@@ -1,178 +0,0 @@
-
-#include <iterator>
-#include <iostream>
-#include <algorithm>
-
-#include <mln/core/image/image2d.hh>
-
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/core/alias/window2d.hh>
-#include <mln/core/image/image_if.hh>
-#include <mln/win/rectangle2d.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
-#include <mln/value/int_u8.hh>
-#include <mln/level/transform.hh>
-
-#include <mln/convert/to_window.hh>
-#include <mln/convert/to_image.hh>
-#include <mln/convert/to_fun.hh>
-
-#include <mln/morpho/gradient.hh>
-#include <mln/morpho/closing_area.hh>
-#include <mln/morpho/meyer_wst.hh>
-
-#include <mln/accu/mean.hh>
-#include <mln/level/take.hh>
-
-#include <mln/util/graph.hh>
-
-#include <mln/debug/println.hh>
-
-
-mln::value::int_u8 foo(unsigned u)
-{
- return u == 0 ?
- 0 : // wshed line
- 1 + (u - 1) % 255; // basin
-}
-
-
-namespace mln
-{
-
- template <typename I>
- void doit(const I& irm,
- const image2d<unsigned>& lbl,
- unsigned nlabels)
- {
- {
-// accu::mean_<unsigned> m;
-
-// mln_piter(I) p(irm.domain());
-// for_all(p)
-// if (lbl(p) == 82)
-// m.take(irm(p));
-
-// level::take(irm | (pw::value(lbl) == pw::cst(82)), m);
-
-// std::cout << "reg 82 has mean = " << m << std::endl;
- }
-
- std::vector< accu::mean_<unsigned> > m(nlabels + 1);
- mln_piter(I) p(irm.domain());
- for_all(p)
- m[lbl(p)].take(irm(p));
-
-// for (unsigned l = 1; l <= nlabels; ++l)
-// std::cout << l << ":" << m[l] << " ";
-// std::cout << std::endl;
-
- accu::mean_<unsigned> mm;
- mm.take(m[70]);
- mm.take(m[77]);
- mm.take(m[80]);
- mm.take(m[82]);
- mm.take(m[99]);
- std::cout << mm.to_result() << std::endl;
- }
-
-
- /*template <typename I, typename N>
- void mk_graph(const I& lbl,
- N nbh,
- unsigned nlabels)
- {
- std::vector< std::vector<bool> > adja(nlabels + 1);
- for (unsigned l = 1; l <= nlabels; ++l)
- adja[l].resize(l, false);
-
- mln_piter(I) p(lbl.domain());
- mln_niter(N) n(nbh, p);
-
- // We compute the adjacency matrix of the RAG.
- for_all(p)
- if (lbl(p) == 0) // wshed
- {
- std::set<unsigned> s;
- for_all(n) if (lbl.has(n))
- {
- if (lbl(n) == 0)
- continue;
- s.insert(lbl(n));
- }
- if (s.size() < 2)
- {
- std::cout << "#" << std::endl;
- continue;
- }
- std::set<unsigned>::const_iterator l1, l2;
- for (l1 = s.begin(); l1 != s.end(); ++l1)
- {
- l2 = l1;
- for (++l2; l2 != s.end(); ++l2)
- adja[*l2][*l1] = true;
- }
- }
-
- unsigned count = 0;
- for (unsigned l1 = 2; l1 <= nlabels; ++l1)
- for (unsigned l2 = 1; l2 < l1; ++l2)
- if (adja[l1][l2])
- ++count;
- std::cout << "link count = " << count << std::endl;
-
- // Graph.
- util::graph<> g;
- // Nodes.
- for (unsigned i = 0; i <= nlabels; ++i)
- g.add_node();
- // Edges.
- for (unsigned l1 = 1; l1 <= nlabels; ++l1)
- for (unsigned l2 = l1 + 1; l2 <= nlabels; ++l2)
- if (adja[l1][l2])
- g.add_edge(l1, l2);
- g.print_debug (std::cout);
-
- }*/
-
-} // end of namespace mln
-
-
-int main()
-{
- using namespace mln;
- using value::int_u8;
-
- image2d<int_u8> irm;
- io::pgm::load(irm, "./+irm6cut.pgm");
-
-// io::pgm::save( morpho::gradient(irm, win::rectangle2d(3,3)),
-// "tmp_grad_3x3.pgm" );
-
- window2d c4p = convert::to_window(c4());
- c4p.insert(0,0);
-// debug::println(convert::to_image(c4p));
- image2d<int_u8> grad = morpho::gradient(irm, c4p);
- io::pgm::save( grad, "tmp_grad_c4p.pgm" );
-
- image2d<int_u8> clo;
- initialize(clo, irm);
-
- morpho::closing_area(grad, c4(), 100, clo);
- io::pgm::save( clo, "tmp_clo_a100.pgm" );
-
- unsigned nbasins;
- image2d<unsigned> wshed = morpho::meyer_wst(clo, c4(), nbasins);
- std::cout << "nbasins = " << nbasins << std::endl;
- io::pgm::save( level::transform(wshed, convert::to_fun(foo)),
- "tmp_wshed.pgm" );
-
-// doit(irm, wshed, nbasins);
-// mk_graph(wshed, c4(), nbasins);
-
-// std::vector< accu::mean_<unsigned> >
-
-}
Index: geraud/color/sum_pix.hh
--- geraud/color/sum_pix.hh (revision 3151)
+++ geraud/color/sum_pix.hh (working copy)
@@ -1,162 +0,0 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_ACCU_SUM_PIX_HH
-# define MLN_ACCU_SUM_PIX_HH
-
-/// \file mln/accu/sum_pix.hh
-///
-/// Define an accumulator that computes a sum.
-
-# include <mln/core/concept/meta_accumulator.hh>
-# include <mln/accu/internal/base.hh>
-
-# include <mln/util/pix.hh> // To prevent accu::sum_pix to work on pixels (ambiguous).
-
-# include <mln/trait/value_.hh> // For mln_sum_pix.
-# include <mln/value/builtin/all.hh> // In the case of summing builtin values.
-# include <mln/literal/zero.hh> // For initialization.
-
-
-namespace mln
-{
-
- namespace accu
- {
-
-
- /// Generic sum_pix accumulator class.
- /*!
- * Parameter \c T is the type of values that we sum. Parameter \c
- * S is the type to store the value sum; the default type of
- * \c S is the summation type (property) of \c T.
- */
- template <typename P, typename S = mln_sum(mln_value(P))>
- struct sum_pix : public mln::accu::internal::base< const S&, sum_pix<P,S> >
- {
- typedef P argument;
-
- sum_pix();
-
- /// Manipulators.
- /// \{
- void init();
- void take(const argument& t);
- void take(const sum_pix<P,S>& other);
- /// \}
-
- void set_value(S v)
- {
- s_ = v;
- }
-
- /// Get the value of the accumulator.
- const S& to_result() const;
-
- /// Check whether this accu is able to return a result.
- /// Always true here.
- bool is_valid() const;
-
- protected:
-
- S s_;
- };
-
-
- namespace meta
- {
-
- /// Meta accumulator for sum_pix.
- struct sum_pix : public Meta_Accumulator< sum_pix >
- {
- template <typename P, typename S = mln_sum(mln_value(P))>
- struct with
- {
- typedef accu::sum_pix<P, S> ret;
- };
- };
-
- } // end of namespace mln::accu::meta
-
-
-# ifndef MLN_INCLUDE_ONLY
-
- template <typename P, typename S>
- inline
- sum_pix<P,S>::sum_pix()
- {
- init();
- }
-
- template <typename P, typename S>
- inline
- void
- sum_pix<P,S>::init()
- {
- s_ = literal::zero;
- }
-
- template <typename P, typename S>
- inline
- void sum_pix<P,S>::take(const argument& p)
- {
- s_ += 1 + p.v();
- }
-
- template <typename P, typename S>
- inline
- void
- sum_pix<P,S>::take(const sum_pix<P,S>& other)
- {
- s_ += other.s_;
- }
-
- template <typename P, typename S>
- inline
- const S&
- sum_pix<P,S>::to_result() const
- {
- return s_;
- }
-
- template <typename P, typename S>
- inline
- bool
- sum_pix<P,S>::is_valid() const
- {
- return true;
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace mln::accu
-
-} // end of namespace mln
-
-
-#endif // ! MLN_ACCU_SUM_PIX_HH
Index: geraud/color/segment.cc
--- geraud/color/segment.cc (revision 3151)
+++ geraud/color/segment.cc (working copy)
@@ -1,639 +0,0 @@
-#include <cstdlib>
-
-#include <mln/core/var.hh>
-
-#include <mln/core/image/image2d.hh>
-#include <mln/core/alias/box3d.hh>
-
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/make/double_neighb2d.hh>
-
-#include <mln/core/image/image_if.hh>
-#include <mln/pw/all.hh>
-#include <mln/core/routine/extend.hh>
-#include <mln/core/routine/duplicate.hh>
-#include <mln/data/paste.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-#include <mln/io/ppm/load.hh>
-#include <mln/io/ppm/save.hh>
-
-#include <mln/math/diff_abs.hh>
-
-#include <mln/debug/println.hh>
-
-#include <mln/morpho/dilation.hh>
-#include <mln/morpho/erosion.hh>
-#include <mln/morpho/tree/data.hh>
-#include <mln/morpho/meyer_wst.hh>
-#include <mln/morpho/closing_attribute.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/labeling/regional_minima.hh>
-
-
-#include <mln/accu/count.hh>
-#include <mln/accu/volume.hh>
-
-#include "sum_pix.hh"
-
-
-namespace mln
-{
-
- point3d color2point(const value::rgb8& c)
- {
- point3d p(c.red(), c.green(), c.blue());
- return p;
- }
-
-
- image2d<value::rgb8> blen_image;
-
-
- template <typename B>
- void accu_blen_take(B& b, const point2d& e)
- {
- if (e.row() % 2)
- {
- b.take(color2point(blen_image(e + up)));
- b.take(color2point(blen_image(e + down)));
- }
- else
- {
- b.take(color2point(blen_image(e + left)));
- b.take(color2point(blen_image(e + right)));
- }
- }
-
-}
-
-#include "blen_pix.hh"
-
-
-
-
-namespace mln
-{
-
- // Functions.
-
- inline
- bool is_row_odd(const point2d& p)
- {
- return p.row() % 2;
- }
-
- inline
- bool is_square(const point2d& p)
- {
- return p.row() % 2 == 0 && p.col() % 2 == 0;
- }
-
- inline
- bool is_edge(const point2d& p)
- {
- return p.row() % 2 + p.col() % 2 == 1;
- }
-
- inline
- bool is_point(const point2d& p)
- {
- return p.row() % 2 && p.col() % 2;
- }
-
-
- // Neighborhoods.
-
- typedef neighb< win::multiple<window2d, bool(*)(const point2d&)> > dbl_neighb2d;
-
- const dbl_neighb2d& e2c()
- {
- static bool e2c_h[] = { 0, 1, 0,
- 0, 0, 0,
- 0, 1, 0 };
- static bool e2c_v[] = { 0, 0, 0,
- 1, 0, 1,
- 0, 0, 0 };
- static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2c_h, e2c_v);
- return nbh;
- }
-
- const dbl_neighb2d& e2e()
- {
- static bool e2e_h[] = { 0, 0, 1, 0, 0,
- 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 0,
- 0, 0, 1, 0, 0 };
- static bool e2e_v[] = { 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 0,
- 1, 0, 0, 0, 1,
- 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0 };
- static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2e_h, e2e_v);
- return nbh;
- }
-
-
- // Transforms.
-
- template <typename T>
- image2d<T>
- image2full(const image2d<T>& input)
- {
- image2d<T> output(2 * input.nrows() - 1,
- 2 * input.ncols() - 1);
- for (int row = 0; row < input.nrows(); ++row)
- for (int col = 0; col < input.ncols(); ++col)
- opt::at(output, 2 * row, 2 * col) = opt::at(input, row, col);
- return output;
- }
-
- template <typename T>
- image2d<T>
- full2image(const image2d<T>& input)
- {
- image2d<T> output((input.nrows() + 1) / 2,
- (input.ncols() + 1) / 2);
- for (int row = 0; row < input.nrows(); row += 2)
- for (int col = 0; col < input.ncols(); col += 2)
- opt::at(output, row / 2, col / 2) =
- opt::at(input, row, col);
- return output;
- }
-
-
- // Display.
-
- template <typename I>
- I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
- {
- unsigned nrows = ima.nrows() / 2 + 1;
- unsigned ncols = ima.ncols() / 2 + 1;
- I output(nrows * (zoom + 1) - 1,
- ncols * (zoom + 1) - 1);
- data::fill(output, bg);
- mln_VAR( edge, ima | is_edge );
- mln_piter(edge_t) p(edge.domain());
- for_all(p)
- if (p.row() % 2) // horizontal edge
- {
- unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
- unsigned col = (p.col() / 2) * (zoom + 1);
- for (unsigned i = 0; i < zoom; ++i)
- opt::at(output, row, col + i) = ima(p);
- }
- else // vertical edge
- {
- unsigned row = (p.row() / 2) * (zoom + 1);
- unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
- for (unsigned i = 0; i < zoom; ++i)
- opt::at(output, row + i, col) = ima(p);
- }
- return output;
- }
-
-
-
- // Distance.
-
- value::int_u8 dist(const value::rgb8& c1, const value::rgb8& c2)
- {
- unsigned d = 0;
- d += (math::diff_abs(c1.red(), c2.red()) + 2) / 3;
- d += (math::diff_abs(c1.green(), c2.green()) + 2) / 3;
- d += (math::diff_abs(c1.blue(), c2.blue()) + 2) / 3;
- if (d > 255)
- d = 255;
- return d;
- }
-
- template <typename I, typename N>
- image2d<value::int_u8>
- dist(const I& input, const N& nbh)
- {
- image2d<value::int_u8> output;
- initialize(output, input);
- data::fill(output, 0);
-
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- n.start();
- value::rgb8 c1 = input(n);
- n.next();
- value::rgb8 c2 = input(n);
- output(p) = dist(c1, c2);
- }
-
- return output;
- }
-
-
- // Sorting.
-
-
- template <typename I>
- struct my_less_
- {
- const I& ima_;
-
- inline
- my_less_(const I& ima)
- : ima_(ima)
- {
- }
-
- inline
- bool operator()(const mln_site(I)& lhs,
- const mln_site(I)& rhs) const
- {
- return util::ord_strict(ima_(lhs), ima_(rhs))
- || (ima_(lhs) == ima_(rhs)
- &&
- util::ord_strict(lhs, rhs));
- }
- };
-
-
- template <typename I, typename S>
- p_array<mln_site(I)> my_sort_increasing(const I& ima, const S& s)
- {
- p_array<mln_site(I)> v;
- convert::from_to(s, v);
- std::sort(v.hook_std_vector_().begin(), v.hook_std_vector_().end(),
- my_less_<I>(ima));
- return v;
- }
-
-
-
-
- // Tree -> attributes (on nodes only).
- // -----------------------------------
-
-
-
- template <typename A, typename T>
- inline
- mln_ch_value(typename T::function, mln_result(A))
- compute_attribute_on_nodes(const A& a, const T& t)
- {
- typedef typename T::function I;
-
- mln_ch_value(I, A) acc;
- mln_ch_value(I, mln_result(A)) attr;
-
- // Initialization of 'acc'.
- {
- initialize(acc, t.f());
- data::fill(acc, a); // Transfer "dynamic data" (state) of 'a'.
- }
-
- // Initialize every attribute with the corresponding pixel.
- {
- mln_piter(I) p(t.f().domain());
- for_all(p)
- acc(p).take_as_init(make::pix(t.f(), p));
- }
-
- // Propagate attribute from a site to its parent.
- {
- mln_fwd_piter(T) p(t.domain());
- for_all(p)
- if (! t.is_root(p))
- acc(t.parent(p)).take(acc(p));
- // No back-propagation to non-node sites.
- }
-
-
- // Change accumulator into its result.
- {
- initialize(attr, acc);
- typedef typename T::nodes_t N;
- mln_piter(N) p(t.nodes());
- for_all(p)
- {
- mln_invariant(t.is_a_node(p));
- attr(p) = acc(p).to_result();
- }
- }
-
- return attr;
- }
-
-
- template <typename A, typename T>
- inline
- mln_ch_value(typename T::function, mln_result(A))
- compute_rand_attribute_on_nodes(const A& a, const T& t)
- {
- typedef typename T::function I;
-
- mln_ch_value(I, mln_result(A)) attr;
- initialize(attr, t.f());
-
- // Initialize every attribute with the corresponding pixel.
- {
- mln_piter(I) p(t.f().domain());
- for_all(p)
- attr(p) = float(std::rand() % 10000) / 1000.f;
- }
-
- // Propagate attribute from a site to its parent.
- {
- mln_fwd_piter(T) p(t.domain());
- for_all(p)
- if (! t.is_root(p))
- attr(t.parent(p)) += attr(p);
- }
-
- return attr;
- }
-
-
-
- // Tree -> nchildren (on nodes).
- // -----------------------------
-
-
- template <typename T>
- inline
- mln_ch_value(typename T::function, unsigned)
- compute_nchildren(const T& t)
- {
- typedef typename T::function I;
- mln_ch_value(I, unsigned) nchildren;
- initialize(nchildren, t.f());
- data::fill(nchildren, 0);
-
- {
- mln_fwd_piter(T) p(t.domain());
- // Propagate attribute from a site to its parent.
- for_all(p)
- if (t.is_a_non_root_node(p))
- {
- mln_invariant(t.is_a_node(t.parent(p)));
- ++nchildren(t.parent(p)); // so parent(p) is a node
- }
- }
-
- return nchildren;
- }
-
-
-
-
- template <typename A, typename T, typename N>
- inline
- mln_concrete(typename T::function)
- filter(const A& a, const T& t, const N& nbh,
- unsigned n_objects,
- mln_value(A)& lambda,
- bool echo = false)
- {
- typedef typename T::function I;
-
- unsigned n_regmins_f; // This value can be obtained while computing the attributes!
- mln_ch_value(I, unsigned) regmins_f = labeling::regional_minima(t.f(), nbh, n_regmins_f);
- if (echo)
- {
- debug::println("f =", t.f());
- debug::println("regmins(f) =", regmins_f);
- // debug::println("par on nodes = ", t.parent_image() | t.nodes());
- std::cout << "n regmins(f) = " << n_regmins_f << std::endl
- << std::endl;
- }
- if (n_objects >= n_regmins_f)
- {
- std::cout << "warning: number of expected objects is greater than number of regmins!" << std::endl;
- std::cout << "aborting..." << std::endl;
- return duplicate(t.f());
- }
-
- lambda = mln_max(mln_value(A));
-
- mln_ch_value(typename T::function, unsigned) nchildren = compute_nchildren(t);
-
- typedef p_array<mln_site(I)> S;
- S s = my_sort_increasing(a, t.nodes());
-
- const typename T::parent_t& par = t.parent_image();
-
- unsigned
- count = n_regmins_f,
- less = 0;
- mln_fwd_piter(S) p(s);
- for_all(p)
- {
- if (a(p) < lambda && par(p) != p)
- {
- mln_assertion(nchildren(par(p)) > 0);
- --nchildren(par(p));
- if (nchildren(par(p)) != 0)
- {
- if (count <= n_objects)
- {
- ++less; // minus 1 object wrt the expected number!
- }
- --count;
- if (count == n_objects)
- {
- lambda = a(p) + 1;
- std::cout << "lambda = " << lambda << std::endl
- << std::endl;
- // break; // Stop iterations.
- }
- }
- }
- }
-
- if (less != 0)
- std::cerr << "WARNING: less objects (" << less << ") than expected..." << std::endl
- << std::endl;
-
- if (echo)
- debug::println("nchildren =", nchildren | t.nodes());
-
-
- // Filtering.
- mln_concrete(I) g;
- {
- initialize(g, t.f());
- mln_bkd_piter(T) p(t.domain());
- for_all(p)
- if (t.is_a_node(p) && a(p) >= lambda)
- g(p) = t.f(p);
- else
- g(p) = g(par(p));
-
- if (echo)
- debug::println("g =", g);
- }
-
- if (echo)
- {
- unsigned n_regmins_g;
- debug::println( "regmin(g)", labeling::regional_minima(g, nbh, n_regmins_g) );
- }
-
- return g;
- }
-
-
- template <typename A, typename I, typename N>
- void
- test_filter(A a, mln_result(A) lambda,
- const I& f, const I& g, const N& nbh,
- bool echo = false)
- {
- mln_concrete(I) g_ref = morpho::closing_attribute<A>(f, nbh, lambda);
- if (echo)
- debug::println("g_ref =", g_ref);
-
- unsigned n_regmins_g_ref;
- mln_ch_value(I, unsigned) regmin_g = labeling::regional_minima(g_ref, nbh, n_regmins_g_ref);
- if (echo)
- std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
- << std::endl;
-
- if (g != g_ref)
- std::cerr << "OOPS: g DIFFERS FROM ref!" << std::endl
- << std::endl;
-
-// bool consistency = (n_regmins_g_ref + less == n_objects);
-// if (consistency == false)
-// std::cerr << "OOPS: INCONSISTENCY (BUG...)!" << std::endl
-// << std::endl;
- }
-
-
-
-} // mln
-
-
-
-void usage(char* argv[])
-{
- std::cerr << "usage: " << argv[0] << " input.ppm n output.ppm" << std::endl;
- std::cerr << " n >= 2" << std::endl;
- abort();
-}
-
-
-
-int main(int argc, char* argv[])
-{
- using namespace mln;
- using value::int_u8;
- using value::rgb8;
-
- if (argc != 4)
- usage(argv);
-
-
- {
-
- // Color version.
- // --------------
-
-
- image2d<rgb8> input;
- io::ppm::load(input, argv[1]);
-
- unsigned n_objects = atoi(argv[2]);
-
-
- // Changing input into 'f on edges'.
-
- image2d<int_u8> f_;
- image2d<rgb8> input_ = image2full(input);
- {
- f_ = dist(extend(input_ | is_edge, pw::value(input_)),
- e2c());
- }
- mln_VAR(f, f_ | is_edge);
- typedef f_t I;
-
-
- // Filtering f -> g.
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- typedef morpho::tree::data<I,S> tree_t;
- tree_t t(f, s, e2e());
-
-// accu::count< util::pix<I> > a_;
-// accu::volume<I> a_;
- accu::sum_pix< util::pix<I> > a_;
-
-// blen_image = input_;
-// accu::blen_pix<I> a_;
-
- mln_VAR(a, compute_attribute_on_nodes(a_, t));
-
- mln_value_(a_t) lambda;
- f_t g = filter(a, t, e2e(), n_objects, lambda);
-
- test_filter(a_, lambda, f, g, e2e());
-
-
- // Watershed transform.
-
- int_u8 nbasins;
- mln_ch_value_(f_t, int_u8) w_edges = morpho::meyer_wst(g, e2e(), nbasins);
-
- // io::pgm::save(display_edge(w_edges.unmorph_(), 0, 3), "temp_w_edges.pgm");
-
- image2d<int_u8> w_all = w_edges.unmorph_();
- {
- // edges -> squares
- mln_VAR(w_squares, w_all | is_square);
- data::paste(morpho::dilation(extend(w_squares, pw::value(w_all)),
- c4().win()),
- w_all);
- // edges -> points
- mln_VAR(w_points, w_all | is_point);
- data::paste(morpho::erosion(extend(w_points, pw::value(w_all)),
- c4().win()),
- w_all);
- }
-
- io::pgm::save(w_all, "temp_w_all.pgm");
-
- }
-
-
-// {
-// // Gray-level version.
-
-// image2d<int_u8> f_;
-// io::pgm::load(f_, argv[1]);
-
-// unsigned n_objects = atoi(argv[2]);
-
-// mln_VAR(f, f_ | is_edge);
-// typedef f_t I;
-
-// typedef p_array<point2d> S;
-// S s = level::sort_psites_decreasing(f);
-
-// typedef morpho::tree::data<I,S> tree_t;
-// tree_t t(f, s, e2e());
-
-// accu::count< util::pix<I> > a_;
-// mln_VAR(a, compute_attribute_on_nodes(a_, t));
-
-// f_t g = filter(a, t, e2e(), n_objects);
-
-// unsigned nbasins;
-// debug::println("wst =", morpho::meyer_wst(g, e2e(), nbasins));
-// }
-
-
-}
Index: geraud/color/blen_pix.hh
--- geraud/color/blen_pix.hh (revision 3151)
+++ geraud/color/blen_pix.hh (working copy)
@@ -1,174 +0,0 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
-//
-// 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, 51 Franklin Street, Fifth Floor,
-// 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 MLN_ACCU_BLEN_PIX_HH
-# define MLN_ACCU_BLEN_PIX_HH
-
-/// \file mln/accu/blen_pix.hh
-///
-/// Define an accumulator that computes a sum.
-
-# include <mln/core/concept/meta_accumulator.hh>
-# include <mln/accu/bbox.hh>
-# include <mln/accu/internal/base.hh>
-
-# include <mln/util/pix.hh> // To prevent accu::blen_pix to work on pixels (ambiguous).
-
-# include <mln/trait/value_.hh> // For mln_blen_pix.
-# include <mln/value/builtin/all.hh> // In the case of summing builtin values.
-# include <mln/literal/zero.hh> // For initialization.
-
-# include <mln/core/alias/point3d.hh>
-
-
-namespace mln
-{
-
-
- namespace accu
- {
-
-
- /// Generic blen_pix accumulator class.
- template <typename I>
- struct blen_pix : public mln::accu::internal::base< unsigned, blen_pix<I> >
- {
- typedef util::pix<I> argument;
-
- blen_pix();
-
- /// Manipulators.
- /// \{
- void init();
- void take(const argument& t);
- void take(const blen_pix<I>& other);
- /// \}
-
- void set_value(unsigned v)
- {
- len_ = v;
- }
-
- /// Get the value of the accumulator.
- unsigned to_result() const;
-
- /// Check whether this accu is able to return a result.
- /// Always true here.
- bool is_valid() const;
-
- const accu::bbox<point3d>& b() const
- {
- return b_;
- }
-
- accu::bbox<point3d>& b()
- {
- return b_;
- }
-
- protected:
-
- accu::bbox<point3d> b_;
- unsigned len_;
- };
-
-
- template <typename B>
- unsigned max_len(const Box<B>& b_)
- {
- const B& b = exact(b_);
- typedef mln_site(B) P;
- enum { n = P::dim };
- unsigned len = b.len(0);
- for (unsigned i = 1; i < n; ++i)
- if (b.len(i) > len)
- len = b.len(i);
- return len;
- }
-
-
-# ifndef MLN_INCLUDE_ONLY
-
- template <typename I>
- inline
- blen_pix<I>::blen_pix()
- {
- init();
- }
-
- template <typename I>
- inline
- void
- blen_pix<I>::init()
- {
- b_.init();
- len_ = 0;
- }
-
- template <typename I>
- inline
- void blen_pix<I>::take(const argument& pxl)
- {
- const mln_site(I)& p = pxl.p();
- accu_blen_take(b_, p);
- len_ = max_len(b_.to_result());
- }
-
- template <typename I>
- inline
- void
- blen_pix<I>::take(const blen_pix<I>& other)
- {
- b_.take(other.b());
- len_ = max_len(b_.to_result());
- }
-
- template <typename I>
- inline
- unsigned
- blen_pix<I>::to_result() const
- {
- return len_;
- }
-
- template <typename I>
- inline
- bool
- blen_pix<I>::is_valid() const
- {
- return true;
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace mln::accu
-
-} // end of namespace mln
-
-
-#endif // ! MLN_ACCU_BLEN_PIX_HH
1
0
12 Jan '09
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Uses opt::value instead .val() method in low level routines.
* mln/level/transform.spe.hh,
* mln/level/transform_inplace.hh,
* mln/data/paste.spe.hh,
* mln/data/fill_with_value.spe.hh,
* mln/data/fill_with_image.spe.hh: Update.
data/fill_with_image.spe.hh | 3 ++-
data/fill_with_value.spe.hh | 3 ++-
data/paste.spe.hh | 4 +++-
level/transform.spe.hh | 3 ++-
level/transform_inplace.hh | 3 ++-
5 files changed, 11 insertions(+), 5 deletions(-)
Index: mln/level/transform.spe.hh
--- mln/level/transform.spe.hh (revision 3150)
+++ mln/level/transform.spe.hh (working copy)
@@ -44,6 +44,7 @@
# include <mln/value/set.hh>
# include <mln/value/lut_vec.hh>
+# include <mln/opt/value.hh>
@@ -214,7 +215,7 @@
mln_ch_value(I, mln_result(F)) output;
initialize(output, input);
- mln_result(F) val = f(input.val());
+ mln_result(F) val = f(opt::value(input));
data::fill_with_value(output, val);
trace::exiting("level::impl::transform_singleton");
Index: mln/level/transform_inplace.hh
--- mln/level/transform_inplace.hh (revision 3150)
+++ mln/level/transform_inplace.hh (working copy)
@@ -38,6 +38,7 @@
# include <mln/core/concept/function.hh>
# include <mln/value/set.hh>
# include <mln/value/lut_vec.hh>
+# include <mln/opt/value.hh>
namespace mln
@@ -251,7 +252,7 @@
level::internal::transform_inplace_tests(input, f);
- input.val() = f(input.val());
+ opt::value(input) = f(opt::value(input));
trace::exiting("level::impl::transform_inplace_singleton");
}
Index: mln/data/paste.spe.hh
--- mln/data/paste.spe.hh (revision 3150)
+++ mln/data/paste.spe.hh (working copy)
@@ -42,6 +42,7 @@
# include <mln/data/memcpy_.hh>
# include <mln/core/box_runstart_piter.hh>
# include <mln/border/get.hh>
+# include <mln/opt/value.hh>
@@ -143,7 +144,8 @@
const I& input = exact(input_);
- data::fill_with_value((output_ | input.domain()).rw(), input.val());
+ data::fill_with_value((output_ | input.domain()).rw(),
+ opt::value(input));
trace::exiting("data::impl::paste_singleton");
}
Index: mln/data/fill_with_value.spe.hh
--- mln/data/fill_with_value.spe.hh (revision 3150)
+++ mln/data/fill_with_value.spe.hh (working copy)
@@ -37,6 +37,7 @@
# endif // ! MLN_DATA_FILL_WITH_VALUE_HH
# include <mln/data/memset_.hh>
+# include <mln/opt/value.hh>
# ifndef MLN_INCLUDE_ONLY
@@ -124,7 +125,7 @@
mlc_is(mln_trait_image_vw_io(I),
trait::image::vw_io::read_write))::check();
- ima.val() = static_cast<mln_value(I)>(val);
+ opt::value(ima) = static_cast<mln_value(I)>(val);
trace::exiting("data::impl::fill_with_value_singleton");
}
Index: mln/data/fill_with_image.spe.hh
--- mln/data/fill_with_image.spe.hh (revision 3150)
+++ mln/data/fill_with_image.spe.hh (working copy)
@@ -43,6 +43,7 @@
# include <mln/core/pixel.hh>
# include <mln/core/box_runstart_piter.hh>
# include <mln/border/get.hh>
+# include <mln/opt/value.hh>
# ifndef MLN_INCLUDE_ONLY
@@ -145,7 +146,7 @@
const J& data = exact(data_);
data::internal::fill_with_image_tests(ima_, data);
- data::fill_with_value(ima_, data.val());
+ data::fill_with_value(ima_, opt::value(data));
trace::exiting("data::impl::fill_with_image_singleton");
}
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Add opt::value routine.
* mln/core/image/flat_image.hh: Update specific method ands typedefs.
* mln/core/concept/image.hh: Remove check of a deprecated spe method.
* mln/opt/at.hh: Add documentation.
* mln/opt/value.hh: New, opt::value routine.
* mln/value/sign.hh: Update documentation.
* tests/core/image/flat_image.cc: Update tests.
* tests/opt/value.cc: New tests.
mln/core/concept/image.hh | 3
mln/core/image/flat_image.hh | 30 ++-------
mln/opt/at.hh | 18 ++++-
mln/opt/value.hh | 124 +++++++++++++++++++++++++++++++++++++++++
mln/value/sign.hh | 2
tests/core/image/flat_image.cc | 2
tests/opt/value.cc | 52 +++++++++++++++++
7 files changed, 201 insertions(+), 30 deletions(-)
Index: mln/core/image/flat_image.hh
--- mln/core/image/flat_image.hh (revision 3149)
+++ mln/core/image/flat_image.hh (working copy)
@@ -117,7 +117,7 @@
typedef const T& rvalue;
/// Return type of read-write access.
- typedef const T& lvalue;
+ typedef T& lvalue;
/// Constructor without argument.
@@ -140,13 +140,12 @@
const T& operator()(const mln_psite(S)& p) const;
/// Read-write access to the image value located at point \p p.
- const T& operator()(const mln_psite(S)& p);
+ T& operator()(const mln_psite(S)& p);
- /// Change the image value.
- void change_value(const T& old_val, const T& new_val);
- const T& val() const;
- T& val();
+ /// Specific methods.
+ const T& value_() const;
+ T& value_();
};
@@ -238,7 +237,7 @@
template <typename T, typename S>
inline
- const T&
+ T&
flat_image<T,S>::operator()(const mln_psite(S)&)
{
mln_precondition(this->is_valid());
@@ -247,21 +246,8 @@
template <typename T, typename S>
inline
- void
- flat_image<T,S>::change_value(const T& old_val, const T& new_val)
- {
- mln_precondition(this->is_valid());
- mln_precondition(old_val == this->data_->val_);
- this->data_->val_ = new_val;
-
- /// Avoid warning when NDEBUG is set
- (void) old_val;
- }
-
- template <typename T, typename S>
- inline
const T&
- flat_image<T,S>::val() const
+ flat_image<T,S>::value_() const
{
mln_precondition(this->is_valid());
return this->data_->val_;
@@ -270,7 +256,7 @@
template <typename T, typename S>
inline
T&
- flat_image<T,S>::val()
+ flat_image<T,S>::value_()
{
mln_precondition(this->is_valid());
return this->data_->val_;
Index: mln/core/concept/image.hh
--- mln/core/concept/image.hh (revision 3149)
+++ mln/core/concept/image.hh (working copy)
@@ -148,9 +148,6 @@
{
static void run()
{
- void (E::*m)(const typename E::value& old_val,
- const typename E::value& new_val) = & E::change_value;
- m = 0;
}
};
Index: mln/opt/at.hh
--- mln/opt/at.hh (revision 3149)
+++ mln/opt/at.hh (working copy)
@@ -31,7 +31,7 @@
/// \file mln/opt/at.hh
///
-/// FIXME
+/// Define the optional routine at.
# include <mln/core/concept/image.hh>
# include <mln/trait/images.hh>
@@ -48,26 +48,38 @@
{
/// One dimension
+ /// Read-only access to the \p ima value located at (\p ind).
template <typename I>
mln_rvalue(I) at(const Image<I>& ima, def::coord ind);
+ /// Read-write access to the \p ima value located at (\p ind).
template <typename I>
mln_lvalue(I) at(Image<I>& ima, def::coord ind);
/// Two dimensions
+ /// Read-only access to the \p ima value located at (\p row, \p col).
template <typename I>
mln_rvalue(I) at(const Image<I>& ima, def::coord row, def::coord col);
+ /// Read-write access to the \p ima value located at (\p row, \p col).
template <typename I>
mln_lvalue(I) at(Image<I>& ima, def::coord row, def::coord col);
/// Three dimensions
+ /// Read-only access to the \p ima value located at
+ /// (\p sli, \p row, \p col).
template <typename I>
- mln_rvalue(I) at(const Image<I>& ima, def::coord sli, def::coord row, def::coord col);
+ mln_rvalue(I) at(const Image<I>& ima,
+ def::coord sli, def::coord row, def::coord col);
+
+
+ /// Read-write access to the \p ima value located at
+ /// (\p sli, \p row, \p col).
template <typename I>
- mln_lvalue(I) at(Image<I>& ima, def::coord sli, def::coord row, def::coord col);
+ mln_lvalue(I) at(Image<I>& ima,
+ def::coord sli, def::coord row, def::coord col);
# ifndef MLN_INCLUDE_ONLY
Index: mln/opt/value.hh
--- mln/opt/value.hh (revision 0)
+++ mln/opt/value.hh (revision 0)
@@ -0,0 +1,124 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// 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, 51 Franklin Street, Fifth Floor,
+// 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 MLN_OPT_VALUE_HH
+# define MLN_OPT_VALUE_HH
+
+/// \file mln/opt/value.hh
+///
+/// Define the opt::value routine.
+
+# include <mln/core/concept/image.hh>
+# include <mln/trait/images.hh>
+
+namespace mln
+{
+
+ namespace opt
+ {
+
+ template <typename I>
+ inline
+ mln_rvalue(I) value(const Image<I>& ima);
+
+ template <typename I>
+ inline
+ mln_lvalue(I) value(Image<I>& ima);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ template <typename I>
+ inline
+ mln_rvalue(I) value_impl(trait::image::category::domain_morpher,
+ const Image<I>& ima)
+ {
+ return value(*exact(ima).delegatee_());
+ }
+
+ template <typename I>
+ inline
+ mln_rvalue(I) value_impl(trait::image::category::any,
+ const Image<I>& ima)
+ {
+ mlc_is(mln_trait_image_value_storage(I),
+ trait::image::value_storage::singleton)::check();
+ return exact(ima).value_();
+ }
+
+
+
+
+ template <typename I>
+ inline
+ mln_lvalue(I) value_impl(trait::image::category::domain_morpher,
+ Image<I>& ima)
+ {
+ return value(*exact(ima).delegatee_());
+ }
+
+ template <typename I>
+ inline
+ mln_lvalue(I) value_impl(trait::image::category::any,
+ Image<I>& ima)
+ {
+ mlc_is(mln_trait_image_value_storage(I),
+ trait::image::value_storage::singleton)::check();
+ return exact(ima).value_();
+ }
+ }
+
+
+ template <typename I>
+ inline
+ mln_rvalue(I) value(const Image<I>& ima)
+ {
+ return impl::value_impl(mln_trait_image_category(I)(), ima);
+ }
+
+ template <typename I>
+ inline
+ mln_lvalue(I) value(Image<I>& ima)
+ {
+ return impl::value_impl(mln_trait_image_category(I)(), ima);
+ }
+
+
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::opt
+
+} // end of namespace mln
+
+
+#endif // ! MLN_OPT_VALUE_HH
Index: mln/value/sign.hh
--- mln/value/sign.hh (revision 3149)
+++ mln/value/sign.hh (working copy)
@@ -52,7 +52,7 @@
class sign : public internal::Integer<sign>
{
public:
- /// FIXME is these typedefs correct?
+ /// FIXME Are these typedefs correct?
/// Define the encoding type
typedef int enc;
Index: tests/core/image/flat_image.cc
--- tests/core/image/flat_image.cc (revision 3149)
+++ tests/core/image/flat_image.cc (working copy)
@@ -51,7 +51,7 @@
{
val = 9;
- test.val() = 9;
+ test.value_() = 9;
mln_piter_(I) p(test.domain());
for_all(p)
mln_assertion(test(p) == val);
Index: tests/opt/value.cc
--- tests/opt/value.cc (revision 0)
+++ tests/opt/value.cc (revision 0)
@@ -0,0 +1,52 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// 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, 51 Franklin Street, Fifth Floor,
+// 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.
+
+/// \file tests/opt/at.cc
+///
+/// Tests on mln::opt::at.
+
+#include <mln/opt/value.hh>
+#include <mln/core/image/flat_image.hh>
+#include <mln/core/alias/box2d.hh>
+
+#include <mln/trace/all.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ short val = 6;
+ typedef flat_image<short, box2d> I;
+ I ima(val, box2d(3, 4));
+
+ opt::value(ima) = 51;
+ mln_precondition(opt::value(ima) == 51);
+
+
+}
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Augment color segmentation algorithm.
* geraud/tufa_2008/filter_n.cc: Simplify a test.
* geraud/color/sum_pix.hh: New.
* geraud/color/blen_pix.hh: New.
* geraud/color/segment.cc: Augment.
color/blen_pix.hh | 174 +++++++++++++++
color/segment.cc | 561 ++++++++++++++++++++++++++++++++++++++++++--------
color/sum_pix.hh | 162 ++++++++++++++
tufa_2008/filter_n.cc | 2
4 files changed, 810 insertions(+), 89 deletions(-)
Index: geraud/tufa_2008/filter_n.cc
--- geraud/tufa_2008/filter_n.cc (revision 3148)
+++ geraud/tufa_2008/filter_n.cc (working copy)
@@ -164,7 +164,7 @@
if (! t.is_root(p))
{
acc(t.parent(p)).take(acc(p));
- if (t.f()(t.parent(p)) != t.f()(p)) // not within a flat zone
+ if (t.is_a_node(p))
++nchildren(t.parent(p)); // so parent(p) is a node
}
// Back-propagate attribute from a node to sites of its
Index: geraud/color/sum_pix.hh
--- geraud/color/sum_pix.hh (revision 0)
+++ geraud/color/sum_pix.hh (revision 0)
@@ -0,0 +1,162 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// 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, 51 Franklin Street, Fifth Floor,
+// 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 MLN_ACCU_SUM_PIX_HH
+# define MLN_ACCU_SUM_PIX_HH
+
+/// \file mln/accu/sum_pix.hh
+///
+/// Define an accumulator that computes a sum.
+
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/accu/internal/base.hh>
+
+# include <mln/util/pix.hh> // To prevent accu::sum_pix to work on pixels (ambiguous).
+
+# include <mln/trait/value_.hh> // For mln_sum_pix.
+# include <mln/value/builtin/all.hh> // In the case of summing builtin values.
+# include <mln/literal/zero.hh> // For initialization.
+
+
+namespace mln
+{
+
+ namespace accu
+ {
+
+
+ /// Generic sum_pix accumulator class.
+ /*!
+ * Parameter \c T is the type of values that we sum. Parameter \c
+ * S is the type to store the value sum; the default type of
+ * \c S is the summation type (property) of \c T.
+ */
+ template <typename P, typename S = mln_sum(mln_value(P))>
+ struct sum_pix : public mln::accu::internal::base< const S&, sum_pix<P,S> >
+ {
+ typedef P argument;
+
+ sum_pix();
+
+ /// Manipulators.
+ /// \{
+ void init();
+ void take(const argument& t);
+ void take(const sum_pix<P,S>& other);
+ /// \}
+
+ void set_value(S v)
+ {
+ s_ = v;
+ }
+
+ /// Get the value of the accumulator.
+ const S& to_result() const;
+
+ /// Check whether this accu is able to return a result.
+ /// Always true here.
+ bool is_valid() const;
+
+ protected:
+
+ S s_;
+ };
+
+
+ namespace meta
+ {
+
+ /// Meta accumulator for sum_pix.
+ struct sum_pix : public Meta_Accumulator< sum_pix >
+ {
+ template <typename P, typename S = mln_sum(mln_value(P))>
+ struct with
+ {
+ typedef accu::sum_pix<P, S> ret;
+ };
+ };
+
+ } // end of namespace mln::accu::meta
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename P, typename S>
+ inline
+ sum_pix<P,S>::sum_pix()
+ {
+ init();
+ }
+
+ template <typename P, typename S>
+ inline
+ void
+ sum_pix<P,S>::init()
+ {
+ s_ = literal::zero;
+ }
+
+ template <typename P, typename S>
+ inline
+ void sum_pix<P,S>::take(const argument& p)
+ {
+ s_ += 1 + p.v();
+ }
+
+ template <typename P, typename S>
+ inline
+ void
+ sum_pix<P,S>::take(const sum_pix<P,S>& other)
+ {
+ s_ += other.s_;
+ }
+
+ template <typename P, typename S>
+ inline
+ const S&
+ sum_pix<P,S>::to_result() const
+ {
+ return s_;
+ }
+
+ template <typename P, typename S>
+ inline
+ bool
+ sum_pix<P,S>::is_valid() const
+ {
+ return true;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_SUM_PIX_HH
Index: geraud/color/segment.cc
--- geraud/color/segment.cc (revision 3148)
+++ geraud/color/segment.cc (working copy)
@@ -1,25 +1,78 @@
+#include <cstdlib>
+
# include <mln/core/var.hh>
# include <mln/core/image/image2d.hh>
+#include <mln/core/alias/box3d.hh>
+
# include <mln/core/alias/neighb2d.hh>
+#include <mln/make/double_neighb2d.hh>
# include <mln/core/image/image_if.hh>
-# include <mln/core/routine/extend.hh>
# include <mln/pw/all.hh>
+#include <mln/core/routine/extend.hh>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/data/paste.hh>
-# include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
# include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/load.hh>
# include <mln/io/ppm/save.hh>
+
# include <mln/math/diff_abs.hh>
-# include <mln/make/double_neighb2d.hh>
-# include <mln/data/paste.hh>
-# include <mln/morpho/closing_volume.hh>
-# include <mln/morpho/meyer_wst.hh>
+#include <mln/debug/println.hh>
+
# include <mln/morpho/dilation.hh>
# include <mln/morpho/erosion.hh>
+#include <mln/morpho/tree/data.hh>
+#include <mln/morpho/meyer_wst.hh>
+#include <mln/morpho/closing_attribute.hh>
+
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+#include <mln/labeling/regional_minima.hh>
+
+
+#include <mln/accu/count.hh>
+#include <mln/accu/volume.hh>
+
+#include "sum_pix.hh"
+
+
+namespace mln
+{
+
+ point3d color2point(const value::rgb8& c)
+ {
+ point3d p(c.red(), c.green(), c.blue());
+ return p;
+ }
+
+
+ image2d<value::rgb8> blen_image;
+
+
+ template <typename B>
+ void accu_blen_take(B& b, const point2d& e)
+ {
+ if (e.row() % 2)
+ {
+ b.take(color2point(blen_image(e + up)));
+ b.take(color2point(blen_image(e + down)));
+ }
+ else
+ {
+ b.take(color2point(blen_image(e + left)));
+ b.take(color2point(blen_image(e + right)));
+ }
+ }
+
+}
+
+#include "blen_pix.hh"
+
-# include <mln/debug/println.hh>
namespace mln
@@ -52,8 +105,69 @@
}
+ // Neighborhoods.
+
+ typedef neighb< win::multiple<window2d, bool(*)(const point2d&)> > dbl_neighb2d;
+
+ const dbl_neighb2d& e2c()
+ {
+ static bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ static bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+ static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2c_h, e2c_v);
+ return nbh;
+ }
+
+ const dbl_neighb2d& e2e()
+ {
+ static bool e2e_h[] = { 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0 };
+ static bool e2e_v[] = { 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0 };
+ static dbl_neighb2d nbh = make::double_neighb2d(is_row_odd, e2e_h, e2e_v);
+ return nbh;
+ }
+
+
// Transforms.
+ template <typename T>
+ image2d<T>
+ image2full(const image2d<T>& input)
+ {
+ image2d<T> output(2 * input.nrows() - 1,
+ 2 * input.ncols() - 1);
+ for (int row = 0; row < input.nrows(); ++row)
+ for (int col = 0; col < input.ncols(); ++col)
+ opt::at(output, 2 * row, 2 * col) = opt::at(input, row, col);
+ return output;
+ }
+
+ template <typename T>
+ image2d<T>
+ full2image(const image2d<T>& input)
+ {
+ image2d<T> output((input.nrows() + 1) / 2,
+ (input.ncols() + 1) / 2);
+ for (int row = 0; row < input.nrows(); row += 2)
+ for (int col = 0; col < input.ncols(); col += 2)
+ opt::at(output, row / 2, col / 2) =
+ opt::at(input, row, col);
+ return output;
+ }
+
+
+ // Display.
+
template <typename I>
I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
{
@@ -82,31 +196,6 @@
return output;
}
- template <typename T>
- image2d<T>
- image2squares(const image2d<T>& input)
- {
- image2d<T> output(2 * input.nrows() - 1,
- 2 * input.ncols() - 1);
- for (int row = 0; row < input.nrows(); ++row)
- for (int col = 0; col < input.ncols(); ++col)
- opt::at(output, 2 * row, 2 * col) = opt::at(input, row, col);
- return output;
- }
-
- template <typename T>
- image2d<T>
- squares2image(const image2d<T>& input)
- {
- image2d<T> output((input.nrows() + 1) / 2,
- (input.ncols() + 1) / 2);
- for (int row = 0; row < input.nrows(); row += 2)
- for (int col = 0; col < input.ncols(); col += 2)
- opt::at(output, row / 2, col / 2) =
- opt::at(input, row, col);
- return output;
- }
-
// Distance.
@@ -145,6 +234,285 @@
}
+ // Sorting.
+
+
+ template <typename I>
+ struct my_less_
+ {
+ const I& ima_;
+
+ inline
+ my_less_(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ inline
+ bool operator()(const mln_site(I)& lhs,
+ const mln_site(I)& rhs) const
+ {
+ return util::ord_strict(ima_(lhs), ima_(rhs))
+ || (ima_(lhs) == ima_(rhs)
+ &&
+ util::ord_strict(lhs, rhs));
+ }
+ };
+
+
+ template <typename I, typename S>
+ p_array<mln_site(I)> my_sort_increasing(const I& ima, const S& s)
+ {
+ p_array<mln_site(I)> v;
+ convert::from_to(s, v);
+ std::sort(v.hook_std_vector_().begin(), v.hook_std_vector_().end(),
+ my_less_<I>(ima));
+ return v;
+ }
+
+
+
+
+ // Tree -> attributes (on nodes only).
+ // -----------------------------------
+
+
+
+ template <typename A, typename T>
+ inline
+ mln_ch_value(typename T::function, mln_result(A))
+ compute_attribute_on_nodes(const A& a, const T& t)
+ {
+ typedef typename T::function I;
+
+ mln_ch_value(I, A) acc;
+ mln_ch_value(I, mln_result(A)) attr;
+
+ // Initialization of 'acc'.
+ {
+ initialize(acc, t.f());
+ data::fill(acc, a); // Transfer "dynamic data" (state) of 'a'.
+ }
+
+ // Initialize every attribute with the corresponding pixel.
+ {
+ mln_piter(I) p(t.f().domain());
+ for_all(p)
+ acc(p).take_as_init(make::pix(t.f(), p));
+ }
+
+ // Propagate attribute from a site to its parent.
+ {
+ mln_fwd_piter(T) p(t.domain());
+ for_all(p)
+ if (! t.is_root(p))
+ acc(t.parent(p)).take(acc(p));
+ // No back-propagation to non-node sites.
+ }
+
+
+ // Change accumulator into its result.
+ {
+ initialize(attr, acc);
+ typedef typename T::nodes_t N;
+ mln_piter(N) p(t.nodes());
+ for_all(p)
+ {
+ mln_invariant(t.is_a_node(p));
+ attr(p) = acc(p).to_result();
+ }
+ }
+
+ return attr;
+ }
+
+
+ template <typename A, typename T>
+ inline
+ mln_ch_value(typename T::function, mln_result(A))
+ compute_rand_attribute_on_nodes(const A& a, const T& t)
+ {
+ typedef typename T::function I;
+
+ mln_ch_value(I, mln_result(A)) attr;
+ initialize(attr, t.f());
+
+ // Initialize every attribute with the corresponding pixel.
+ {
+ mln_piter(I) p(t.f().domain());
+ for_all(p)
+ attr(p) = float(std::rand() % 10000) / 1000.f;
+ }
+
+ // Propagate attribute from a site to its parent.
+ {
+ mln_fwd_piter(T) p(t.domain());
+ for_all(p)
+ if (! t.is_root(p))
+ attr(t.parent(p)) += attr(p);
+ }
+
+ return attr;
+ }
+
+
+
+ // Tree -> nchildren (on nodes).
+ // -----------------------------
+
+
+ template <typename T>
+ inline
+ mln_ch_value(typename T::function, unsigned)
+ compute_nchildren(const T& t)
+ {
+ typedef typename T::function I;
+ mln_ch_value(I, unsigned) nchildren;
+ initialize(nchildren, t.f());
+ data::fill(nchildren, 0);
+
+ {
+ mln_fwd_piter(T) p(t.domain());
+ // Propagate attribute from a site to its parent.
+ for_all(p)
+ if (t.is_a_non_root_node(p))
+ {
+ mln_invariant(t.is_a_node(t.parent(p)));
+ ++nchildren(t.parent(p)); // so parent(p) is a node
+ }
+ }
+
+ return nchildren;
+ }
+
+
+
+
+ template <typename A, typename T, typename N>
+ inline
+ mln_concrete(typename T::function)
+ filter(const A& a, const T& t, const N& nbh,
+ unsigned n_objects,
+ mln_value(A)& lambda,
+ bool echo = false)
+ {
+ typedef typename T::function I;
+
+ unsigned n_regmins_f; // This value can be obtained while computing the attributes!
+ mln_ch_value(I, unsigned) regmins_f = labeling::regional_minima(t.f(), nbh, n_regmins_f);
+ if (echo)
+ {
+ debug::println("f =", t.f());
+ debug::println("regmins(f) =", regmins_f);
+ // debug::println("par on nodes = ", t.parent_image() | t.nodes());
+ std::cout << "n regmins(f) = " << n_regmins_f << std::endl
+ << std::endl;
+ }
+ if (n_objects >= n_regmins_f)
+ {
+ std::cout << "warning: number of expected objects is greater than number of regmins!" << std::endl;
+ std::cout << "aborting..." << std::endl;
+ return duplicate(t.f());
+ }
+
+ lambda = mln_max(mln_value(A));
+
+ mln_ch_value(typename T::function, unsigned) nchildren = compute_nchildren(t);
+
+ typedef p_array<mln_site(I)> S;
+ S s = my_sort_increasing(a, t.nodes());
+
+ const typename T::parent_t& par = t.parent_image();
+
+ unsigned
+ count = n_regmins_f,
+ less = 0;
+ mln_fwd_piter(S) p(s);
+ for_all(p)
+ {
+ if (a(p) < lambda && par(p) != p)
+ {
+ mln_assertion(nchildren(par(p)) > 0);
+ --nchildren(par(p));
+ if (nchildren(par(p)) != 0)
+ {
+ if (count <= n_objects)
+ {
+ ++less; // minus 1 object wrt the expected number!
+ }
+ --count;
+ if (count == n_objects)
+ {
+ lambda = a(p) + 1;
+ std::cout << "lambda = " << lambda << std::endl
+ << std::endl;
+ // break; // Stop iterations.
+ }
+ }
+ }
+ }
+
+ if (less != 0)
+ std::cerr << "WARNING: less objects (" << less << ") than expected..." << std::endl
+ << std::endl;
+
+ if (echo)
+ debug::println("nchildren =", nchildren | t.nodes());
+
+
+ // Filtering.
+ mln_concrete(I) g;
+ {
+ initialize(g, t.f());
+ mln_bkd_piter(T) p(t.domain());
+ for_all(p)
+ if (t.is_a_node(p) && a(p) >= lambda)
+ g(p) = t.f(p);
+ else
+ g(p) = g(par(p));
+
+ if (echo)
+ debug::println("g =", g);
+ }
+
+ if (echo)
+ {
+ unsigned n_regmins_g;
+ debug::println( "regmin(g)", labeling::regional_minima(g, nbh, n_regmins_g) );
+ }
+
+ return g;
+ }
+
+
+ template <typename A, typename I, typename N>
+ void
+ test_filter(A a, mln_result(A) lambda,
+ const I& f, const I& g, const N& nbh,
+ bool echo = false)
+ {
+ mln_concrete(I) g_ref = morpho::closing_attribute<A>(f, nbh, lambda);
+ if (echo)
+ debug::println("g_ref =", g_ref);
+
+ unsigned n_regmins_g_ref;
+ mln_ch_value(I, unsigned) regmin_g = labeling::regional_minima(g_ref, nbh, n_regmins_g_ref);
+ if (echo)
+ std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
+ << std::endl;
+
+ if (g != g_ref)
+ std::cerr << "OOPS: g DIFFERS FROM ref!" << std::endl
+ << std::endl;
+
+// bool consistency = (n_regmins_g_ref + less == n_objects);
+// if (consistency == false)
+// std::cerr << "OOPS: INCONSISTENCY (BUG...)!" << std::endl
+// << std::endl;
+ }
+
+
+
} // mln
@@ -167,88 +535,105 @@
if (argc != 4)
usage(argv);
- image2d<rgb8> raw_input, input;
-
- io::ppm::load(raw_input, argv[1]);
- input = image2squares(raw_input);
- // e2c
-
- bool e2c_h[] = { 0, 1, 0,
- 0, 0, 0,
- 0, 1, 0 };
+ {
- bool e2c_v[] = { 0, 0, 0,
- 1, 0, 1,
- 0, 0, 0 };
+ // Color version.
+ // --------------
- mln_VAR( e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v) );
+ image2d<rgb8> input;
+ io::ppm::load(input, argv[1]);
+ unsigned n_objects = atoi(argv[2]);
- image2d<int_u8> G = dist(extend(input | is_edge, pw::value(input)),
- e2c);
- mln_VAR(G_edges, G | is_edge);
+ // Changing input into 'f on edges'.
- /*
+ image2d<int_u8> f_;
+ image2d<rgb8> input_ = image2full(input);
{
- io::pgm::save(display_edge(G, 0, 3),
- "temp_G.pgm");
+ f_ = dist(extend(input_ | is_edge, pw::value(input_)),
+ e2c());
}
- */
+ mln_VAR(f, f_ | is_edge);
+ typedef f_t I;
- // e2e
- bool e2e_h[] = { 0, 0, 1, 0, 0,
- 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 0,
- 0, 0, 1, 0, 0 };
+ // Filtering f -> g.
- bool e2e_v[] = { 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 0,
- 1, 0, 0, 0, 1,
- 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0 };
+ typedef p_array<point2d> S;
+ S s = level::sort_psites_decreasing(f);
- mln_VAR( e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v) );
+ typedef morpho::tree::data<I,S> tree_t;
+ tree_t t(f, s, e2e());
- data::paste( morpho::closing_volume(G_edges, e2e, 50), G_edges );
+// accu::count< util::pix<I> > a_;
+// accu::volume<I> a_;
+ accu::sum_pix< util::pix<I> > a_;
- /*
- {
- io::pgm::save(display_edge(G_edges.unmorph_(), 0, 3),
- "temp_G_closed.pgm");
- }
- */
+// blen_image = input_;
+// accu::blen_pix<I> a_;
+
+ mln_VAR(a, compute_attribute_on_nodes(a_, t));
+
+ mln_value_(a_t) lambda;
+ f_t g = filter(a, t, e2e(), n_objects, lambda);
+
+ test_filter(a_, lambda, f, g, e2e());
+
+
+ // Watershed transform.
int_u8 nbasins;
- mln_VAR(W_edges, morpho::meyer_wst(G_edges, e2e, nbasins));
+ mln_ch_value_(f_t, int_u8) w_edges = morpho::meyer_wst(g, e2e(), nbasins);
+
+ // io::pgm::save(display_edge(w_edges.unmorph_(), 0, 3), "temp_w_edges.pgm");
- /*
+ image2d<int_u8> w_all = w_edges.unmorph_();
{
- io::pgm::save(display_edge(W_edges.unmorph_(), 0, 3),
- "temp_W_edges.pgm");
+ // edges -> squares
+ mln_VAR(w_squares, w_all | is_square);
+ data::paste(morpho::dilation(extend(w_squares, pw::value(w_all)),
+ c4().win()),
+ w_all);
+ // edges -> points
+ mln_VAR(w_points, w_all | is_point);
+ data::paste(morpho::erosion(extend(w_points, pw::value(w_all)),
+ c4().win()),
+ w_all);
}
- */
- mln_VAR(W_all, W_edges.unmorph_());
+ io::pgm::save(w_all, "temp_w_all.pgm");
+ }
- mln_VAR(W_squares, W_all | is_square);
- data::paste(morpho::dilation(extend(W_squares, pw::value(W_all)),
- c4().win()),
- W_all);
- mln_VAR(W_points, W_all | is_point);
- data::paste(morpho::erosion(extend(W_points, pw::value(W_all)),
- c4().win()),
- W_all);
+// {
+// // Gray-level version.
+// image2d<int_u8> f_;
+// io::pgm::load(f_, argv[1]);
+
+// unsigned n_objects = atoi(argv[2]);
+
+// mln_VAR(f, f_ | is_edge);
+// typedef f_t I;
+
+// typedef p_array<point2d> S;
+// S s = level::sort_psites_decreasing(f);
+
+// typedef morpho::tree::data<I,S> tree_t;
+// tree_t t(f, s, e2e());
+
+// accu::count< util::pix<I> > a_;
+// mln_VAR(a, compute_attribute_on_nodes(a_, t));
+
+// f_t g = filter(a, t, e2e(), n_objects);
+
+// unsigned nbasins;
+// debug::println("wst =", morpho::meyer_wst(g, e2e(), nbasins));
+// }
- {
- io::pgm::save(W_all, "temp_W_all.pgm");
- }
}
Index: geraud/color/blen_pix.hh
--- geraud/color/blen_pix.hh (revision 0)
+++ geraud/color/blen_pix.hh (revision 0)
@@ -0,0 +1,174 @@
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// 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, 51 Franklin Street, Fifth Floor,
+// 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 MLN_ACCU_BLEN_PIX_HH
+# define MLN_ACCU_BLEN_PIX_HH
+
+/// \file mln/accu/blen_pix.hh
+///
+/// Define an accumulator that computes a sum.
+
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/accu/bbox.hh>
+# include <mln/accu/internal/base.hh>
+
+# include <mln/util/pix.hh> // To prevent accu::blen_pix to work on pixels (ambiguous).
+
+# include <mln/trait/value_.hh> // For mln_blen_pix.
+# include <mln/value/builtin/all.hh> // In the case of summing builtin values.
+# include <mln/literal/zero.hh> // For initialization.
+
+# include <mln/core/alias/point3d.hh>
+
+
+namespace mln
+{
+
+
+ namespace accu
+ {
+
+
+ /// Generic blen_pix accumulator class.
+ template <typename I>
+ struct blen_pix : public mln::accu::internal::base< unsigned, blen_pix<I> >
+ {
+ typedef util::pix<I> argument;
+
+ blen_pix();
+
+ /// Manipulators.
+ /// \{
+ void init();
+ void take(const argument& t);
+ void take(const blen_pix<I>& other);
+ /// \}
+
+ void set_value(unsigned v)
+ {
+ len_ = v;
+ }
+
+ /// Get the value of the accumulator.
+ unsigned to_result() const;
+
+ /// Check whether this accu is able to return a result.
+ /// Always true here.
+ bool is_valid() const;
+
+ const accu::bbox<point3d>& b() const
+ {
+ return b_;
+ }
+
+ accu::bbox<point3d>& b()
+ {
+ return b_;
+ }
+
+ protected:
+
+ accu::bbox<point3d> b_;
+ unsigned len_;
+ };
+
+
+ template <typename B>
+ unsigned max_len(const Box<B>& b_)
+ {
+ const B& b = exact(b_);
+ typedef mln_site(B) P;
+ enum { n = P::dim };
+ unsigned len = b.len(0);
+ for (unsigned i = 1; i < n; ++i)
+ if (b.len(i) > len)
+ len = b.len(i);
+ return len;
+ }
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ blen_pix<I>::blen_pix()
+ {
+ init();
+ }
+
+ template <typename I>
+ inline
+ void
+ blen_pix<I>::init()
+ {
+ b_.init();
+ len_ = 0;
+ }
+
+ template <typename I>
+ inline
+ void blen_pix<I>::take(const argument& pxl)
+ {
+ const mln_site(I)& p = pxl.p();
+ accu_blen_take(b_, p);
+ len_ = max_len(b_.to_result());
+ }
+
+ template <typename I>
+ inline
+ void
+ blen_pix<I>::take(const blen_pix<I>& other)
+ {
+ b_.take(other.b());
+ len_ = max_len(b_.to_result());
+ }
+
+ template <typename I>
+ inline
+ unsigned
+ blen_pix<I>::to_result() const
+ {
+ return len_;
+ }
+
+ template <typename I>
+ inline
+ bool
+ blen_pix<I>::is_valid() const
+ {
+ return true;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_BLEN_PIX_HH
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add some commentary.
* mln/core/internal/site_relative_iterator_base.hh:
(center_at_): Add some commentary.
* mln/morpho/general.spe.hh: Remove obsolete FIXME.
core/internal/site_relative_iterator_base.hh | 3 ++-
morpho/general.spe.hh | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
Index: mln/core/internal/site_relative_iterator_base.hh
--- mln/core/internal/site_relative_iterator_base.hh (revision 3147)
+++ mln/core/internal/site_relative_iterator_base.hh (working copy)
@@ -147,7 +147,7 @@
{
mlc_converts_to(P, const mln_psite(S)&)::check();
c_ = & static_cast< const mln_psite(S)& >(c);
- exact(this)->center_at_(c);
+ exact(this)->center_at_(c); // May call some extra code.
this->invalidate();
}
@@ -240,6 +240,7 @@
void
site_relative_iterator_base<S,E>::center_at_(const P& c)
{
+ // Default is no-op, meaning "no extra code".
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/morpho/general.spe.hh
--- mln/morpho/general.spe.hh (revision 3147)
+++ mln/morpho/general.spe.hh (working copy)
@@ -239,7 +239,7 @@
extension::adjust_fill(input, geom::delta(win) + 1, op.neutral(input));
mln_concrete(I) output;
- output = accu::transform_directional(op.accu_incr(input), input, win, dir); // FIXME: Use _line.
+ output = accu::transform_directional(op.accu_incr(input), input, win, dir);
trace::exiting("morpho::impl:general_directional");
return output;
1
0