cleanup-2008 2007: Add some tutorial-like files about cubical complex.
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add some tutorial-like files about cubical complex. * sandbox/geraud/cs2d/tuto.cc: New. * sandbox/geraud/cs2d/tuto_bis.cc: New. tuto.cc | 145 +++++++++++++++++++++++++++++++ tuto_bis.cc | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 422 insertions(+) Index: sandbox/geraud/cs2d/tuto.cc --- sandbox/geraud/cs2d/tuto.cc (revision 0) +++ sandbox/geraud/cs2d/tuto.cc (revision 0) @@ -0,0 +1,145 @@ +# include <mln/core/image2d.hh> +# include <mln/core/image_if.hh> + +# include <mln/core/neighb2d.hh> +# include <mln/core/window2d.hh> +# include <mln/convert/to_window.hh> + +# include <mln/debug/println.hh> +# include <mln/fun/p2v/iota.hh> +# include <mln/level/paste.hh> +# include <mln/level/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); + + level::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 + + level::fill(inplace(ima | is_cell), 'c'); + level::fill(inplace(ima | is_edge), 'e'); + level::fill(inplace(ima | is_point), 'p'); + + debug::println(ima); + // c e c e c + // e p e p e + // c e c e c + } + + { + image2d<int> ima(3, 5); + + level::fill(ima, 0); + debug::println(ima); + // 0 0 0 0 0 + // 0 0 0 0 0 + // 0 0 0 0 0 + + level::fill(inplace(ima | is_cell), 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 : + + level::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 + + level::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: sandbox/geraud/cs2d/tuto_bis.cc --- sandbox/geraud/cs2d/tuto_bis.cc (revision 0) +++ sandbox/geraud/cs2d/tuto_bis.cc (revision 0) @@ -0,0 +1,277 @@ +# include <vector> + +# include <mln/core/image2d.hh> +# include <mln/core/sub_image.hh> +# include <mln/core/image_if.hh> +# include <mln/core/image_if_value.hh> + +# include <mln/core/neighb2d.hh> +# include <mln/core/window2d.hh> +# include <mln/convert/to_window.hh> + +# include <mln/debug/println.hh> +# include <mln/fun/p2v/iota.hh> +# include <mln/level/paste.hh> +# include <mln/level/fill.hh> + +# include <mln/morpho/dilation.hh> +# include <mln/morpho/gradient.hh> +# include <mln/morpho/meyer_wst.hh> + +# include <mln/level/transform.hh> +# include <mln/accu/mean.hh> + +# include "dbl_neighb.hh" + + +namespace mln +{ + + + 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 + + namespace accu + { + + 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 + +} // mln + + + 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; + + + +#define mln_alias(Var, Expr) \ +typeof(Expr) Var = Expr; + + + +int main() +{ + using namespace mln; + + window2d c4 = convert::to_window(mln::c4()); + + + dbl_neighb_<dpoint2d, is_row_odd_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(make::dpoint2d(0,0)) + .insert_false(make::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)); + } + + + image2d<int> ima(3, 5); + + mln_alias(cell, ima | is_cell); + level::fill(cell, fun::p2v::iota); + debug::println(cell); + // 1 2 3 + // + // 4 5 6 + + mln_alias(edge, ima | is_edge); + level::paste(morpho::gradient(edge, nbh_e2c), edge); + // ^^^^^^^ + // edge -> neighbooring cells + debug::println(edge); + // 1 1 + // 3 3 3 + // 1 1 + + unsigned nbasins; + mln_alias(wst, morpho::meyer_wst(edge, nbh_e2e, nbasins)); + // ^^^^^^^ + // edge -> neighbooring edges + debug::println(wst); + // 2 2 + // 0 0 0 + // 1 1 + + std::cout << nbasins << " bassins" << std::endl; + // 2 bassins + + + // '0' IS THE TAG VALUE FOR THE WATERSHED LINE + // THE OTHER VALUES ARE THE REGION LABELS + + + std::cout << "the watershed line = " << (wst | 0).domain() << std::endl; + // the watershed line = {(1,0)(1,2)(1,4)} + // ^^^^^ + // meaning (row = 1, col = 0) + + // Actually wst is: + // + // 0 1 2 3 4 <- col + // +-----------+ + // 0 | 2 2 | + // 1 | 0 0 0 | + // 2 | 1 1 | + // +-----------+ + // ^ + // | + // row + + + // YET THOSE VALUES ARE ON EDGES, NOT ON CELLS... + + + mln_alias(label, wst.full()); + debug::println(label); + // 0 2 0 2 0 + // 0 0 0 0 0 + // 0 1 0 1 0 + + level::paste(morpho::dilation(label | is_cell, c4), label); + + debug::println(label); + // 2 2 2 2 2 + // 0 0 0 0 0 + // 1 1 1 1 1 + debug::println(label | is_cell); + // 2 2 2 + // + // 1 1 1 + + + // ABOVE, WE HAVE THE LABEL IMAGE (POINTS-ONLY). + // BELOW, THE ORIGINAL IMAGE (POINTS-ONLY). + + + debug::println(cell); + // 1 2 3 + // + // 4 5 6 + + + // NOW WE WANT TO MODIFY THE INPUT IMAGE TO FLATTEN REGIONS... + + + std::vector<int> m(nbasins + 1); + accu::compute<accu::mean>(cell, label, m); + for (unsigned i = 1; i <= nbasins; ++i) + std::cout << "mean value of basin " << i << " is " << m[i] << std::endl; + + level::fill(cell, level::transform(label, m)); + debug::println(cell); + // 2 2 2 + // + // 5 5 5 + + // DONE! +}
participants (1)
-
Thierry Geraud