https://svn.lrde.epita.fr/svn/oln/trunk
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Update milena.
* olena/oln/morpho/Rd/union_find.hh: Update.
* milena/test/main.cc: Use Rd.
* milena/morpho/Rd.hh: New.
* milena/level/fill.hh: Add assertions.
* milena/level/compare.hh: New.
* milena/level/paste.hh: New.
* milena/core/macros.hh (mln_ch_value): New.
* milena/core/concept/image.hh: Update.
* milena/core/image2d.hh: Update.
milena/core/concept/image.hh | 8 +
milena/core/image2d.hh | 6 +
milena/core/macros.hh | 4
milena/level/compare.hh | 63 +++++++++++++
milena/level/fill.hh | 20 ++++
milena/level/paste.hh | 38 +++++++
milena/morpho/Rd.hh | 181 ++++++++++++++++++++++++++++++++++++++
milena/test/main.cc | 83 +++++++++--------
olena/oln/morpho/Rd/union_find.hh | 51 +++++-----
9 files changed, 393 insertions(+), 61 deletions(-)
Index: olena/oln/morpho/Rd/union_find.hh
--- olena/oln/morpho/Rd/union_find.hh (revision 986)
+++ olena/oln/morpho/Rd/union_find.hh (working copy)
@@ -29,6 +29,7 @@
# define OLN_MORPHO_RD_UNION_FIND_HH
# include <oln/morpho/Rd/utils.hh>
+# include <oln/core/internal/max_value.hh>
namespace oln
@@ -45,6 +46,7 @@
struct union_find_t
{
typedef oln_point(I) point;
+ typedef oln_value(I) value;
// in:
I f, g;
@@ -55,8 +57,8 @@
// aux:
std::vector<point> S;
- I data;
- oln_plain_value(I, bool) is_proc;
+ // was: I data;
+ oln_plain_value(I, bool) isproc;
oln_plain_value(I, point) parent;
union_find_t(const I& f, const I& g, const N& nbh)
@@ -64,14 +66,15 @@
{
prepare(o, with, f);
prepare(parent, with, f);
- prepare(is_proc, with, f);
- prepare(data, with, f);
+ prepare(isproc, with, f);
+ // was: prepare(data, with, f);
// init
std::cout << "0 ";
- level::fill(inplace(is_proc), false);
+ level::fill(inplace(isproc), false);
S = histo_reverse_sort(g);
+ level::paste(f, inplace(o)); // new: replace make_set(p) { data(p) = f(p) }
// first pass
@@ -83,35 +86,40 @@
make_set(p);
oln_niter(N) n(nbh, p);
for_all(n)
- if (f.has(n) and is_proc(n))
+ {
+ if (f.has(n))
+ assert(isproc(n) = is_proc(n, p));
+ if (f.has(n) and isproc(n))
do_union(n, p);
- is_proc(p) = true;
+ }
+ isproc(p) = true;
}
// second pass
std::cout << "2 ";
- level::fill(inplace(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);
+ if (o(p) = oln_max(value))
+ o(p) = g(p);
else
- {
- assert(is_proc(parent(p)) = true);
o(p) = o(parent(p));
}
- is_proc(p) = true;
+
}
+ bool is_proc(const point& n, const point& p) const
+ {
+ return g(n) > g(p) or (g(n) = g(p) and n < p);
}
void make_set(const point& p)
{
parent(p) = p;
- data(p) = f(p);
+ // was: data(p) = f(p);
+ // now: in "initialization"
}
point find_root(const point& x)
@@ -122,24 +130,21 @@
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))
+ // NEW: o replaces data
+
+ if (g(r) = g(p) or g(p) >= o(r)) // equiv test
{
parent(r) = p;
- if (data(r) > data(p))
- data(p) = data(r); // increasing criterion
+ if (o(r) > o(p))
+ o(p) = o(r); // increasing criterion
}
else
- data(p) = 255;
+ o(p) = oln_max(value);
}
}
Index: milena/test/main.cc
--- milena/test/main.cc (revision 986)
+++ milena/test/main.cc (working copy)
@@ -10,11 +10,15 @@
#include <core/neighb2d.hh>
#include <morpho/erosion.hh>
+#include <morpho/Rd.hh>
-int cos_sin(const mln::point2d& p)
+typedef unsigned char int_u8;
+
+
+int_u8 cos_sin(const mln::point2d& p)
{
- return int(255 * std::cos(float(p.row())) * std::sin(float(p.col())));
+ return (int_u8)(255 * std::cos(float(p.row())) * std::sin(float(p.col())));
}
@@ -22,43 +26,46 @@
{
using namespace mln;
- box2d b = mk_box2d(/* row = */ 1, 3,
- /* col = */ 4, 6);
- std::cout << b << std::endl;
-
- bool w[] - { 0, 1, 0,
- 0, 1, 0,
- 1, 0, 0 };
- window2d win = mk_window2d(w);
- std::cout << win << std::endl;
- std::cout << c8() << std::endl;
-
- /*
- {
- image2d<int> ima(b);
- level::fill(ima, 51);
- debug::println(ima);
-
- std::cout << win << std::endl;
-
- morpho::erosion(ima, win);
-
- rectangle2d rec(1, 2);
- std::cout << rec << std::endl;
+ const unsigned size = 1000;
+ image2d<int_u8> f(size, size);
+ morpho::Rd(f, f, c8());
}
- */
-
-
- {
- image2d<int> ima(b);
- level::fill(ima, cos_sin);
- debug::println(ima);
- std::cout << std::endl;
- image2d<int> ima2 = morpho::erosion(ima, win);
- debug::println(ima2);
- }
-}
+// box2d b = mk_box2d(/* row = */ 1, 3,
+// /* col = */ 4, 6);
+// std::cout << b << std::endl;
+
+// bool w[] +// { 0, 1, 0,
+// 0, 1, 0,
+// 1, 0, 0 };
+// window2d win = mk_window2d(w);
+// std::cout << win << std::endl;
+// std::cout << c8() << std::endl;
+
+// {
+// image2d<int> ima(b);
+// level::fill(ima, 51);
+// debug::println(ima);
+
+// std::cout << win << std::endl;
+
+// morpho::erosion(ima, win);
+
+// rectangle2d rec(1, 2);
+// std::cout << rec << std::endl;
+// }
+
+
+// {
+// image2d<int> ima(b);
+// level::fill(ima, cos_sin);
+// debug::println(ima);
+
+// std::cout << std::endl;
+
+// image2d<int> ima2 = morpho::erosion(ima, win);
+// debug::println(ima2);
+// }
Index: milena/morpho/Rd.hh
--- milena/morpho/Rd.hh (revision 0)
+++ milena/morpho/Rd.hh (revision 0)
@@ -0,0 +1,181 @@
+#ifndef MLN_MORPHO_RD_HH
+# define MLN_MORPHO_RD_HH
+
+# include <vector>
+
+# include <core/concept/image.hh>
+# include <core/concept/neighborhood.hh>
+
+# include <value/props.hh>
+
+# include <level/fill.hh>
+# include <level/compare.hh>
+
+
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ template <typename I, typename N>
+ I Rd(const Image<I>& f, const Image<I>& g, const
Neighborhood<N>& nbh);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ 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_point(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_point(I)> vec(ima.domain().npoints());
+ // 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 Rd
+ {
+ typedef mln_point(I) point;
+ typedef mln_value(I) value;
+
+ // in:
+ const I& f;
+ const I& g;
+ const N& nbh;
+
+ // out:
+ I o;
+
+ // aux:
+ mln_ch_value(I, bool) is_proc;
+ mln_ch_value(I, point) parent;
+ std::vector<point> S;
+
+ Rd(const I& f, const I& g, const N& nbh)
+ : f(f), g(g), nbh(nbh),
+ o(f.domain()),
+ is_proc(f.domain()),
+ parent(f.domain())
+ {
+ // init
+ level::fill(o, f);
+ S = histo_reverse_sort(g);
+ level::fill(is_proc, false); // FIXME: rm
+
+ // 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))
+ assert(is_proc(n) = is_proc__(n, p));
+ if (f.has(n) and is_proc(n))
+ do_union(n, p);
+ }
+ is_proc(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));
+ is_proc(p) = true;
+ }
+
+ }
+
+ bool is_proc__(const point& n, const point& p) const
+ {
+ return g(n) > g(p) or (g(n) = g(p) and n < p);
+ }
+
+ void make_set(const point& p)
+ {
+ parent(p) = 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) >= o(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 (o(r) > o(p))
+ o(p) = o(r); // increasing criterion
+ }
+ else
+ o(p) = mln_max(value);
+ }
+ }
+
+ };
+
+ } // end of namespace mln::morpho::impl
+
+
+ // facade
+
+ template <typename I, typename N>
+ I Rd(const Image<I>& f, const Image<I>& g, const
Neighborhood<N>& nbh)
+ {
+ assert(f <= g);
+ impl::Rd<I,N> run(exact(f), exact(g), exact(nbh));
+ return run.o;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_RD_HH
Index: milena/level/fill.hh
--- milena/level/fill.hh (revision 986)
+++ milena/level/fill.hh (working copy)
@@ -22,6 +22,10 @@
void fill(Image<I>& ima_,
const mln_value(I) array[]);
+ template <typename I, typename J>
+ void fill(Image<I>& ima_,
+ const Image<J>& data);
+
# ifndef MLN_INCLUDE_ONLY
@@ -30,6 +34,7 @@
const mln_value(I)& value)
{
I& ima = exact(ima_);
+ assert(ima.has_data());
mln_piter(I) p(ima.domain());
for_all(p)
ima(p) = value;
@@ -40,6 +45,7 @@
mln_value(I) (*f)(const mln_point(I)& p))
{
I& ima = exact(ima_);
+ assert(ima.has_data());
mln_piter(I) p(ima.domain());
for_all(p)
ima(p) = f(p);
@@ -50,12 +56,26 @@
const mln_value(I) array[])
{
I& ima = exact(ima_);
+ assert(ima.has_data());
mln_piter(I) p(ima.domain());
unsigned i = 0;
for_all(p)
ima(p) = array[i++];
}
+ template <typename I, typename J>
+ void fill(Image<I>& ima_,
+ const Image<J>& data_)
+ {
+ I& ima = exact(ima_);
+ const J& data = exact(data_);
+ assert(ima.has_data() and data.has_data());
+
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ ima(p) = data(p);
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::level
Index: milena/level/compare.hh
--- milena/level/compare.hh (revision 0)
+++ milena/level/compare.hh (revision 0)
@@ -0,0 +1,63 @@
+#ifndef MLN_LEVEL_COMPARE_HH
+# define MLN_LEVEL_COMPARE_HH
+
+# include <core/concept/image.hh>
+
+
+namespace mln
+{
+
+ template <typename L, typename R>
+ bool operator = (const Image<L>& lhs, const Image<R>& rhs);
+
+ template <typename L, typename R>
+ bool operator < (const Image<L>& lhs, const Image<R>& rhs);
+
+ template <typename L, typename R> // required!
+ bool operator <= (const Image<L>& lhs, const Image<R>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename L, typename R>
+ bool operator = (const Image<L>& lhs_, const Image<R>& rhs_)
+ {
+ const L& lhs = exact(lhs_);
+ const R& rhs = exact(rhs_);
+ mln_piter(L) p(lhs.domain());
+ for_all(p)
+ if (not (lhs(p) = rhs(p)))
+ return false;
+ return true;
+ }
+
+ template <typename L, typename R>
+ bool operator < (const Image<L>& lhs_, const Image<R>& rhs_)
+ {
+ const L& lhs = exact(lhs_);
+ const R& rhs = exact(rhs_);
+ mln_piter(L) p(lhs.domain());
+ for_all(p)
+ if (not (lhs(p) < rhs(p)))
+ return false;
+ return true;
+ }
+
+ template <typename L, typename R> // required!
+ bool operator <= (const Image<L>& lhs_, const Image<R>& rhs_)
+ {
+ const L& lhs = exact(lhs_);
+ const R& rhs = exact(rhs_);
+ mln_piter(L) p(lhs.domain());
+ for_all(p)
+ if (not (lhs(p) <= rhs(p)))
+ return false;
+ return true;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LEVEL_COMPARE_HH
Index: milena/level/paste.hh
--- milena/level/paste.hh (revision 0)
+++ milena/level/paste.hh (revision 0)
@@ -0,0 +1,38 @@
+#ifndef MLN_LEVEL_PASTE_HH
+# define MLN_LEVEL_PASTE_HH
+
+# include <core/concept/image.hh>
+
+
+namespace mln
+{
+
+ namespace level
+ {
+
+ template <typename I, typename J>
+ void paste(const Image<I>& data, Image<J>& destination);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I, typename J>
+ void paste(const Image<I>& data_, Image<J>& destination_)
+ {
+ const I& data = exact(data_);
+ I& destination = exact(destination_);
+ assert(ima.has_data() and destination.has_data());
+
+ mln_piter(I) p(data.domain());
+ for_all(p)
+ destination(p) = data(p);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::level
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LEVEL_PASTE_HH
Index: milena/core/macros.hh
--- milena/core/macros.hh (revision 986)
+++ milena/core/macros.hh (working copy)
@@ -25,4 +25,8 @@
# define mln_rvalue(T) typename T::rvalue
# define mln_lvalue(T) typename T::lvalue
+
+# define mln_ch_value(I, T) typename I::template change_value<T>::ret
+
+
#endif // ! MLN_CORE_MACROS_HH
Index: milena/core/concept/image.hh
--- milena/core/concept/image.hh (revision 986)
+++ milena/core/concept/image.hh (working copy)
@@ -25,6 +25,12 @@
rvalue operator()(const psite& p) const;
lvalue operator()(const psite& p);
+ template <typename T>
+ struct change_value
+ {
+ typedef ret;
+ };
+
// provided by internal::image_base_:
@@ -71,6 +77,8 @@
typedef mln_rvalue(E) rvalue;
typedef mln_lvalue(E) lvalue;
+ typedef mln_ch_value(E, value) change;
+
bool (E::*m3)() const = & E::has_data;
m3 = 0;
bool (E::*m4)(const psite& p) const = & E::owns_;
Index: milena/core/image2d.hh
--- milena/core/image2d.hh (revision 986)
+++ milena/core/image2d.hh (working copy)
@@ -15,6 +15,12 @@
typedef const T& rvalue;
typedef T& lvalue;
+ template <typename U>
+ struct change_value
+ {
+ typedef image2d<U> ret;
+ };
+
image2d();
image2d(int nrows, int ncols);
image2d(const box2d& b);