
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox Index: ChangeLog from Thierry Geraud <thierry.geraud@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