https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add some bench + canvas + subsampling + browsing code.
* bench: New directory.
* bench/input_iz.pgm.gz: New.
* bench/fastest_statistical_tour_browsing.cc: New.
* bench/fastest_forall_p_browsing.cc: New.
* bench/iz.cc: New.
* bench/fastest_statistical_tour_nbh_browsing.cc: New.
* bench/z_sub_browsing: New.
* bench/z_sub_browsing/fast.cc: New.
* bench/z_sub_browsing/debase.hh: New.
* bench/z_sub_browsing/integral.hh: New.
* bench/z_sub_browsing/+inc: New.
* bench/z_sub_browsing/in.pgm.gz: New.
* bench/z_sub_browsing/debase.cc: New.
* bench/z_sub_browsing/integral.cc: New.
* bench/z_sub_browsing/README: New.
* theo/mln/morpho/canvas/lena_blurred.pgm.gz: New.
* theo/mln/morpho/canvas/lena.pgm.gz: New.
* theo/mln/morpho/canvas/g.pbm.gz: New.
* theo/mln/morpho/canvas/lena_min.pgm.gz: New.
* theo/mln/morpho/canvas/reconstruction_on_set.hh: Layout.
* theo/mln/morpho/canvas/f_and_g.pbm.gz: New.
* theo/mln/morpho/canvas/regminid.pbm.gz: New.
* theo/mln/morpho/canvas/one_domain.cc: New.
* theo/mln/subsampling: New directory.
* theo/mln/subsampling/sizes.cc: New.
* theo/mln/subsampling/debase.hh: New.
* theo/mln/subsampling/integral.hh: New.
* theo/mln/subsampling/in.pgm.gz: New.
* theo/mln/subsampling/debase.cc: New.
* theo/mln/subsampling/integral.cc: New.
* theo/mln/browsing: New directory.
* theo/mln/browsing/window_sliding.cc: New.
bench/fastest_forall_p_browsing.cc | 384 ++++++++++++++++
bench/fastest_statistical_tour_browsing.cc | 168 +++++++
bench/fastest_statistical_tour_nbh_browsing.cc | 186 ++++++++
bench/iz.cc | 386 ++++++++++++++++
bench/z_sub_browsing/README | 5
bench/z_sub_browsing/debase.cc | 23 +
bench/z_sub_browsing/debase.hh | 351 +++++++++++++++
bench/z_sub_browsing/fast.cc | 139 ++++++
bench/z_sub_browsing/integral.cc | 23 +
bench/z_sub_browsing/integral.hh | 165 +++++++
theo/mln/browsing/window_sliding.cc | 52 ++
theo/mln/morpho/canvas/one_domain.cc | 569 +++++++++++++++++++++++++
theo/mln/subsampling/debase.cc | 23 +
theo/mln/subsampling/debase.hh | 351 +++++++++++++++
theo/mln/subsampling/integral.cc | 38 +
theo/mln/subsampling/integral.hh | 295 ++++++++++++
theo/mln/subsampling/sizes.cc | 45 +
17 files changed, 3203 insertions(+)
Index: bench/input_iz.pgm.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: bench/input_iz.pgm.gz
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: bench/fastest_statistical_tour_browsing.cc
--- bench/fastest_statistical_tour_browsing.cc (revision 0)
+++ bench/fastest_statistical_tour_browsing.cc (revision 0)
@@ -0,0 +1,168 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/pw/all.hh>
+#include <mln/data/compare.hh>
+#include <mln/debug/println.hh>
+#include <mln/util/timer.hh>
+
+
+
+# define loop(n) for (unsigned i = 0; i < n; ++i)
+
+
+
+namespace mln
+{
+
+
+ // test_
+
+ template <typename I>
+ void test_(const std::string& routine, float t, const I& ima, mln_value(I) n)
+ {
+ std::cout << routine << ' ' << t << std::endl;
+ if (ima != (pw::cst(n) | ima.domain()))
+ std::cerr << "bug in " << routine << '!'
<< std::endl;
+ }
+
+
+
+ // piter
+
+ template <typename I>
+ void piter_based(I& ima)
+ {
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ if ((p.row() + p.col()) % 2 == 0)
+ ++ima(p);
+ for_all(p)
+ if ((p.row() + p.col()) % 2 == 1)
+ ++ima(p);
+ }
+
+
+ // row_col
+
+ template <typename I>
+ void row_col_based(I& ima)
+ {
+ const unsigned nrows = ima.nrows(), ncols = ima.ncols();
+ for (int row = 0; row < nrows; ++row)
+ for (int col = row % 2; col < ncols; col += 2)
+ ++ima.at_(row, col);
+ for (int row = 0; row < nrows; ++row)
+ for (int col = ! (row % 2); col < ncols; col += 2)
+ ++ima.at_(row, col);
+ }
+
+
+ // run_ptr
+
+ template <typename I>
+ void run_ptr_based(I& ima)
+ {
+ mln_box_runstart_piter(I) s(ima.domain());
+ const unsigned n = s.run_length();
+
+ // half-tour 0
+ unsigned skip = 0;
+ for_all(s)
+ {
+ mln_value(I)* ptr = &ima(s) + skip;
+ for (unsigned i = 0; i < n; i += 2)
+ {
+ ++*ptr;
+ ptr += 2;
+ }
+ skip = ! skip;
+ }
+
+ // half-tour 1
+ skip = 1;
+ for_all(s)
+ {
+ mln_value(I)* ptr = &ima(s) + skip;
+ for (unsigned i = 0; i < n; i += 2)
+ {
+ ++*ptr;
+ ptr += 2;
+ }
+ skip = ! skip;
+ }
+ }
+
+
+} // end of namespace mln
+
+
+
+
+
+int main()
+{
+ using namespace mln;
+
+ const unsigned n = 10, size = 1000;
+ image2d<char> ima(size, size);
+ util::timer t;
+ std::string routine;
+
+
+ // piter
+
+ {
+ routine = "piter";
+ data::fill(ima, 0);
+ t.start();
+ loop(n) piter_based(ima);
+ test_(routine, t.stop(), ima, n);
+ }
+
+
+ // row_col
+
+ {
+ routine = "row_col";
+ data::fill(ima, 0);
+ t.start();
+ loop(n) row_col_based(ima);
+ test_(routine, t.stop(), ima, n);
+ }
+
+
+ // run_ptr
+
+ {
+ routine = "run_ptr";
+ data::fill(ima, 0);
+ t.start();
+ loop(n) run_ptr_based(ima);
+ test_(routine, t.stop(), ima, n);
+ }
+
+}
Index: bench/fastest_forall_p_browsing.cc
--- bench/fastest_forall_p_browsing.cc (revision 0)
+++ bench/fastest_forall_p_browsing.cc (revision 0)
@@ -0,0 +1,384 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/util/timer.hh>
+
+
+
+# define loop(n) for (unsigned i = 0; i < n; ++i)
+
+
+
+namespace mln
+{
+
+
+ // (r, c)
+
+ template <typename I>
+ void bench_00(I& ima)
+ {
+ const unsigned nr = ima.nrows(), nc = ima.ncols();
+ for (int r = 0; r < nr; ++r)
+ for (int c = 0; c < nc; ++c)
+ ima.at_(r, c) = 0;
+ }
+
+
+ // ptr
+
+ template <typename I>
+ void bench_0(I& ima)
+ {
+ const unsigned n = ima.nelements();
+ mln_value(I)* ptr = ima.buffer();
+ for (unsigned i = 0; i < n; ++i)
+ *ptr++ = 0;
+ }
+
+ template <typename I>
+ void bench_0(I& ima1, const I& ima2)
+ {
+ const unsigned n = ima1.nelements();
+ mln_value(I)* ptr1 = ima1.buffer();
+ const mln_value(I)* ptr2 = ima2.buffer();
+ for (unsigned i = 0; i < n; ++i)
+ *ptr1++ = *ptr2++;
+ }
+
+
+ // piter
+
+ template <typename I>
+ void bench_1(I& ima)
+ {
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ ima(p) = 0;
+ }
+
+
+ // pixter
+
+ template <typename I>
+ void bench_2(I& ima)
+ {
+ mln_fwd_pixter(I) pxl(ima);
+ for_all(pxl)
+ pxl.val() = 0;
+ }
+
+ template <typename I>
+ void bench_2(I& ima1, const I& ima2)
+ {
+ mln_fwd_pixter(I) pxl1(ima1);
+ mln_fwd_pixter(const I) pxl2(ima2);
+ for_all_2(pxl1, pxl2)
+ pxl1.val() = pxl2.val();
+ }
+
+
+ // pixter -> offset
+
+ template <typename I>
+ void bench_3(I& ima)
+ {
+ mln_fwd_pixter(I) pxl(ima);
+ for_all(pxl)
+ {
+ unsigned p = pxl.offset();
+ ima.element(p) = 0;
+ }
+ }
+
+ template <typename I>
+ void bench_3(I& ima1, const I& ima2)
+ {
+ // border::equalize(ima1, ima2);
+ mln_fwd_pixter(I) pxl(ima1);
+ for_all(pxl)
+ {
+ unsigned p = pxl.offset();
+ ima1.element(p) = ima2.element(p);
+ }
+ }
+
+
+ // pixter -> point
+
+ template <typename I>
+ void bench_4(I& ima)
+ {
+ mln_fwd_pixter(I) pxl(ima);
+ for_all(pxl)
+ {
+ unsigned o = pxl.offset();
+ mln_psite(I) p = ima.point_at_index(o);
+ ima(p) = 0;
+ }
+ }
+
+
+
+ // box_runstart_piter -> ptr
+
+ template <typename I>
+ void bench_5(I& ima)
+ {
+ mln_box_runstart_piter(I) s(ima.domain());
+ const unsigned n = s.run_length();
+ for_all(s)
+ {
+ mln_value(I)* ptr = & ima(s);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ *ptr++ = 0;
+ }
+ }
+ }
+
+
+ // box_runstart_piter -> (ptr, point)
+
+ template <typename I>
+ void bench_6(I& ima)
+ {
+ typedef mln_site(I) P;
+ const unsigned dim_1 = P::dim - 1;
+ mln_box_runstart_piter(I) s(ima.domain());
+ const unsigned n = s.run_length();
+ for_all(s)
+ {
+ mln_value(I)* ptr = & ima(s);
+ P p = s;
+ for (unsigned i = 0; i < n; ++i)
+ {
+ *ptr++ = 0;
+ ++p[dim_1];
+ }
+ }
+ }
+
+ template <typename I>
+ void bench_6(I& ima1, const I& ima2)
+ {
+ typedef mln_site(I) P;
+ const unsigned dim_1 = P::dim - 1;
+ mln_box_runstart_piter(I) s(ima1.domain());
+ const unsigned n = s.run_length();
+ for_all(s)
+ {
+ mln_value(I)* ptr1 = & ima1(s);
+ const mln_value(I)* ptr2 = & ima2(s);
+ P p = s;
+ for (unsigned i = 0; i < n; ++i)
+ {
+ *ptr1++ = *ptr2++;
+ ++p[dim_1];
+ }
+ }
+ }
+
+
+// template <typename I>
+// void bench_6_alt(I& ima1, const I& ima2)
+// {
+// typedef mln_site(I) P;
+// const unsigned dim_1 = P::dim - 1;
+// mln_fwd_by_run_piter(I) p(ima1.domain());
+// for_all(p)
+// {
+// if (p.at_runstart())
+// {
+// p.update(ptr1, ima1);
+// p.update(ptr2, ima2);
+// }
+// *ptr1++ = *ptr2++;
+// p; // converts to point2d
+// }
+// }
+
+
+
+ // box_runstart_piter -> (offset, point)
+
+ template <typename I>
+ void bench_7(I& ima)
+ {
+ typedef mln_site(I) P;
+ const unsigned dim_1 = P::dim - 1;
+ mln_box_runstart_piter(I) s(ima.domain());
+ const unsigned n = s.run_length();
+ for_all(s)
+ {
+ unsigned offset = ima.index_of_point(s);
+ P p = s;
+ for (unsigned i = 0; i < n; ++i)
+ {
+ ima.element(offset) = 0;
+ ++offset;
+ ++p[dim_1];
+ }
+ }
+ }
+
+
+
+} // end of namespace mln
+
+
+
+
+
+int main()
+{
+ using namespace mln;
+
+ const unsigned n = 100, size = 1000;
+ image2d<int> ima(size, size), ima2(size, size);
+ util::timer t;
+
+
+ // (r, c)
+
+ {
+ t.start();
+ loop(n) bench_00(ima);
+ float ts = t.stop();
+ std::cout << "(r, c) " << ts << std::endl;
+ }
+
+
+ // ptr
+
+ {
+ t.start();
+ loop(n) bench_0(ima);
+ float ts = t.stop();
+ std::cout << "ptr " << ts << std::endl;
+ }
+
+// {
+// t.start();
+// loop(n) bench_0(ima, ima2);
+// float ts = t.stop();
+// std::cout << "2 ptrs " << ts << std::endl;
+// }
+
+
+ // piter
+
+ {
+ t.start();
+ loop(n) bench_1(ima);
+ std::cout << "piter " << t.stop() << std::endl;
+ }
+
+
+ // pixter
+
+ {
+ t.start();
+ loop(n) bench_2(ima);
+ float ts = t.stop();
+ std::cout << "pixter " << ts << std::endl;
+ }
+
+// {
+// t.start();
+// loop(n) bench_2(ima, ima2);
+// float ts = t.stop();
+// std::cout << "2 pixters " << ts << std::endl;
+// }
+
+
+ // pixter -> offset
+
+ {
+ t.start();
+ loop(n) bench_3(ima);
+ std::cout << "pixter -> offset " << t.stop() <<
std::endl;
+ }
+
+// {
+// t.start();
+// loop(n) bench_3(ima, ima2);
+// std::cout << t.stop() << std::endl;
+// }
+
+
+ // pixter -> point
+
+ {
+ t.start();
+ loop(n) bench_4(ima);
+ std::cout << "pixter -> point " << t.stop() <<
std::endl;
+ }
+
+
+ // box_runstart_piter -> ptr
+
+ {
+ t.start();
+ loop(n) bench_5(ima);
+ std::cout << "box_runstart_piter -> ptr " << t.stop()
<< std::endl;
+ }
+
+
+ // box_runstart_piter -> (ptr, point)
+
+ {
+ t.start();
+ loop(n) bench_6(ima);
+ float ts = t.stop();
+ std::cout << "runstart -> (ptr, point) " << ts <<
std::endl;
+ }
+
+// {
+// t.start();
+// loop(n) bench_6(ima, ima2);
+// float ts = t.stop();
+// std::cout << "runstart -> (2 ptrs, point) " << ts
<< std::endl;
+// }
+
+
+ // box_runstart_piter -> (offset, point)
+
+ {
+ t.start();
+ loop(n) bench_7(ima);
+ float ts = t.stop();
+ std::cout << "runstart -> (offset, point) " << ts <<
std::endl;
+ }
+
+// {
+// t.start();
+// loop(n) bench_7(ima, ima2);
+// float ts = t.stop();
+// std::cout << "runstart -> (2 offsets, point) " << ts
<< std::endl;
+// }
+
+}
Index: bench/iz.cc
--- bench/iz.cc (revision 0)
+++ bench/iz.cc (revision 0)
@@ -0,0 +1,386 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#include <queue>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/data/fill.hh>
+#include <mln/extension/fill.hh>
+
+#include <mln/transform/influence_zone_geodesic.hh>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/util/timer.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
+
+
+# define loop(n) for (unsigned i = 0; i < n; ++i)
+
+
+
+namespace mln
+{
+
+
+ template <typename I, typename N>
+ mln_concrete(I) do_iz(const I& input, const N& nbh)
+ {
+ mln_ch_value(I, unsigned) dmap;
+ std::queue<unsigned> q;
+ mln_concrete(I) output;
+
+ // Initialization.
+ {
+ output = duplicate(input); // <-- init
+ extension::fill(output, 1); // For the extension to be ignored.
+
+ mln_pixter(const I) p(input);
+ mln_nixter(const I, N) n(p, nbh);
+ for_all(p)
+ if (p.val() != 0) // <-- inqueue_p_wrt_input_p
+ {
+ ; // <-- init_p
+ // FIXME: dmap.element(p.offset()) = 0;
+ for_all(n)
+ if (n.val() == 0) // <-- inqueue_p_wrt_input_n
+ {
+ q.push(p.offset());
+ break;
+ }
+ }
+ }
+
+ // Propagation.
+ {
+ unsigned p;
+
+ util::array<int> dp = offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+
+ while (! q.empty())
+ {
+ p = q.front();
+ q.pop();
+ // pas de saturation
+ if (output.element(p) == 0)
+ std::cerr << "oops!" << std::endl;
+ for (unsigned i = 0; i < n_nbhs; ++i)
+ {
+ unsigned n = p + dp[i];
+ if (output.element(n) == 0)
+ {
+ output.element(n) = output.element(p); // <- process
+ q.push(n);
+ }
+ }
+ }
+ }
+
+ return output;
+ }
+
+
+
+ template <typename I, typename N>
+ mln_concrete(I) do_iz__bis(const I& input, const N& nbh)
+ {
+ std::queue<unsigned> q;
+ mln_concrete(I) output;
+
+ util::array<int> dp = offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+
+ // Initialization.
+ {
+ output = duplicate(input); // <-- init
+ extension::fill(output, 1); // For the extension to be ignored.
+
+ mln_box_runstart_piter(I) s(input.domain());
+ const unsigned len = s.run_length();
+ for_all(s)
+ {
+ unsigned p = input.index_of_point(s);
+ for (unsigned i = 0; i < len; ++i, ++p)
+ if (input.element(p) != 0)
+ {
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+ if (input.element(n) == 0)
+ {
+ q.push(p);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Propagation.
+ {
+ unsigned p;
+
+ while (! q.empty())
+ {
+ p = q.front();
+ q.pop();
+ mln_invariant(output.element(p) != 0);
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+ if (output.element(n) == 0)
+ {
+ output.element(n) = output.element(p); // <- process
+ q.push(n);
+ }
+ }
+ }
+ }
+
+ return output;
+ }
+
+
+
+
+
+ template <typename I, typename N>
+ mln_concrete(I) do_iz__ter(const I& input, const N& nbh)
+ {
+ std::queue<unsigned> q;
+ mln_concrete(I) output;
+
+ util::array<int> dp = offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+ const unsigned
+ skip_border = 2 * input.border(),
+ nrows = input.nrows(),
+ ncols = input.ncols();
+
+ // Initialization.
+ {
+ output = duplicate(input); // <-- init
+ extension::fill(output, 1); // For the extension to be ignored.
+
+ unsigned p = input.index_of_point(point2d(0,0));
+ for (unsigned row = 0; row < nrows; ++row, p += skip_border)
+ {
+ for (unsigned i = 0; i < ncols; ++i, ++p)
+ if (input.element(p) != 0)
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+ if (input.element(n) == 0)
+ {
+ q.push(p);
+ break;
+ }
+ }
+ }
+ }
+
+ // Propagation.
+ {
+ unsigned p;
+
+ while (! q.empty())
+ {
+ p = q.front();
+ q.pop();
+ mln_invariant(output.element(p) != 0);
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+ if (output.element(n) == 0)
+ {
+ output.element(n) = output.element(p); // <- process
+ q.push(n);
+ }
+ }
+ }
+ }
+
+ return output;
+ }
+
+
+
+
+ template <typename I, typename N>
+ mln_concrete(I) do_iz__ptr(const I& input, const N& nbh)
+ {
+ std::queue<mln_value(I)*> q;
+ mln_concrete(I) output;
+
+ util::array<int> dp = offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+ const unsigned
+ skip_border = 2 * input.border(),
+ nrows = input.nrows(),
+ ncols = input.ncols();
+
+ // Initialization.
+ {
+ output = duplicate(input);
+ // For the extension to be ignored:
+ extension::fill(input, 0); // in initialization
+ extension::fill(output, 1); // in propagation
+
+ const unsigned nelts = input.nelements();
+ const mln_value(I)* p_i = & input.at_(0, 0);
+ mln_value(I)* p_o = & output.at_(0, 0);
+ for (unsigned i = 0; i < nelts; ++i, ++p_i, ++p_o)
+ {
+ if (*p_i == 0)
+ continue;
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ const mln_value(I)* n_i = p_i + dp[j];
+ if (*n_i == 0)
+ {
+ q.push(p_o);
+ break;
+ }
+ }
+ }
+
+ }
+
+ // Propagation.
+ {
+ mln_value(I)* ptr;
+
+ while (! q.empty())
+ {
+ ptr = q.front();
+ q.pop();
+ mln_invariant(*ptr != 0);
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ mln_value(I)* ntr = ptr + dp[j];
+ if (*ntr == 0)
+ {
+ *ntr = *ptr;
+ q.push(ntr);
+ }
+ }
+ }
+ }
+
+ return output;
+ }
+
+
+
+} // end of namespace mln
+
+
+
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ image2d<int_u8> in;
+ io::pgm::load(in, "input_iz.pgm");
+
+ util::timer t;
+ neighb2d nbh = c4();
+
+// {
+// t.start();
+// image2d<int_u8> ref = transform::influence_zone_geodesic(in, nbh,
mln_max(unsigned));
+// float ts = t.stop();
+// std::cout << ts << std::endl;
+// io::pgm::save(ref, "ref.pgm");
+// }
+
+// {
+// t.start();
+// image2d<int_u8> out = do_iz__bis(in, nbh);
+// float ts = t.stop();
+// std::cout << ts << std::endl;
+// io::pgm::save(out, "iz_bis.pgm");
+// }
+
+// {
+// t.start();
+// image2d<int_u8> out = do_iz__ter(in, nbh);
+// float ts = t.stop();
+// std::cout << ts << std::endl;
+// io::pgm::save(out, "iz_ter.pgm");
+// }
+
+// {
+// t.start();
+// image2d<int_u8> out = do_iz__ptr(in, nbh);
+// float ts = t.stop();
+// std::cout << ts << std::endl;
+// io::pgm::save(out, "iz_ptr.pgm");
+// }
+
+
+ const unsigned n_times = 10;
+
+ {
+ t.start();
+ loop(n_times) transform::influence_zone_geodesic(in, nbh, mln_max(unsigned));
+ float ts = t.stop();
+ std::cout << ts << std::endl;
+ }
+
+ {
+ t.start();
+ loop(n_times) do_iz(in, nbh);
+ float ts = t.stop();
+ std::cout << ts << std::endl;
+ }
+
+ {
+ t.start();
+ loop(n_times) do_iz__bis(in, nbh);
+ float ts = t.stop();
+ std::cout << ts << std::endl;
+ }
+
+ {
+ t.start();
+ loop(n_times) do_iz__ter(in, nbh);
+ float ts = t.stop();
+ std::cout << ts << std::endl;
+ }
+
+ {
+ t.start();
+ loop(n_times) do_iz__ptr(in, nbh);
+ float ts = t.stop();
+ std::cout << ts << std::endl;
+ }
+
+}
Index: bench/fastest_statistical_tour_nbh_browsing.cc
--- bench/fastest_statistical_tour_nbh_browsing.cc (revision 0)
+++ bench/fastest_statistical_tour_nbh_browsing.cc (revision 0)
@@ -0,0 +1,186 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/pw/all.hh>
+#include <mln/data/compare.hh>
+#include <mln/debug/println.hh>
+#include <mln/util/timer.hh>
+
+
+
+# define loop(n) for (unsigned i = 0; i < n; ++i)
+
+
+
+namespace mln
+{
+
+
+ // test_
+
+ template <typename I>
+ void test_(const std::string& routine, float t, const I& ima, unsigned n)
+ {
+ dpoint2d dp(1, 1);
+ box2d
+ b = ima.domain(),
+ inner(b.pmin() + dp, b.pmax() - dp);
+ std::cout << routine << ' ' << t << std::endl;
+ if ((ima | inner) != (pw::cst(4 * n) | inner))
+ std::cerr << "bug in " << routine << '!'
<< std::endl;
+ // FIXME: other tests...
+ }
+
+
+
+ // piter
+
+ template <typename I, typename N>
+ void piter_based(I& ima, const N& nbh)
+ {
+ mln_piter(I) p(ima.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if ((p.row() + p.col()) % 2 == 0)
+ for_all(n)
+ ++ima(n);
+ for_all(p)
+ if ((p.row() + p.col()) % 2 == 1)
+ for_all(n)
+ ++ima(n);
+ }
+
+
+ // row_col
+
+ template <typename I, typename N>
+ void row_col_based(I& ima, const N& nbh)
+ {
+ const unsigned nrows = ima.nrows(), ncols = ima.ncols();
+ unsigned n_nbhs = nbh.size();
+ for (int row = 0; row < nrows; ++row)
+ for (int col = row % 2; col < ncols; col += 2)
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ ++ima.at_(row + nbh.dp(j).row(), col + nbh.dp(j).col());
+ for (int row = 0; row < nrows; ++row)
+ for (int col = ! (row % 2); col < ncols; col += 2)
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ ++ima.at_(row + nbh.dp(j).row(), col + nbh.dp(j).col());
+ }
+
+
+ // run_ptr
+
+ template <typename I, typename N>
+ void run_ptr_based(I& ima, const N& nbh)
+ {
+ mln_box_runstart_piter(I) s(ima.domain());
+ const unsigned n = s.run_length();
+
+ util::array<int> dp = offsets_wrt(ima, nbh);
+ const unsigned n_nbhs = dp.nelements();
+
+ // half-tour 0
+ unsigned skip = 0;
+ for_all(s)
+ {
+ mln_value(I)* ptr = &ima(s) + skip;
+ for (unsigned i = 0; i < n; i += 2)
+ {
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ ++*(ptr + dp(j));
+ ptr += 2;
+ }
+ skip = ! skip;
+ }
+
+ // half-tour 1
+ skip = 1;
+ for_all(s)
+ {
+ mln_value(I)* ptr = &ima(s) + skip;
+ for (unsigned i = 0; i < n; i += 2)
+ {
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ ++*(ptr + dp(j));
+ ptr += 2;
+ }
+ skip = ! skip;
+ }
+ }
+
+
+} // end of namespace mln
+
+
+
+
+
+int main()
+{
+ using namespace mln;
+
+ const unsigned n = 10, size = 1000;
+ image2d<char> ima(size, size);
+ neighb2d nbh = c4();
+ util::timer t;
+ std::string routine;
+
+
+ // piter
+
+ {
+ routine = "piter";
+ data::fill(ima, 0);
+ t.start();
+ loop(n) piter_based(ima, nbh);
+ test_(routine, t.stop(), ima, n);
+ }
+
+
+ // row_col
+
+ {
+ routine = "row_col";
+ data::fill(ima, 0);
+ t.start();
+ loop(n) row_col_based(ima, nbh);
+ test_(routine, t.stop(), ima, n);
+ }
+
+
+ // run_ptr
+
+ {
+ routine = "run_ptr";
+ data::fill(ima, 0);
+ t.start();
+ loop(n) run_ptr_based(ima, nbh);
+ test_(routine, t.stop(), ima, n);
+ }
+
+}
Index: bench/z_sub_browsing/fast.cc
--- bench/z_sub_browsing/fast.cc (revision 0)
+++ bench/z_sub_browsing/fast.cc (revision 0)
@@ -0,0 +1,139 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/util/array.hh>
+#include <mln/util/timer.hh>
+#include <mln/data/fill.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
+
+namespace mln
+{
+
+// template <typename I>
+// void
+// test1(const I& input, I& out)
+// {
+// unsigned s = 2;
+// util::timer timer_;
+// timer_.start();
+
+// mln_box_runstart_piter(I) sp(out.domain());
+
+// const unsigned n = sp.run_length();
+
+// unsigned row_offset = input.domain().ncols()
+// + 2 * input.border();
+
+// util::array< mln_value(I)*> ptr(s);
+// util::array<const mln_value(I)*> ptr_input(s);
+
+// sp.start();
+// while (sp.is_valid())
+// {
+// mln_site(I)
+// site = sp; // Site at scale 1.
+
+// unsigned nptr = 0;
+// for (; sp.is_valid() && nptr < ptr.size(); ++nptr)
+// {
+// ptr(nptr) = & out(sp);
+// ptr_input(nptr) = & input(sp);
+// sp.next();
+// }
+// ptr.resize(nptr);
+
+// for (unsigned col = 0; col < n; col += s, site[1] += s)
+// {
+// for (unsigned i = 0; i < ptr.size() ; ++i)
+// for (unsigned j = 0; j < s; ++j)
+// *ptr(i)++ = *ptr_input(i)++;
+// }
+// }
+
+// float t_ = timer_;
+// std::cout << "Test 1 - " << t_ << std::endl;
+// }
+
+
+ template <typename I>
+ void
+ test2(const I& input, I& out, unsigned s)
+ {
+ const unsigned s_2 = s * s, round_it = s_2 / 2;
+ util::timer timer_;
+ timer_.start();
+
+ typedef mln_value(I) V;
+ typedef mln_sum(V) S;
+
+ mln_box_runstart_piter(I) sp(input.domain());
+
+ const unsigned n = sp.run_length();
+
+ int row_offset = input.domain().ncols() + 2 * input.border();
+ int row_offset_s = row_offset - s;
+ int row_offset_next = - (s - 1) * row_offset;
+
+ mln_value(I)* ptr = out.buffer();
+ const mln_value(I)* ptr_input;
+
+ sp.start();
+ while (sp.is_valid())
+ {
+ mln_site(I)
+ site = sp; // Site at scale 1.
+
+ ptr_input = & input(sp);
+
+ for (unsigned col = 0; col < n; col += s, site[1] += s)
+ {
+
+ // tile
+ S sum = 0;
+ for (unsigned i = 0; i < s;)
+ {
+ for (unsigned j = 0; j < s; ++j)
+ sum += *ptr_input++;
+
+ ++i;
+ if (i < s)
+ ptr_input += row_offset_s;
+ }
+
+ ptr_input += row_offset_next;
+ *ptr++ = sum / s_2;
+ }
+
+ for (unsigned i = 0; i < s; ++i)
+ sp.next();
+ }
+
+ float t_ = timer_;
+ std::cout << t_ << std::endl;
+ }
+
+
+
+} // end of namespace mln
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ def::coord
+ r = 3144,
+ c = 2252;
+
+ image2d<int_u8> input;
+ io::pgm::load(input, "in.pgm");
+
+ unsigned s = 3;
+ box2d b = make::box2d((input.nrows() + s - 1) / s,
+ (input.ncols() + s - 1) / s);
+ image2d<int_u8> output(b, 0);
+ test2(input, output, s);
+
+ io::pgm::save(output, "out.pgm");
+
+}
Index: bench/z_sub_browsing/debase.hh
--- bench/z_sub_browsing/debase.hh (revision 0)
+++ bench/z_sub_browsing/debase.hh (revision 0)
@@ -0,0 +1,351 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_SUBSAMPLING_DEBASE_HH
+# define MLN_SUBSAMPLING_DEBASE_HH
+
+/// \file
+///
+/// Debase subsampling.
+
+#include <mln/core/concept/image.hh>
+
+#define MLN_FLOAT double
+#include <sandbox/theo/exec/gaussian_directional_2d.hh>
+
+
+
+namespace mln
+{
+
+ namespace subsampling
+ {
+
+ /// FIXME: Doc.
+
+ template <typename I>
+ mln_concrete(I)
+ debase(const Image<I>& input,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift); // FIXME: Add round_up_size.
+
+
+ template <typename I>
+ mln_concrete(I)
+ debase(const Image<I>& input, unsigned gap);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ // Implementation.
+
+ namespace impl
+ {
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase");
+
+ const I& input = exact(input_);
+
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+
+ box<P> b(pmin, pmax);
+ mln_concrete(I) output(b);
+ mln_piter(I) p(output.domain());
+ for_all(p)
+ output(p) = input(p * gap + shift);
+
+ trace::exiting("subsampling::impl::debase");
+ return output;
+ }
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_fastest(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase_fastest");
+
+ const I& input = exact(input_);
+
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+
+ box<P> b(pmin, pmax);
+
+ typedef mln_concrete(I) O;
+ O output(b);
+
+ mln_box_runstart_piter(O) s(output.domain());
+ const unsigned n = s.run_length();
+ for_all(s)
+ {
+ const mln_value(I)* pi = & input(s * gap + shift);
+ mln_value(O)* po = & output(s);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ *po++ = *pi;
+ pi += gap;
+ }
+ }
+
+ trace::exiting("subsampling::impl::debase_fastest");
+ return output;
+ }
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_gaussian_antialiased_fastest(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase_gaussian_antialiased_fastest");
+
+ const I& input = exact(input_);
+
+ image2d<MLN_FLOAT> temp(input.domain());
+ data::fill(temp, input);
+ temp = linear::gaussian_directional_2d(temp, 1, 1.5, 0);
+ temp = linear::gaussian_directional_2d(temp, 0, 1.5, 0);
+
+ typedef mln_value(I) V;
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+
+ box<P> b(pmin, pmax);
+
+ typedef mln_concrete(I) O;
+ O output(b);
+
+ mln_box_runstart_piter(O) s(output.domain());
+ const unsigned n = s.run_length();
+ for_all(s)
+ {
+ const MLN_FLOAT* pi = & temp(s * gap + shift);
+ mln_value(O)* po = & output(s);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ *po++ = V(*pi + 0.49);
+ pi += gap;
+ }
+ }
+
+ trace::entering("subsampling::impl::debase_gaussian_antialiased_fastest");
+ return output;
+ }
+
+
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_2d_antialias_pointer_fastest(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase_2d_antialias_pointer_fastest");
+
+ const I& input = exact(input_);
+
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+
+ box<P> b(pmin, pmax);
+
+ typedef mln_concrete(I) O;
+ O output(b);
+
+ const unsigned nrows = input.nrows();
+ const unsigned ncols = input.ncols();
+
+ typedef mln_value(I) V;
+ typedef mln_sum(V) S;
+ for (unsigned row = 0; row < nrows; row += gap)
+ {
+ const V* ptr1 = & input.at_(row, 0);
+ const V* ptr2 = & input.at_(row + 1, 0);
+ const V* ptr3 = & input.at_(row + 2, 0);
+ for (unsigned col = 0; col < ncols; col += gap)
+ {
+ S s;
+
+ // mean
+ s = *ptr1++ + *ptr1++ + *ptr1++;
+ s += *ptr2++ + *ptr2++ + *ptr2++;
+ s += *ptr3++ + *ptr3++ + *ptr3++;
+ output.at_(row / gap, col / gap) = (s + 4) / 9;
+// // cut
+// s = 1 * *ptr1++ + 2 * *ptr1++ + 1 * *ptr1++;
+// s += 2 * *ptr2++ + 3 * *ptr2++ + 2 * *ptr2++;
+// s += 1 * *ptr3++ + 2 * *ptr3++ + 1 * *ptr3++;
+// output.at_(row / gap, col / gap) = (s + 7) / 15;
+ }
+ }
+
+ trace::exiting("subsampling::impl::debase_2d_antialias_pointer_fastest");
+ return output;
+ }
+
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_2d_antialias_offset_fastest(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase_2d_antialias_offset_fastest");
+
+ const I& input = exact(input_);
+
+ typedef mln_value(I) V;
+ typedef mln_sum(V) S;
+
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+ box<P> b(pmin, pmax);
+ typedef mln_concrete(I) O;
+ O output(b);
+
+ const V* ptr1 = & input.at_(0, 0);
+ const V* ptr2 = & input.at_(1, 0);
+ const V* ptr3 = & input.at_(2, 0);
+
+ mln_box_runstart_piter(O) s(output.domain());
+ const unsigned n = s.run_length();
+
+ unsigned offset = input.delta_index(point2d(3,0) - point2d(0,3*n));
+
+ for_all(s)
+ {
+ mln_value(O)* po = & output(s);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ S s;
+ s = *ptr1++ + *ptr1++ + *ptr1++;
+ s += *ptr2++ + *ptr2++ + *ptr2++;
+ s += *ptr3++ + *ptr3++ + *ptr3++;
+ *po++ = (s + 4) / 9;
+ }
+ ptr1 += offset;
+ ptr2 += offset;
+ ptr3 += offset;
+ }
+
+ trace::exiting("subsampling::impl::debase_2d_antialias_offset_fastest");
+ return output;
+ }
+
+
+ } // end of namespace mln::subsampling::impl
+
+
+
+ // Dispatch.
+
+ namespace internal
+ {
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_dispatch(const Image<I>& input,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ return impl::debase_2d_antialias_pointer_fastest /* debase_2d_antialias_offset_fastest
*/(input, gap, shift);
+ }
+
+
+ } // end of namespace mln::subsampling::internal
+
+
+
+ // Facades.
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase(const Image<I>& input,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::debase");
+
+ typedef mln_site(I) P;
+
+ mln_precondition(exact(input).is_valid());
+ mln_precondition(exact(input).domain().pmin() == literal::origin);
+ mln_precondition(gap > 1);
+ for (unsigned i = 0; i < P::dim; ++i)
+ mln_precondition(shift[i] < gap);
+
+ mln_concrete(I) output;
+ output = internal::debase_dispatch(input, gap, shift);
+
+ trace::exiting("subsampling::debase");
+ return output;
+ }
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase(const Image<I>& input, unsigned gap)
+ {
+ return debase(input, gap, literal::zero);
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::subsampling
+
+} // end of namespace mln
+
+
+#endif // ! MLN_SUBSAMPLING_DEBASE_HH
Index: bench/z_sub_browsing/integral.hh
--- bench/z_sub_browsing/integral.hh (revision 0)
+++ bench/z_sub_browsing/integral.hh (revision 0)
@@ -0,0 +1,165 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_SUBSAMPLING_INTEGRAL_HH
+# define MLN_SUBSAMPLING_INTEGRAL_HH
+
+/// \file
+///
+/// Both subsampling and integral image computation.
+
+#include <mln/core/concept/image.hh>
+
+
+
+namespace mln
+{
+
+ namespace subsampling
+ {
+
+ /// FIXME: Doc.
+
+ template <typename I>
+ mln_concrete(I)
+ integral(const Image<I>& input, unsigned scale);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ // Implementation.
+
+ namespace impl
+ {
+
+
+ template <unsigned scale, typename I>
+ inline
+ mln_concrete(I)
+ integral_(const Image<I>& input_)
+ {
+ trace::entering("subsampling::impl::integral_");
+
+ const I& input = exact(input_);
+ const unsigned scale2 = scale * scale, round_it = scale2 / 2;
+
+ typedef mln_value(I) V;
+ typedef mln_sum(V) S;
+ typedef mln_site(I) P;
+
+ box<P> b = make::box2d(input.nrows() / scale, input.ncols() / scale);
+ const unsigned nrows = b.nrows(), ncols = b.ncols();
+
+ typedef mln_concrete(I) O;
+ O output(b, 0); // no external border in 'output'
+ V* po = output.buffer();
+
+ unsigned
+ tile_cr = input.delta_index(dpoint2d(scale, - ncols * scale)),
+ cr = input.delta_index(dpoint2d(1, - (int)scale));
+
+ const V* pi = & input.at_(0, 0); // first point of tiles
+ for (unsigned row = 0; row < nrows; ++row)
+ {
+ S hsum = 0, hsum2 = 0; // horizontal integral
+ for (unsigned col = 0; col < ncols; ++col)
+ {
+ S sum = 0, sum2 = 0;
+ const V* ptr = pi;
+
+ for (unsigned r = 0; r < scale; ++r)
+ {
+ for (unsigned c = 0; c < scale; ++c)
+ {
+ sum += *ptr;
+ // sum2 += *ptr * *ptr;
+ ++ptr;
+ }
+ ptr += cr;
+ }
+
+ // ...
+ pi += scale;
+ *po++ = (round_it + sum) / scale2;
+ }
+ pi += tile_cr;
+ }
+
+ trace::exiting("subsampling::impl::integral_");
+ return output;
+ }
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ integral(const Image<I>& input, unsigned scale)
+ {
+ // mln_precondition(input.nrows() % scale == 0);
+ // mln_precondition(input.ncols() % scale == 0);
+ if (scale == 3)
+ return integral_<3>(input);
+ else
+ std::cerr << "NYI!" << std::endl;
+ }
+
+ } // end of namespace mln::subsampling::impl
+
+
+
+
+ // Facades.
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ integral(const Image<I>& input_, unsigned scale)
+ {
+ trace::entering("subsampling::integral");
+
+ const I& input = exact(input_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(input.domain().pmin() == literal::origin);
+ mln_precondition(scale > 1);
+
+ mln_concrete(I) output;
+ output = impl::integral(input, scale);
+
+ trace::exiting("subsampling::integral");
+ return output;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::subsampling
+
+} // end of namespace mln
+
+
+#endif // ! MLN_SUBSAMPLING_INTEGRAL_HH
Index: bench/z_sub_browsing/in.pgm.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: bench/z_sub_browsing/in.pgm.gz
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: bench/z_sub_browsing/debase.cc
--- bench/z_sub_browsing/debase.cc (revision 0)
+++ bench/z_sub_browsing/debase.cc (revision 0)
@@ -0,0 +1,23 @@
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/util/timer.hh>
+
+#include "debase.hh"
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ image2d<int_u8> in;
+ io::pgm::load(in, "in.pgm");
+
+ util::timer t;
+ t.start();
+ image2d<int_u8> out = subsampling::debase(in, 3, dpoint2d(1,1));
+ float t_ = t.stop();
+ std::cout << t_ << std::endl;
+
+ io::pgm::save(out, "out.pgm");
+}
Index: bench/z_sub_browsing/integral.cc
--- bench/z_sub_browsing/integral.cc (revision 0)
+++ bench/z_sub_browsing/integral.cc (revision 0)
@@ -0,0 +1,23 @@
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/util/timer.hh>
+
+#include "integral.hh"
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ image2d<int_u8> in;
+ io::pgm::load(in, "in.pgm");
+
+ util::timer t;
+ t.start();
+ image2d<int_u8> out = subsampling::integral(in, 3);
+ float t_ = t.stop();
+ std::cout << t_ << std::endl;
+
+ io::pgm::save(out, "out.pgm");
+}
Index: bench/z_sub_browsing/README
--- bench/z_sub_browsing/README (revision 0)
+++ bench/z_sub_browsing/README (revision 0)
@@ -0,0 +1,5 @@
+debase en 03 DNDEBUG: 0.08
+integral: 0.16
+fast: ???
+
+les 3 codes font une moyenne de tiles pour le sub-sampling
Index: theo/mln/morpho/canvas/lena_blurred.pgm.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: theo/mln/morpho/canvas/lena_blurred.pgm.gz
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: theo/mln/morpho/canvas/lena.pgm.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: theo/mln/morpho/canvas/lena.pgm.gz
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: theo/mln/morpho/canvas/g.pbm.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: theo/mln/morpho/canvas/g.pbm.gz
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: theo/mln/morpho/canvas/lena_min.pgm.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: theo/mln/morpho/canvas/lena_min.pgm.gz
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: theo/mln/morpho/canvas/reconstruction_on_set.hh
Index: theo/mln/morpho/canvas/f_and_g.pbm.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: theo/mln/morpho/canvas/f_and_g.pbm.gz
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: theo/mln/morpho/canvas/regminid.pbm.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: theo/mln/morpho/canvas/regminid.pbm.gz
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: theo/mln/morpho/canvas/one_domain.cc
--- theo/mln/morpho/canvas/one_domain.cc (revision 0)
+++ theo/mln/morpho/canvas/one_domain.cc (revision 0)
@@ -0,0 +1,569 @@
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/morpho/canvas/internal/find_root.hh>
+
+# include <mln/data/fill.hh>
+# include <mln/data/sort_psites.hh>
+# include <mln/border/equalize.hh>
+# include <mln/border/fill.hh>
+
+
+// cc
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/debug/println.hh>
+#include <mln/io/pbm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pbm/save.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/data/compare.hh>
+#include <mln/util/timer.hh>
+
+#include <mln/labeling/regional_maxima.hh>
+#include <mln/labeling/regional_minima.hh>
+#include <mln/pw/all.hh>
+
+
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ namespace canvas
+ {
+
+
+ template <typename I, typename N, typename F>
+ inline
+ mln_result(F)
+ one_domain_union_find(const Image<I>& f_, const
Neighborhood<N>& nbh_,
+ F& functor)
+ {
+ trace::entering("morpho::canvas::one_domain_union_find");
+
+ const I& f = exact(f_);
+ const N& nbh = exact(nbh_);
+
+ typedef typename F::S S;
+ typedef mln_psite(I) P;
+ typedef mln_value(I) V;
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, P) parent;
+ mln_result(F) output;
+
+ // Initialization.
+ {
+ initialize(output, f);
+ functor.output = output;
+
+ initialize(parent, f);
+ initialize(deja_vu, f);
+ data::fill(deja_vu, false);
+
+ functor.set_default(); // <-- set_default
+ }
+
+ // First pass.
+ {
+ mln_bkd_piter(S) p(functor.s());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ if (functor.domain(p)) // <-- domain
+ {
+ // Make-Set.
+ parent(p) = p;
+ functor.init(p); // <-- init
+
+ for_all(n) if (f.domain().has(n))
+ {
+ // See below (*)
+ if (functor.domain(n)) // <-- domain
+ {
+ if (deja_vu(n))
+ {
+ if (functor.equiv(p, n)) // <-- equiv
+ {
+ // Do-Union.
+ P r = internal::find_root(parent, n);
+ if (r != p)
+ {
+// if (do_merge(p, r))
+ {
+ parent(r) = p;
+ functor.merge(p, r); // <-- merge
+ }
+// else
+// no_merge(p, r);
+ }
+ }
+ else
+ functor.do_no_union(p, n); // <-- do_no_union
+ }
+ }
+ else
+ {
+ mln_invariant(deja_vu(n) == false);
+ functor.border(p, n); // <-- border
+ }
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ // Second pass.
+ {
+ mln_fwd_piter(S) p(functor.s());
+ for_all(p)
+ if (functor.domain(p)) // <-- domain
+ if (parent(p) == p)
+ functor.root(p); // <-- root
+ else
+ output(p) = output(parent(p));
+ }
+
+ trace::exiting("morpho::canvas::one_domain_union_find");
+ return output;
+ }
+
+ } // end of namespace mln::morpho::canvas
+
+ } // end of namespace mln::morpho
+
+
+
+ // base functor
+
+ struct functor_base
+ {
+ void set_default()
+ {
+ }
+ template <typename P>
+ void init(const P&)
+ {
+ }
+ template <typename P>
+ void root(const P&)
+ {
+ }
+ template <typename P>
+ bool domain(const P&)
+ {
+ return true;
+ }
+ template <typename P1, typename P2>
+ void do_no_union(const P1&, const P2&)
+ {
+ }
+ template <typename P1, typename P2>
+ void border(const P1&, const P2&)
+ {
+ }
+ template <typename P1, typename P2>
+ bool equiv(const P1&, const P2&)
+ {
+ return true;
+ }
+ template <typename P1, typename P2>
+ void merge(const P1&, const P2&)
+ {
+ }
+ // no default for:
+ // typedef S
+ // .s()
+ };
+
+
+ // "binary reconstruction by dilation" functor
+
+ template <typename F, typename G>
+ struct rd_functor : functor_base
+ {
+ typedef mln_concrete(F) result;
+
+ const F& f;
+ const G& g;
+
+ typedef mln_domain(F) S;
+
+ rd_functor(const F& f, const G& g)
+ : f(f), g(g)
+ {
+ }
+
+ result output;
+ typedef mln_psite(F) P;
+
+ void set_default()
+ {
+ mln::data::fill(output, false);
+ }
+
+ bool domain(const P& p) const
+ {
+ return g(p) == true;
+ }
+
+ void init(const P& p)
+ {
+ output(p) = f(p);
+ }
+
+ void merge(const P& p, const P& r)
+ {
+ output(p) = output(p) || output(r);
+ }
+
+ S s() const
+ {
+ return f.domain();
+ }
+
+ };
+
+
+ // "labeling" functor
+
+ template <typename I, typename L>
+ struct lab_functor : functor_base
+ {
+ typedef mln_ch_value(I, L) result;
+
+ const I& input;
+ mln_value(I) val;
+
+ L nlabels;
+ bool status;
+
+ lab_functor(const I& input, const mln_value(I)& val)
+ : input(input), val(val)
+ {
+ }
+
+ result output;
+ typedef mln_psite(I) P;
+
+ typedef mln_domain(I) S;
+
+ S s() const
+ {
+ return input.domain();
+ }
+
+ void set_default()
+ {
+ data::fill(output, L(literal::zero));
+ nlabels = 0;
+ status = true;
+ }
+
+ bool domain(const P& p) const
+ {
+ return input(p) == val;
+ }
+
+ bool equiv(const P& p, const P& n)
+ {
+ return input(n) == val;
+ }
+
+ void root(const P& p)
+ {
+ if (status == false)
+ return;
+
+ if (nlabels == mln_max(L))
+ {
+ status = false;
+ trace::warning("labeling aborted!");
+ }
+ else
+ output(p) = ++nlabels;
+ }
+
+ };
+
+
+ // "regional maxima labeling" functor
+
+ template <typename I, typename L>
+ struct regmaxlab_functor : functor_base
+ {
+ typedef mln_ch_value(I, L) result;
+
+ const I& input;
+
+ L nlabels;
+ bool status;
+ mln_ch_value(I, bool) attr;
+
+ typedef mln_psite(I) P;
+ typedef p_array<P> S;
+ S s_;
+
+ result output;
+
+ regmaxlab_functor(const I& input)
+ : input(input)
+ {
+ s_ = data::sort_psites_increasing(input);
+ }
+
+ const S& s() const
+ {
+ return s_;
+ }
+
+ void set_default()
+ {
+ initialize(attr, input);
+ data::fill(attr, true);
+ data::fill(output, L(literal::zero));
+ nlabels = 0;
+ status = true;
+ }
+
+ bool equiv(const P& p, const P& n)
+ {
+ return input(n) == input(p);
+ }
+
+ void merge(const P& p, const P& r)
+ {
+ attr(p) = attr(p) && attr(r);
+ }
+
+ void do_no_union(const P& p, const P& n)
+ {
+ mln_invariant(input(n) > input(p));
+ attr(p) = false;
+ (void)n;
+ }
+
+ void root(const P& p)
+ {
+ if (attr(p) == false || status == false)
+ return;
+
+ if (nlabels == mln_max(L))
+ {
+ status = false;
+ trace::warning("labeling aborted!");
+ }
+ else
+ output(p) = ++nlabels;
+ }
+
+ };
+
+
+ // "regional minima identification" functor
+
+ template <typename I>
+ struct regminid_functor : functor_base
+ {
+ typedef mln_ch_value(I, bool) result;
+
+ const I& input;
+
+ typedef mln_psite(I) P;
+ typedef p_array<P> S;
+ S s_;
+
+ result output;
+
+ regminid_functor(const I& input)
+ : input(input)
+ {
+ s_ = data::sort_psites_decreasing(input);
+ }
+
+ const S& s() const
+ {
+ return s_;
+ }
+
+ void init(const P& p)
+ {
+ output(p) = true;
+ }
+
+ bool equiv(const P& p, const P& n)
+ {
+ return input(n) == input(p);
+ }
+
+ void merge(const P& p, const P& r)
+ {
+ output(p) = output(p) && output(r);
+ }
+
+ void do_no_union(const P& p, const P& n)
+ {
+ if (input(n) < input(p))
+ output(p) = false;
+ }
+
+ };
+
+
+
+ // "reconstruction by dilation on function" functor
+
+ template <typename F, typename G>
+ struct rdf_functor : functor_base
+ {
+ typedef mln_concrete(F) result;
+
+ const F& f;
+ const G& g;
+
+ typedef mln_value(F) V;
+ typedef mln_psite(F) P;
+ typedef p_array<P> S;
+ S s_;
+
+ result output;
+
+ rdf_functor(const F& f, const G& g)
+ : f(f), g(g)
+ {
+ s_ = data::sort_psites_decreasing(g);
+ }
+
+ const S& s() const
+ {
+ return f.domain();
+ }
+
+ void set_default()
+ {
+ mln::data::fill(output, f);
+ }
+
+ bool equiv(const P& p, const P& n)
+ {
+ return g(r) == g(p) || g(p) >= output(r);
+ }
+
+ void merge(const P& p, const P& r)
+ {
+ if (output(r) > output(p))
+ output(p) = output(r);
+ }
+
+ void do_no_union(const P& p, const P& n)
+ {
+ output(p) = mln_max(V);
+ }
+
+ void root(const P& p)
+ {
+ if (output(p) == mln_max(V))
+ output(p) = g(p);
+ }
+
+ };
+
+
+
+} // end of namespace mln
+
+
+
+int main()
+{
+ using namespace mln;
+
+ typedef value::int_u8 L;
+ neighb2d nbh = c4();
+
+ util::timer t;
+
+
+ // On sets.
+
+// {
+// typedef image2d<bool> I;
+
+// I f, g, ref;
+
+// io::pbm::load(f, "f_and_g.pbm");
+// io::pbm::load(g, "g.pbm");
+
+// {
+// t.start();
+// rd_functor<I,I> fun(f, g);
+// I rd = morpho::canvas::one_domain_union_find(f, nbh, fun);
+// std::cout << "rd: " << t.stop() << std::endl;
+// io::pbm::save(rd, "rd.pbm");
+// }
+
+// {
+// t.start();
+// lab_functor<I,L> fun(f, true);
+// image2d<L> lab = morpho::canvas::one_domain_union_find(f, nbh, fun);
+// std::cout << "lab: " << t.stop() << std::endl;
+// io::pgm::save(lab, "lab.pgm");
+// }
+// }
+
+
+ // On functions.
+
+ {
+ typedef image2d<value::int_u8> I;
+ I f;
+ io::pgm::load(f, "./lena_blurred.pgm");
+
+// {
+// // regional maxima labeling
+// t.start();
+// regmaxlab_functor<I,L> fun(f);
+// image2d<L> lab = morpho::canvas::one_domain_union_find(f, nbh, fun);
+// std::cout << "regmax lab: " << t.stop() <<
std::endl;
+// io::pgm::save(lab, "regmaxlab.pgm");
+
+// L nlabels_ref;
+// if (lab != labeling::regional_maxima(f, nbh, nlabels_ref)
+// || fun.nlabels != nlabels_ref)
+// std::cerr << "oops" << std::endl;
+// }
+
+// {
+// // regional minima identification
+// t.start();
+// regminid_functor<I> fun(f);
+// image2d<bool> id = morpho::canvas::one_domain_union_find(f, nbh, fun);
+// std::cout << "regmin id: " << t.stop() <<
std::endl;
+// io::pbm::save(id, "regminid.pbm");
+
+// L forget_it;
+// if (id != ((pw::value(labeling::regional_minima(f, nbh, forget_it)) !=
pw::cst(0)) | id.domain()))
+// std::cerr << "oops" << std::endl;
+// }
+
+ {
+ // reconstruction by dilation
+ I f, g;
+ io::pgm::load(f, "lena.pgm");
+ io::pgm::load(g, "lena_min.pgm");
+ if (! (f <= g))
+ std::cerr << "OK" << std::endl;
+
+ rdf_functor<I,I> fun(f, g);
+ I rdf = morpho::canvas::one_domain_union_find(f, nbh, fun);
+ std::cout << "rdf: " << t.stop() << std::endl;
+ io::pgm::save(rdf, "rdf.pbm");
+
+ }
+
+ }
+
+}
Index: theo/mln/subsampling/sizes.cc
--- theo/mln/subsampling/sizes.cc (revision 0)
+++ theo/mln/subsampling/sizes.cc (revision 0)
@@ -0,0 +1,45 @@
+#include <iostream>
+#include <cstdlib>
+
+
+void usage(const char* argv[])
+{
+ std::cerr << argv[0] << " n_scales s q nr nc" <<
std::endl;
+ std::abort();
+}
+
+
+unsigned sub(unsigned nbr, unsigned down_scaling)
+{
+ return (nbr + down_scaling - 1) / down_scaling;
+}
+
+
+int main(int argc, const char* argv[])
+{
+ unsigned n_scales = std::atoi(argv[1]);
+ unsigned s = std::atoi(argv[2]);
+ unsigned q = std::atoi(argv[3]);
+
+ unsigned nr_1 = std::atoi(argv[4]);
+ unsigned nc_1 = std::atoi(argv[5]);
+
+ unsigned* nc;
+ nc = new unsigned[n_scales + 1];
+
+ nc[1] = nc_1;
+ nc[2] = sub(nc[1], s);
+ for (unsigned i = 3; i <= n_scales; ++i)
+ nc[i] = sub(nc[i - 1], q);
+
+ for (unsigned i = 1; i <= n_scales; ++i)
+ std::cout << nc[i] << ' ';
+ std::cout << std::endl;
+
+ for (unsigned i = n_scales; i > 2; --i)
+ nc[i - 1] = q * nc[i];
+
+ for (unsigned i = 1; i <= n_scales; ++i)
+ std::cout << nc[i] << ' ';
+ std::cout << std::endl;
+}
Index: theo/mln/subsampling/debase.hh
--- theo/mln/subsampling/debase.hh (revision 0)
+++ theo/mln/subsampling/debase.hh (revision 0)
@@ -0,0 +1,351 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_SUBSAMPLING_DEBASE_HH
+# define MLN_SUBSAMPLING_DEBASE_HH
+
+/// \file
+///
+/// Debase subsampling.
+
+#include <mln/core/concept/image.hh>
+
+#define MLN_FLOAT double
+#include <sandbox/theo/exec/gaussian_directional_2d.hh>
+
+
+
+namespace mln
+{
+
+ namespace subsampling
+ {
+
+ /// FIXME: Doc.
+
+ template <typename I>
+ mln_concrete(I)
+ debase(const Image<I>& input,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift); // FIXME: Add round_up_size.
+
+
+ template <typename I>
+ mln_concrete(I)
+ debase(const Image<I>& input, unsigned gap);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ // Implementation.
+
+ namespace impl
+ {
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase");
+
+ const I& input = exact(input_);
+
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+
+ box<P> b(pmin, pmax);
+ mln_concrete(I) output(b);
+ mln_piter(I) p(output.domain());
+ for_all(p)
+ output(p) = input(p * gap + shift);
+
+ trace::exiting("subsampling::impl::debase");
+ return output;
+ }
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_fastest(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase_fastest");
+
+ const I& input = exact(input_);
+
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+
+ box<P> b(pmin, pmax);
+
+ typedef mln_concrete(I) O;
+ O output(b);
+
+ mln_box_runstart_piter(O) s(output.domain());
+ const unsigned n = s.run_length();
+ for_all(s)
+ {
+ const mln_value(I)* pi = & input(s * gap + shift);
+ mln_value(O)* po = & output(s);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ *po++ = *pi;
+ pi += gap;
+ }
+ }
+
+ trace::exiting("subsampling::impl::debase_fastest");
+ return output;
+ }
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_gaussian_antialiased_fastest(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase_gaussian_antialiased_fastest");
+
+ const I& input = exact(input_);
+
+ image2d<MLN_FLOAT> temp(input.domain());
+ data::fill(temp, input);
+ temp = linear::gaussian_directional_2d(temp, 1, 1.5, 0);
+ temp = linear::gaussian_directional_2d(temp, 0, 1.5, 0);
+
+ typedef mln_value(I) V;
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+
+ box<P> b(pmin, pmax);
+
+ typedef mln_concrete(I) O;
+ O output(b);
+
+ mln_box_runstart_piter(O) s(output.domain());
+ const unsigned n = s.run_length();
+ for_all(s)
+ {
+ const MLN_FLOAT* pi = & temp(s * gap + shift);
+ mln_value(O)* po = & output(s);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ *po++ = V(*pi + 0.49);
+ pi += gap;
+ }
+ }
+
+ trace::entering("subsampling::impl::debase_gaussian_antialiased_fastest");
+ return output;
+ }
+
+
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_2d_antialias_pointer_fastest(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase_2d_antialias_pointer_fastest");
+
+ const I& input = exact(input_);
+
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+
+ box<P> b(pmin, pmax);
+
+ typedef mln_concrete(I) O;
+ O output(b);
+
+ const unsigned nrows = input.nrows();
+ const unsigned ncols = input.ncols();
+
+ typedef mln_value(I) V;
+ typedef mln_sum(V) S;
+ for (unsigned row = 0; row < nrows; row += gap)
+ {
+ const V* ptr1 = & input.at_(row, 0);
+ const V* ptr2 = & input.at_(row + 1, 0);
+ const V* ptr3 = & input.at_(row + 2, 0);
+ for (unsigned col = 0; col < ncols; col += gap)
+ {
+ S s;
+
+ // mean
+ s = *ptr1++ + *ptr1++ + *ptr1++;
+ s += *ptr2++ + *ptr2++ + *ptr2++;
+ s += *ptr3++ + *ptr3++ + *ptr3++;
+ output.at_(row / gap, col / gap) = (s + 4) / 9;
+// // cut
+// s = 1 * *ptr1++ + 2 * *ptr1++ + 1 * *ptr1++;
+// s += 2 * *ptr2++ + 3 * *ptr2++ + 2 * *ptr2++;
+// s += 1 * *ptr3++ + 2 * *ptr3++ + 1 * *ptr3++;
+// output.at_(row / gap, col / gap) = (s + 7) / 15;
+ }
+ }
+
+ trace::exiting("subsampling::impl::debase_2d_antialias_pointer_fastest");
+ return output;
+ }
+
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_2d_antialias_offset_fastest(const Image<I>& input_,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::impl::debase_2d_antialias_offset_fastest");
+
+ const I& input = exact(input_);
+
+ typedef mln_value(I) V;
+ typedef mln_sum(V) S;
+
+ typedef mln_site(I) P;
+ P pmin = input.domain().pmin() / gap,
+ pmax = input.domain().pmax() / gap;
+ box<P> b(pmin, pmax);
+ typedef mln_concrete(I) O;
+ O output(b);
+
+ const V* ptr1 = & input.at_(0, 0);
+ const V* ptr2 = & input.at_(1, 0);
+ const V* ptr3 = & input.at_(2, 0);
+
+ mln_box_runstart_piter(O) s(output.domain());
+ const unsigned n = s.run_length();
+
+ unsigned offset = input.delta_index(point2d(3,0) - point2d(0,3*n));
+
+ for_all(s)
+ {
+ mln_value(O)* po = & output(s);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ S s;
+ s = *ptr1++ + *ptr1++ + *ptr1++;
+ s += *ptr2++ + *ptr2++ + *ptr2++;
+ s += *ptr3++ + *ptr3++ + *ptr3++;
+ *po++ = (s + 4) / 9;
+ }
+ ptr1 += offset;
+ ptr2 += offset;
+ ptr3 += offset;
+ }
+
+ trace::exiting("subsampling::impl::debase_2d_antialias_offset_fastest");
+ return output;
+ }
+
+
+ } // end of namespace mln::subsampling::impl
+
+
+
+ // Dispatch.
+
+ namespace internal
+ {
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase_dispatch(const Image<I>& input,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ return impl::debase_2d_antialias_pointer_fastest /* debase_2d_antialias_offset_fastest
*/(input, gap, shift);
+ }
+
+
+ } // end of namespace mln::subsampling::internal
+
+
+
+ // Facades.
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase(const Image<I>& input,
+ unsigned gap,
+ const mln_deduce(I, site, delta)& shift)
+ {
+ trace::entering("subsampling::debase");
+
+ typedef mln_site(I) P;
+
+ mln_precondition(exact(input).is_valid());
+ mln_precondition(exact(input).domain().pmin() == literal::origin);
+ mln_precondition(gap > 1);
+ for (unsigned i = 0; i < P::dim; ++i)
+ mln_precondition(shift[i] < gap);
+
+ mln_concrete(I) output;
+ output = internal::debase_dispatch(input, gap, shift);
+
+ trace::exiting("subsampling::debase");
+ return output;
+ }
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ debase(const Image<I>& input, unsigned gap)
+ {
+ return debase(input, gap, literal::zero);
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::subsampling
+
+} // end of namespace mln
+
+
+#endif // ! MLN_SUBSAMPLING_DEBASE_HH
Index: theo/mln/subsampling/integral.hh
--- theo/mln/subsampling/integral.hh (revision 0)
+++ theo/mln/subsampling/integral.hh (revision 0)
@@ -0,0 +1,295 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_SUBSAMPLING_INTEGRAL_HH
+# define MLN_SUBSAMPLING_INTEGRAL_HH
+
+/// \file
+///
+/// Both subsampling and integral image computation.
+
+#include <mln/core/concept/image.hh>
+#include <mln/debug/println.hh>
+
+
+
+namespace mln
+{
+
+ namespace subsampling
+ {
+
+ /// FIXME: Doc.
+
+ template <typename I>
+ mln_concrete(I)
+ integral(const Image<I>& input, unsigned scale);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ // Implementation.
+
+ namespace impl
+ {
+
+
+ template <unsigned scale, typename I>
+ inline
+ mln_concrete(I)
+ integral__why_is_it_slow(const Image<I>& input_)
+ {
+ trace::entering("subsampling::impl::integral__why_is_it_slow");
+
+ const I& input = exact(input_);
+ const unsigned scale2 = scale * scale, round_it = scale2 / 2;
+
+ typedef mln_value(I) V;
+ typedef mln_sum(V) S;
+ typedef mln_site(I) P;
+
+ box<P> b = make::box2d(input.nrows() / scale, input.ncols() / scale);
+ const unsigned nrows = b.nrows(), ncols = b.ncols();
+
+ typedef mln_concrete(I) O;
+ O output(b, 0); // no external border in 'output'
+ V* po = output.buffer();
+
+ unsigned
+ tile_cr = input.delta_index(dpoint2d(scale, - ncols * scale)),
+ cr = input.delta_index(dpoint2d(1, - (int)scale));
+
+ const V* pi = & input.at_(0, 0); // first point of tiles
+
+ // (row, col) are tile coordinates.
+ for (unsigned row = 0; row < nrows; ++row)
+ {
+ S hsum = 0, hsum2 = 0; // horizontal integral
+ for (unsigned col = 0; col < ncols; ++col)
+ {
+ S sum = 0, sum2 = 0;
+ const V* ptr = pi;
+
+ for (unsigned r = 0; r < scale; ++r)
+ {
+ for (unsigned c = 0; c < scale; ++c)
+ {
+ sum += *ptr;
+ ++ptr;
+ }
+ ptr += cr;
+ }
+ // ...
+ pi += scale;
+ *po++ = (round_it + sum) / scale2;
+ }
+ pi += tile_cr;
+ }
+
+ trace::exiting("subsampling::impl::integral__why_is_it_slow");
+ return output;
+ }
+
+
+
+ template <unsigned scale, typename I>
+ inline
+ mln_concrete(I)
+ integral_(const Image<I>& input_)
+ {
+ trace::entering("subsampling::impl::integral_");
+
+ const I& input = exact(input_);
+ const unsigned scale2 = scale * scale, round_it = scale2 / 2;
+
+ typedef mln_value(I) V;
+ typedef mln_sum(V) S;
+ typedef mln_site(I) P;
+
+ box<P> b = make::box2d((input.nrows() + scale - 1) / scale,
+ (input.ncols() + scale - 1) / scale);
+ typedef mln_concrete(I) O;
+ O output(b, 0);
+ V* po = output.buffer();
+
+ const unsigned nrows = input.nrows();
+ const unsigned ncols = input.ncols();
+
+ typedef const V* Ptr;
+ Ptr ptr[scale];
+ for (unsigned row = 0; row < nrows; row += scale)
+ {
+ for (unsigned r = 0; r < scale; ++r)
+ ptr[r] = & input.at_(row + r, 0);
+
+ for (unsigned col = 0; col < ncols; col += scale)
+ {
+ S sum = 0;
+ for (unsigned r = 0; r < scale; ++r)
+ for (unsigned c = 0; c < scale; ++c)
+ // g++ does *not* un-roll this inner loop!!!
+ // icc does...
+ sum += *ptr[r]++;
+
+ *po++ = (round_it + sum) / scale2;
+ }
+ }
+
+ trace::exiting("subsampling::impl::integral_");
+ return output;
+ }
+
+
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ integral_3(const Image<I>& input_)
+ {
+ trace::entering("subsampling::impl::integral_3");
+
+ const unsigned scale = 3;
+
+ const I& input = exact(input_);
+ const unsigned area = scale * scale;
+
+ typedef mln_value(I) V;
+ typedef mln_sum(V) S;
+ typedef mln_site(I) P;
+
+ box<P> b = make::box2d((input.nrows() + scale - 1) / scale,
+ (input.ncols() + scale - 1) / scale);
+ const unsigned up = b.ncols();
+
+ mln_concrete(I) sub(b, 0);
+ V* p_sub = sub.buffer();
+
+ mln_ch_value(I, S) integral_sum(b, 0);
+ S* p_isum = integral_sum.buffer();
+
+ mln_ch_value(I, S) integral_sum_2(b, 0);
+ S* p_isum_2 = integral_sum_2.buffer();
+
+ const unsigned nrows = input.nrows();
+ const unsigned ncols = input.ncols();
+
+ for (unsigned row = 0; row < nrows; row += scale)
+ {
+ S h_sum = 0, h_sum_2 = 0;
+ const V* ptr1 = & input.at_(row, 0);
+ const V* ptr2 = & input.at_(row + 1, 0);
+ const V* ptr3 = & input.at_(row + 2, 0);
+ for (unsigned col = 0; col < ncols; col += scale)
+ {
+ S sum;
+ sum = *ptr1++ + *ptr1++ + *ptr1++;
+ sum += *ptr2++ + *ptr2++ + *ptr2++;
+ sum += *ptr3++ + *ptr3++ + *ptr3++;
+
+ S val = sum / area;
+ *p_sub++ = val;
+
+ h_sum += val;
+ h_sum_2 += val * val;
+
+ if (row != 0)
+ {
+ *p_isum = h_sum + *(p_isum - up);
+ *p_isum_2 = h_sum_2 + *(p_isum_2 - up);
+ }
+ else
+ {
+ // exception
+ *p_isum = h_sum;
+ *p_isum_2 = h_sum_2;
+ }
+
+ p_isum += 1;
+ p_isum_2 += 1;
+ }
+ }
+
+ debug::println(sub);
+ debug::println(integral_sum);
+ debug::println(integral_sum_2);
+
+ trace::exiting("subsampling::impl::integral_3");
+ return sub;
+ }
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ integral(const Image<I>& input, unsigned scale)
+ {
+ // mln_precondition(input.nrows() % scale == 0);
+ // mln_precondition(input.ncols() % scale == 0);
+ if (scale == 3)
+ return integral_3(input);
+ else
+ std::cerr << "NYI!" << std::endl;
+ }
+
+
+ } // end of namespace mln::subsampling::impl
+
+
+
+
+ // Facades.
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ integral(const Image<I>& input_, unsigned scale)
+ {
+ trace::entering("subsampling::integral");
+
+ const I& input = exact(input_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(input.domain().pmin() == literal::origin);
+ mln_precondition(scale > 1);
+
+ mln_concrete(I) output;
+ output = impl::integral(input, scale);
+
+ trace::exiting("subsampling::integral");
+ return output;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::subsampling
+
+} // end of namespace mln
+
+
+#endif // ! MLN_SUBSAMPLING_INTEGRAL_HH
Index: theo/mln/subsampling/in.pgm.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: theo/mln/subsampling/in.pgm.gz
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: theo/mln/subsampling/debase.cc
--- theo/mln/subsampling/debase.cc (revision 0)
+++ theo/mln/subsampling/debase.cc (revision 0)
@@ -0,0 +1,23 @@
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/util/timer.hh>
+
+#include "debase.hh"
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ image2d<int_u8> in;
+ io::pgm::load(in, "in.pgm");
+
+ util::timer t;
+ t.start();
+ image2d<int_u8> out = subsampling::debase(in, 3, dpoint2d(1,1));
+ float t_ = t.stop();
+ std::cout << t_ << std::endl;
+
+ io::pgm::save(out, "out.pgm");
+}
Index: theo/mln/subsampling/integral.cc
--- theo/mln/subsampling/integral.cc (revision 0)
+++ theo/mln/subsampling/integral.cc (revision 0)
@@ -0,0 +1,38 @@
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/util/timer.hh>
+
+#include "integral.hh"
+
+#include <mln/debug/iota.hh>
+#include <mln/debug/println.hh>
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+
+ image2d<int_u8> in(6, 9);
+ debug::iota(in);
+ debug::println(in);
+
+ image2d<int_u8> out = subsampling::integral(in, 3);
+// debug::println(out);
+
+
+// {
+// image2d<int_u8> in;
+// io::pgm::load(in, "in.pgm");
+
+// util::timer t;
+// t.start();
+// image2d<int_u8> out = subsampling::integral(in, 3);
+// float t_ = t.stop();
+// std::cout << t_ << std::endl;
+
+// io::pgm::save(out, "out.pgm");
+// }
+
+}
Index: theo/mln/browsing/window_sliding.cc
--- theo/mln/browsing/window_sliding.cc (revision 0)
+++ theo/mln/browsing/window_sliding.cc (revision 0)
@@ -0,0 +1,52 @@
+#include <iostream>
+#include <cassert>
+
+
+
+
+void window_sliding(unsigned nr, unsigned nc,
+ unsigned h, unsigned w)
+{
+ const unsigned h_2 = h / 2;
+ const int d_row_up = - 1 - h_2, d_row_down = h_2;
+
+ // top part
+ for (int row = 0; row <= h_2; ++row)
+ {
+ assert(row + d_up < 0);
+ assert(row + d_down >= 0 && row + d_down < nr);
+ // top left
+ // ...
+
+ // top middle
+ // ...
+
+ // top right
+ // ...
+ }
+ // main part
+ for (int row = h_2 + 1; row <= nr - 1 - h_2; ++row)
+ {
+ assert(row + d_up >= 0 && row + d_up < nr);
+ assert(row + d_down >= 0 && row + d_down < nr);
+ }
+ // bottom part
+ for (int row = nr - h_2; row < nr; ++row)
+ {
+ assert(row + d_up >= 0 && row + d_up < nr);
+ assert(row + d_down >= nr);
+ }
+}
+
+
+
+int main()
+{
+
+// unsigned nr = 50, nc = 100;
+
+ unsigned nr = 10, nc = 10;
+ unsigned h = 3, w = 5;
+ window_sliding(nr, nc, h, w);
+
+}