* binarization/sauvola_threshold.hh,
* binarization/sauvola.hh: Use fun::v2v::rgb_to_int_u8.
* binarization/sauvola_ms.hh: New. Sauvola multi-scale routine.
* src/binarization/sauvola.cc: Make the window size a program
argument.
* src/binarization/sauvola_ms.cc: Use Sauvola multi-scale routine.
---
scribo/ChangeLog | 14 +
scribo/binarization/sauvola.hh | 4 +-
scribo/binarization/sauvola_ms.hh | 822 +++++++++++++++
scribo/binarization/sauvola_threshold.hh | 14 +-
scribo/src/binarization/sauvola.cc | 7 +-
scribo/src/binarization/sauvola_ms.cc | 1669 +-----------------------------
6 files changed, 876 insertions(+), 1654 deletions(-)
create mode 100644 scribo/binarization/sauvola_ms.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index a5c7fea..8488ae3 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,19 @@
2009-12-14 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Cleanup Sauvola's binarization code.
+
+ * binarization/sauvola_threshold.hh,
+ * binarization/sauvola.hh: Use fun::v2v::rgb_to_int_u8.
+
+ * binarization/sauvola_ms.hh: New. Sauvola multi-scale routine.
+
+ * src/binarization/sauvola.cc: Make the window size a program
+ argument.
+
+ * src/binarization/sauvola_ms.cc: Use Sauvola multi-scale routine.
+
+2009-12-14 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* core/object_image.hh: Make use of mln::labeled_image_base.
2009-12-14 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/scribo/binarization/sauvola.hh b/scribo/binarization/sauvola.hh
index 5323847..1339c66 100644
--- a/scribo/binarization/sauvola.hh
+++ b/scribo/binarization/sauvola.hh
@@ -35,6 +35,8 @@
# include <mln/value/int_u8.hh>
# include <mln/value/rgb8.hh>
+# include <mln/fun/v2v/rgb_to_int_u.hh>
+
# include <scribo/binarization/sauvola_threshold.hh>
# include <scribo/binarization/binarize.hh>
@@ -106,7 +108,7 @@ namespace scribo
mln_precondition(exact(input).is_valid());
mln_ch_value(I, value::int_u8) gima;
- gima = data::transform(input, internal::rgb8_to_int_u8());
+ gima = data::transform(input, mln::fun::v2v::rgb_to_int_u<8>());
mln_ch_value(I, bool)
output = binarize(gima,
diff --git a/scribo/binarization/sauvola_ms.hh b/scribo/binarization/sauvola_ms.hh
new file mode 100644
index 0000000..bc52620
--- /dev/null
+++ b/scribo/binarization/sauvola_ms.hh
@@ -0,0 +1,822 @@
+// 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 SCRIBO_BINARIZATION_SAUVOLA_MS_HH
+# define SCRIBO_BINARIZATION_SAUVOLA_MS_HH
+
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/data/fill.hh>
+
+# include <mln/subsampling/antialiased.hh>
+
+# include <mln/transform/influence_zone_geodesic.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/border/mirror.hh>
+# include <mln/border/adjust.hh>
+
+# include <mln/core/box_runend_piter.hh>
+
+# include <scribo/subsampling/integral_single_image.hh>
+
+# include <scribo/core/macros.hh>
+# include <scribo/core/object_image.hh>
+
+# include <scribo/binarization/sauvola_threshold.hh>
+# include <scribo/binarization/internal/first_pass_functor.hh>
+
+# include <scribo/canvas/integral_browsing.hh>
+
+
+namespace scribo
+{
+
+ namespace binarization
+ {
+
+ using namespace mln;
+ using value::int_u8;
+
+
+ unsigned my_find_root(image2d<unsigned>& parent, unsigned x)
+ {
+ if (parent.element(x) == x)
+ return x;
+ return parent.element(x) = my_find_root(parent,
+ parent.element(x));
+ }
+
+
+ image2d<int_u8>
+ compute_t_n_and_e_2(const image2d<int_u8>& sub, image2d<int_u8>&
e_2,
+ unsigned lambda_min, unsigned lambda_max,
+ unsigned s,
+ unsigned q, unsigned i, unsigned w,
+ const image2d<util::couple<double,double> >& integral_sum_sum_2)
+ {
+ typedef image2d<int_u8> I;
+ typedef point2d P;
+
+ unsigned ratio = std::pow(q, i - 2); // Ratio in comparison to e_2
+
+ unsigned
+ w_local = w * ratio,
+ w_local_h = w_local,
+ w_local_w = w_local;
+
+ if (! (w_local % 2))
+ {
+ --w_local_w;
+ ++w_local_h;
+ }
+
+ // 1st pass
+ scribo::binarization::internal::first_pass_functor< image2d<int_u8> >
+ f(sub);
+ scribo::canvas::integral_browsing(integral_sum_sum_2,
+ ratio,
+ w_local_w, w_local_h,
+ s,
+ f);
+
+ // 2nd pass
+ {
+ util::array<mln_value_(I) *> ptr(ratio);
+ unsigned nrows = geom::nrows(e_2);
+
+ mln_box_runend_piter_(I) sp(sub.domain()); // Backward.
+ unsigned ncols = sp.run_length();
+ for_all(sp)
+ {
+ unsigned p = &sub(sp) - sub.buffer(); // Offset
+ P site = sp;
+
+ {
+ P tmp = site * ratio;
+
+ // FIXME: to be removed!
+ if (tmp.row() + ratio >= nrows)
+ ptr.resize(nrows - tmp.row());
+
+ ptr(0) = &e_2(tmp);
+ // FIXME: pointers could just be updated with an offset.
+ for (unsigned j = 1; j < ptr.size(); ++j)
+ {
+ tmp[0] += 1;
+ ptr(j) = & e_2(tmp);
+ }
+ }
+
+ for (unsigned j = 0; j < ncols; ++j)
+ {
+ if (f.msk.element(p))
+ {
+
+ mln_site_(I) sq = site * ratio;
+
+ if (f.parent.element(p) == p)
+ {
+ // test over the component cardinality
+ f.msk.element(p) = f.card.element(p) > lambda_min
+ && f.card.element(p) < lambda_max;
+
+ if (f.msk.element(p) && e_2(sq) == 0u)
+ {
+ for (unsigned l = 0; l < ptr.size(); ++l)
+ std::memset(ptr(l), i, ratio * sizeof(mln_value_(I)));
+ }
+
+ }
+ else
+ {
+ // Propagation
+ f.msk.element(p) = f.msk.element(f.parent.element(p));
+
+ if (f.msk.element(p) && e_2(sq) == 0u)
+ {
+ for (unsigned l = 0; l < ptr.size(); ++l)
+ std::memset(ptr(l), i, ratio * sizeof(mln_value_(I)));
+ }
+
+ }
+ }
+
+ for (unsigned l = 0; l < ptr.size(); ++l)
+ ptr(l) -= ratio;
+
+ --site[1];
+ --p;
+ }
+
+ }
+ } // end of 2nd pass
+
+ return f.t_sub;
+ }
+
+
+
+ template <typename I, typename J, typename K>
+ mln_ch_value(I, bool)
+ multi_scale_binarization(const I& in, const J& e2,
+ const util::array<K>& t_ima,
+ unsigned s)
+ {
+ mln_ch_value(I,bool) out;
+ initialize(out, in);
+
+ typedef const mln_value(K)* ptr_type;
+
+ ptr_type ptr_t[5];
+ ptr_t[2] = & t_ima[2].at_(0, 0);
+ ptr_t[3] = & t_ima[3].at_(0, 0);
+ ptr_t[4] = & t_ima[4].at_(0, 0);
+
+
+ const mln_value(J)* ptr_e2 = & e2.at_(0, 0);
+ const mln_value(I)* ptr__in = & in.at_(0, 0);
+ bool* ptr__out = & out.at_(0, 0);
+
+
+ // Since we iterate from a smaller image in the largest ones and
+ // image at scale 1 does not always have a size which can be
+ // divided by (4*s), some sites in the border may not be processed
+ // and we must skip them.
+ int more_offset = - ((4 * s) - in.ncols() % (4 * s));
+
+ if (more_offset == - (static_cast<int>(4*s)))
+ more_offset = 0; // No offset needed.
+
+ const int
+ nrows4 = t_ima[4].nrows(), ncols4 = t_ima[4].ncols(),
+
+
+ delta1 = in.delta_index(dpoint2d(+1, -(s - 1))),
+ delta1b = in.delta_index(dpoint2d(+1, -(s + s - 1))),
+ delta1c = in.delta_index(dpoint2d(-(s + s - 1), +1)),
+ delta1d = in.delta_index(dpoint2d(+1, -(s * 4 - 1))),
+ delta1e = in.delta_index(dpoint2d(-(s * 4 - 1), +1)),
+ delta1f = in.delta_index(dpoint2d(-(s - 1), +1)),
+
+ delta2 = t_ima[2].delta_index(dpoint2d(+1, -1)),
+ delta2b = t_ima[2].delta_index(dpoint2d(+1, -3)),
+ delta2c = t_ima[2].delta_index(dpoint2d(-3, +1)),
+
+ delta3 = t_ima[3].delta_index(dpoint2d(+1, -1)),
+
+ eor1 = in.delta_index(dpoint2d(+4 * s, - in.ncols())) + more_offset,
+ eor2 = t_ima[2].delta_index(dpoint2d(+4,- t_ima[2].ncols())),
+ eor3 = t_ima[3].delta_index(dpoint2d(+2,- t_ima[3].ncols())),
+ eor4 = t_ima[4].delta_index(dpoint2d(+1,- t_ima[4].ncols()));
+
+ mln_value(J) threshold;
+ for (int row4 = 0; row4 < nrows4; ++row4)
+ {
+ for (int col4 = 0; col4 < ncols4; ++col4)
+ {
+ // top left 1
+ {
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1f; ptr__in += delta1f;
+ }
+
+ ++ptr_t[2]; ++ptr_e2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1b; ptr__in += delta1b;
+ }
+
+ ptr_t[2] += delta2; ptr_e2 += delta2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1f; ptr__in += delta1f;
+
+ }
+
+ ++ptr_t[2]; ++ptr_e2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1c; ptr__in += delta1c;
+ }
+
+ ptr_t[2] -= delta2; ptr_e2 -= delta2;
+ }
+
+ // top right 1
+ ptr_t[3] += 1;
+ {
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1f; ptr__in += delta1f;
+ }
+
+ ++ptr_t[2]; ++ptr_e2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1b; ptr__in += delta1b;
+ }
+
+ ptr_t[2] += delta2; ptr_e2 += delta2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1f; ptr__in += delta1f;
+ }
+
+ ++ptr_t[2]; ++ptr_e2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1d; ptr__in += delta1d;
+ }
+
+ ptr_t[2] += delta2b; ptr_e2 += delta2b;
+ }
+
+ // bot left 1
+ ptr_t[3] += delta3;
+ {
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1f; ptr__in += delta1f;
+ }
+
+ ++ptr_t[2]; ++ptr_e2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1b; ptr__in += delta1b;
+ }
+
+ ptr_t[2] += delta2; ptr_e2 += delta2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1f; ptr__in += delta1f;
+ }
+
+ ++ptr_t[2]; ++ptr_e2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1c; ptr__in += delta1c;
+ }
+
+ ptr_t[2] -= delta2; ptr_e2 -= delta2;
+ }
+
+ // bot right 1
+ ptr_t[3] += 1;
+ {
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1f; ptr__in += delta1f;
+ }
+
+ ++ptr_t[2]; ++ptr_e2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1b; ptr__in += delta1b;
+ }
+
+ ptr_t[2] += delta2; ptr_e2 += delta2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1f; ptr__in += delta1f;
+ }
+
+ ++ptr_t[2]; ++ptr_e2;
+ threshold = *ptr_t[*ptr_e2];
+ {
+ for (unsigned i = 1; i < s; ++i)
+ {
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1; ptr__in += delta1;
+ }
+
+ for (unsigned j = 1; j < s; ++j)
+ {
+ *ptr__out = *ptr__in < threshold;
+ ++ptr__out; ++ptr__in;
+ }
+ *ptr__out = *ptr__in < threshold;
+ ptr__out += delta1e; ptr__in += delta1e;
+ }
+ }
+
+ // bot right -> next top left
+ ptr_t[2] += delta2c; ptr_e2 += delta2c;
+ ptr_t[3] = ptr_t[3] - delta3;
+ ptr_t[4] += 1;
+ }
+
+ // eof -> next bof
+ ptr__out += eor1; ptr__in += eor1;
+ ptr_t[2] += eor2; ptr_e2 += eor2;
+ ptr_t[3] += eor3;
+ ptr_t[4] += eor4;
+ }
+
+ return out;
+ }
+
+
+
+ unsigned sub(unsigned nbr, unsigned down_scaling)
+ {
+ return (nbr + down_scaling - 1) / down_scaling;
+ }
+
+ // Compute domains of subsampled images and make sure they can be
+ // divided by 2.
+ template <typename I>
+ util::array<util::couple<mln_domain(I), unsigned> >
+ compute_sub_domains(const I& ima, unsigned n_scales, unsigned s)
+ {
+ util::array<util::couple<unsigned, unsigned> > n(n_scales + 2);
+
+ n(1) = make::couple(ima.nrows(), ima.ncols());
+ n(2) = make::couple(sub(n(1).first(), s),
+ sub(n(1).second(), s));
+ for (unsigned i = 3; i <= n_scales + 1; ++i)
+ n(i) = make::couple(sub(n(i - 1).first(), 2),
+ sub(n(i - 1).second(), 2));
+
+
+ util::array<util::couple<mln_domain(I), unsigned> > out(n.size());
+ out(0) = make::couple(make::box2d(1,1), 1u);
+ out(1) = make::couple(make::box2d(ima.nrows(), ima.ncols()), 2u);
+ out(n_scales + 1) = make::couple(make::box2d(n(n_scales + 1).first(),
+ n(n_scales + 1).second()),
+ 1u);
+
+ for (unsigned i = n_scales; i > 1; --i)
+ out(i) = make::couple(make::box2d(2 * out(i + 1).first().nrows(),
+ 2 * out(i + 1).first().ncols()),
+ 2 * out(i + 1).second());
+
+ out(1).second() = std::max(out(2).first().ncols() * s - ima.ncols(),
+ out(2).first().nrows() * s - ima.nrows());
+
+ return out;
+ }
+
+ template <typename I>
+ mln_ch_value(I,bool)
+ sauvola_ms(const Image<I>& input_1_, unsigned w_1,
+ unsigned s, unsigned lambda_min_1)
+ {
+ trace::entering("scribo::binarization::sauvola_ms");
+
+ const I& input_1 = exact(input_1_);
+
+ mlc_is_a(mln_value(I), value::Scalar)::check();
+ mln_precondition(input_1.is_valid());
+
+ dpoint2d none(0, 0);
+
+ // Number of subscales.
+ unsigned nb_subscale = 3;
+
+ // Window size.
+ unsigned w_work = w_1 / s; // Scale 2
+
+
+ // Subscale step.
+ unsigned q = 2;
+
+ unsigned lambda_min_2 = lambda_min_1 / s;
+ unsigned lambda_max_2 = lambda_min_2 * q;
+
+
+ util::array<I> t_ima;
+
+ // Make sure t_ima indexes start from 2.
+ {
+ I dummy(1,1);
+ for (unsigned i = 0; i < nb_subscale + 2; ++i)
+ t_ima.append(dummy);
+ }
+
+ util::array<I> sub_ima;
+
+ // Make sure sub_ima indexes start from 2.
+ {
+ I dummy(1,1);
+ sub_ima.append(dummy);
+ sub_ima.append(dummy);
+ }
+
+ util::array<util::couple<box2d, unsigned> >
+ sub_domains = compute_sub_domains(input_1, nb_subscale, s);
+
+ border::adjust(input_1, sub_domains(1).second());
+ border::mirror(input_1);
+
+
+ // Resize input and compute integral images.
+ typedef image2d<util::couple<double,double> > integral_t;
+ integral_t integral_sum_sum_2;
+
+ // Subsampling from scale 1 to 2.
+ sub_ima.append(scribo::subsampling::integral(input_1, s,
+ integral_sum_sum_2,
+ sub_domains[2].first(),
+ sub_domains[2].second()));
+
+
+ // Subsampling to scale 3 and 4.
+ for (unsigned i = 3; i <= nb_subscale + 1; ++i)
+ sub_ima.append(mln::subsampling::antialiased(sub_ima[i - 1], q, none,
+ sub_domains[i].first(),
+ sub_domains[i].second()));
+
+
+ // Compute threshold images.
+ image2d<int_u8> e_2;
+ initialize(e_2, sub_ima[2]);
+ data::fill(e_2, 0u);
+
+ // Highest scale -> no maximum component size.
+ {
+ int i = sub_ima.size() - 1;
+ unsigned ratio = std::pow(q, i - 2); // Ratio compared to e_2
+ t_ima[i] = compute_t_n_and_e_2(sub_ima[i], e_2,
+ lambda_min_2 / ratio,
+ mln_max(unsigned),
+ s,
+ q, i, w_work, integral_sum_sum_2);
+ }
+
+ // Other scales -> maximum and minimum component size.
+ {
+ for (int i = sub_ima.size() - 2; i > 2; --i)
+ {
+ unsigned ratio = std::pow(q, i - 2); // Ratio compared to e_2
+ t_ima[i] = compute_t_n_and_e_2(sub_ima[i], e_2,
+ lambda_min_2 / ratio,
+ lambda_max_2 / ratio,
+ s,
+ q, i, w_work, integral_sum_sum_2);
+ }
+ }
+
+ // Lowest scale -> no minimum component size.
+ {
+ t_ima[2] = compute_t_n_and_e_2(sub_ima[2], e_2, 0, lambda_max_2,
+ s, 1, 2, w_work, integral_sum_sum_2);
+ }
+
+
+ // Propagate scale values.
+ e_2 = transform::influence_zone_geodesic(e_2, c8());
+
+
+ // Binarize
+ image2d<bool> output = multi_scale_binarization(input_1, e_2, t_ima, s);
+
+ trace::exiting("scribo::binarization::sauvola_ms");
+ return output;
+ }
+
+ } // end of namespace scribo::binarization
+
+} // end of namespace scribo
+
+
+#endif // SCRIBO_BINARIZATION_SAUVOLA_MS_HH
diff --git a/scribo/binarization/sauvola_threshold.hh
b/scribo/binarization/sauvola_threshold.hh
index b1f9a81..20abc50 100644
--- a/scribo/binarization/sauvola_threshold.hh
+++ b/scribo/binarization/sauvola_threshold.hh
@@ -44,6 +44,8 @@
# include <mln/pw/all.hh>
# include <mln/core/routine/duplicate.hh>
+# include <mln/fun/v2v/rgb_to_int_u.hh>
+
# include <scribo/core/init_integral_image.hh>
@@ -96,16 +98,6 @@ namespace scribo
namespace internal
{
- struct rgb8_to_int_u8 : Function_v2v< rgb8_to_int_u8 >
- {
- typedef value::int_u8 result;
- result operator()(const value::rgb8& c) const
- {
- return (c.red() + c.green() + c.blue()) / 3;
- }
- };
-
-
/*! \brief compute Sauvola's threshold applying directly the formula.
\param[in] m_x_y Mean value.
@@ -383,7 +375,7 @@ namespace scribo
mln_ch_value(I, value::int_u8) gima;
gima = data::transform(input,
- internal::rgb8_to_int_u8());
+ mln::fun::v2v::rgb_to_int_u<8>());
mln_ch_value(I, value::int_u8)
output = impl::generic::sauvola_threshold(gima, window_size,
diff --git a/scribo/src/binarization/sauvola.cc b/scribo/src/binarization/sauvola.cc
index 28d3ae7..efe4787 100644
--- a/scribo/src/binarization/sauvola.cc
+++ b/scribo/src/binarization/sauvola.cc
@@ -33,6 +33,7 @@
const char *args_desc[][2] =
{
{ "input.ppm", "A color image." },
+ { "wsize", "Window size (Common value: 51)." },
{0, 0}
};
@@ -42,10 +43,10 @@ int main(int argc, char *argv[])
using namespace mln;
using value::rgb8;
- if (argc != 3)
+ if (argc != 4)
return scribo::debug::usage(argv,
"Binarization of a color image based on Sauvola's algorithm.",
- "input.ppm output.pbm",
+ "input.ppm wsize output.pbm",
args_desc, "A binary image.");
trace::entering("main");
@@ -53,7 +54,7 @@ int main(int argc, char *argv[])
image2d<rgb8> input;
io::ppm::load(input, argv[1]);
- io::pbm::save(scribo::binarization::sauvola(input), argv[2]);
+ io::pbm::save(scribo::binarization::sauvola(input, atoi(argv[2])), argv[3]);
trace::exiting("main");
diff --git a/scribo/src/binarization/sauvola_ms.cc
b/scribo/src/binarization/sauvola_ms.cc
index ff5a99d..b3b4791 100644
--- a/scribo/src/binarization/sauvola_ms.cc
+++ b/scribo/src/binarization/sauvola_ms.cc
@@ -23,1300 +23,39 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/data/stretch.hh>
-#include <mln/data/paste.hh>
-#include <mln/debug/iota.hh>
-#include <mln/debug/quiet.hh>
-#include <mln/debug/println.hh>
-#include <mln/debug/println_with_border.hh>
-#include <mln/debug/filename.hh>
-#include <mln/fun/i2v/array.hh>
-#include <mln/io/pbm/all.hh>
-#include <mln/io/pgm/all.hh>
-#include <mln/io/ppm/all.hh>
-#include <mln/literal/colors.hh>
-#include <mln/math/sqr.hh>
-#include <mln/math/abs.hh>
-
-#include <mln/subsampling/antialiased.hh>
-
-#include <mln/transform/influence_zone_geodesic.hh>
-#include <mln/util/timer.hh>
-#include <mln/value/int_u16.hh>
+#include <mln/core/image/image2d.hh>
#include <mln/value/int_u8.hh>
-#include <mln/value/label_16.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/border/equalize.hh>
-#include <mln/border/mirror.hh>
-#include <mln/border/adjust.hh>
-#include <mln/debug/filename.hh>
-
-#include <mln/core/box_runend_piter.hh>
-#include <mln/core/box_runstart_piter.hh>
-
-#include <scribo/subsampling/integral_single_image.hh>
-//#include <scribo/subsampling/integral.hh>
-
-#include <scribo/core/macros.hh>
-#include <scribo/core/object_image.hh>
-
-#include <scribo/filter/objects_small.hh>
-#include <scribo/filter/objects_large.hh>
-
-#include <scribo/filter/objects_thin.hh>
-#include <scribo/filter/objects_thick.hh>
-
-#include <scribo/primitive/extract/objects.hh>
-
-#include <scribo/binarization/sauvola_threshold.hh>
-#include <scribo/binarization/internal/first_pass_functor.hh>
-
-#include <scribo/canvas/integral_browsing.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pbm/save.hh>
+#include <scribo/binarization/sauvola_ms.hh>
#include <scribo/debug/usage.hh>
-#include <scribo/debug/save_object_diff.hh>
-namespace mln
+bool check_args(int argc, char * argv[])
{
+ if (argc < 5 || argc > 6)
+ return false;
- using value::int_u8;
-
-
- unsigned my_find_root(image2d<unsigned>& parent, unsigned x)
- {
- if (parent.element(x) == x)
- return x;
- return parent.element(x) = my_find_root(parent,
- parent.element(x));
- }
-
-
- image2d<int_u8>
- compute_t_n_and_e_2(const image2d<int_u8>& sub, image2d<int_u8>&
e_2,
- unsigned lambda_min, unsigned lambda_max,
- unsigned s,
- unsigned q, unsigned i, unsigned w,
- const image2d<util::couple<double,double> >& integral_sum_sum_2)
- // lambdas: limits of component cardinality at this scale
- {
- typedef image2d<int_u8> I;
- typedef point2d P;
-
- util::timer tt;
- float t_;
-
- unsigned ratio = std::pow(q, i - 2); // Ratio in comparison to e_2
-
-
- tt.restart();
-
- unsigned
- w_local = w * ratio,
- w_local_h = w_local,
- w_local_w = w_local;
-
- if (! (w_local % 2))
- {
- --w_local_w;
- ++w_local_h;
- }
-
-// std::cout << "Echelle " << i
-// << " - w_local_h = " << w_local_h
-// << " - w_local_w = " << w_local_w
-// << " - w_1 = " << (w_local - 1) * s + 1
-// << std::endl;
-
-// std::cout << "Ratio = " << ratio << std::endl;
-// std::cout << " -----------" << std::endl;
-
- // 1st pass
- scribo::binarization::internal::first_pass_functor< image2d<int_u8> >
- f(sub);
- scribo::canvas::integral_browsing(integral_sum_sum_2,
- ratio,
- w_local_w, w_local_h,
- s,
- f);
-
-
- t_ = tt;
- if (! mln::debug::quiet)
- std::cout << "1st pass - " << t_ << std::endl;
-
- tt.restart();
-
- {
- util::array<mln_value_(I) *> ptr(ratio);
- unsigned nrows = geom::nrows(e_2);
-
- mln_box_runend_piter_(I) sp(sub.domain()); // Backward.
- unsigned ncols = sp.run_length();
- for_all(sp)
- {
- unsigned p = &sub(sp) - sub.buffer(); // Offset
- P site = sp;
-
- {
- P tmp = site * ratio;
-
- // FIXME: to be removed!
- if (tmp.row() + ratio >= nrows)
- ptr.resize(nrows - tmp.row());
-
- ptr(0) = &e_2(tmp);
- // FIXME: pointers could just be updated with an offset.
- for (unsigned j = 1; j < ptr.size(); ++j)
- {
- tmp[0] += 1;
- ptr(j) = & e_2(tmp);
- }
- }
-
- for (unsigned j = 0; j < ncols; ++j)
- {
- if (f.msk.element(p))
- {
-
- mln_site_(I) sq = site * ratio;
-
- if (f.parent.element(p) == p)
- {
- // test over the component cardinality
- f.msk.element(p) = f.card.element(p) > lambda_min
- && f.card.element(p) < lambda_max;
-
- if (f.msk.element(p) && e_2(sq) == 0u)
- {
- for (unsigned l = 0; l < ptr.size(); ++l)
- std::memset(ptr(l), i, ratio * sizeof(mln_value_(I)));
- }
-
- }
- else
- {
- // Propagation
- f.msk.element(p) = f.msk.element(f.parent.element(p));
-
- if (f.msk.element(p) && e_2(sq) == 0u)
- {
- for (unsigned l = 0; l < ptr.size(); ++l)
- std::memset(ptr(l), i, ratio * sizeof(mln_value_(I)));
- }
-
- }
- }
-
- for (unsigned l = 0; l < ptr.size(); ++l)
- ptr(l) -= ratio;
-
- --site[1];
- --p;
- }
-
- }
-
- t_ = tt;
- if (! mln::debug::quiet)
- std::cout << "2nd pass - " << t_ << std::endl;
-
-// io::pgm::save(e_2, mln::debug::filename("e.pgm", i));
-// io::pbm::save(f.msk, mln::debug::filename("mask.pbm", i));
-// io::pgm::save(data::stretch(int_u8(), card),
mln::debug::filename("card.pgm"));
- } // end of 2nd pass
-
-// io::pgm::save(f.t_sub, mln::debug::filename("t.pgm", i));
- return f.t_sub;
- }
-
-
-
- template <typename I, typename J, typename K>
- mln_ch_value(I, bool)
- binarize_generic(const I& in, const J& e2, const util::array<K>&
t_ima,
- unsigned s)
- {
- mln_ch_value(I,bool) out;
- initialize(out, in);
-
- typedef const mln_value(K)* ptr_type;
-
- ptr_type ptr_t[5];
- ptr_t[2] = & t_ima[2].at_(0, 0);
- ptr_t[3] = & t_ima[3].at_(0, 0);
- ptr_t[4] = & t_ima[4].at_(0, 0);
-
-
- const mln_value(J)* ptr_e2 = & e2.at_(0, 0);
- const mln_value(I)* ptr__in = & in.at_(0, 0);
- bool* ptr__out = & out.at_(0, 0);
-
-
- // Since we iterate from a smaller image in the largest ones and
- // image at scale 1 does not always have a size which can be
- // divided by (4*s), some sites in the border may not be processed
- // and we must skip them.
- int more_offset = - ((4 * s) - in.ncols() % (4 * s));
-
- if (more_offset == - (static_cast<int>(4*s)))
- more_offset = 0; // No offset needed.
-
- const int
- nrows4 = t_ima[4].nrows(), ncols4 = t_ima[4].ncols(),
-
-
- delta1 = in.delta_index(dpoint2d(+1, -(s - 1))),
- delta1b = in.delta_index(dpoint2d(+1, -(s + s - 1))),
- delta1c = in.delta_index(dpoint2d(-(s + s - 1), +1)),
- delta1d = in.delta_index(dpoint2d(+1, -(s * 4 - 1))),
- delta1e = in.delta_index(dpoint2d(-(s * 4 - 1), +1)),
- delta1f = in.delta_index(dpoint2d(-(s - 1), +1)),
-
- delta2 = t_ima[2].delta_index(dpoint2d(+1, -1)),
- delta2b = t_ima[2].delta_index(dpoint2d(+1, -3)),
- delta2c = t_ima[2].delta_index(dpoint2d(-3, +1)),
-
- delta3 = t_ima[3].delta_index(dpoint2d(+1, -1)),
-
- eor1 = in.delta_index(dpoint2d(+4 * s, - in.ncols())) + more_offset,
- eor2 = t_ima[2].delta_index(dpoint2d(+4,- t_ima[2].ncols())),
- eor3 = t_ima[3].delta_index(dpoint2d(+2,- t_ima[3].ncols())),
- eor4 = t_ima[4].delta_index(dpoint2d(+1,- t_ima[4].ncols()));
-
- mln_value(J) threshold;
- for (int row4 = 0; row4 < nrows4; ++row4)
- {
- for (int col4 = 0; col4 < ncols4; ++col4)
- {
- // top left 1
- {
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1f; ptr__in += delta1f;
- }
-
- ++ptr_t[2]; ++ptr_e2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1b; ptr__in += delta1b;
- }
-
- ptr_t[2] += delta2; ptr_e2 += delta2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1f; ptr__in += delta1f;
-
- }
-
- ++ptr_t[2]; ++ptr_e2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1c; ptr__in += delta1c;
- }
-
- ptr_t[2] -= delta2; ptr_e2 -= delta2;
- }
-
- // top right 1
- ptr_t[3] += 1;
- {
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1f; ptr__in += delta1f;
- }
-
- ++ptr_t[2]; ++ptr_e2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1b; ptr__in += delta1b;
- }
-
- ptr_t[2] += delta2; ptr_e2 += delta2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1f; ptr__in += delta1f;
- }
-
- ++ptr_t[2]; ++ptr_e2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1d; ptr__in += delta1d;
- }
-
- ptr_t[2] += delta2b; ptr_e2 += delta2b;
- }
-
- // bot left 1
- ptr_t[3] += delta3;
- {
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1f; ptr__in += delta1f;
- }
-
- ++ptr_t[2]; ++ptr_e2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1b; ptr__in += delta1b;
- }
-
- ptr_t[2] += delta2; ptr_e2 += delta2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1f; ptr__in += delta1f;
- }
-
- ++ptr_t[2]; ++ptr_e2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1c; ptr__in += delta1c;
- }
-
- ptr_t[2] -= delta2; ptr_e2 -= delta2;
- }
-
- // bot right 1
- ptr_t[3] += 1;
- {
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1f; ptr__in += delta1f;
- }
-
- ++ptr_t[2]; ++ptr_e2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1b; ptr__in += delta1b;
- }
-
- ptr_t[2] += delta2; ptr_e2 += delta2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1f; ptr__in += delta1f;
- }
-
- ++ptr_t[2]; ++ptr_e2;
- threshold = *ptr_t[*ptr_e2];
- {
- for (unsigned i = 1; i < s; ++i)
- {
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
-
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1; ptr__in += delta1;
- }
-
- for (unsigned j = 1; j < s; ++j)
- {
- *ptr__out = *ptr__in < threshold;
- ++ptr__out; ++ptr__in;
- }
- *ptr__out = *ptr__in < threshold;
- ptr__out += delta1e; ptr__in += delta1e;
- }
- }
-
- // bot right -> next top left
- ptr_t[2] += delta2c; ptr_e2 += delta2c;
- ptr_t[3] = ptr_t[3] - delta3;
- ptr_t[4] += 1;
- }
-
- // eof -> next bof
- ptr__out += eor1; ptr__in += eor1;
- ptr_t[2] += eor2; ptr_e2 += eor2;
- ptr_t[3] += eor3;
- ptr_t[4] += eor4;
- }
-
-
-// mln::debug::println(out);
-
- return out;
- }
-
-
-
-// template <typename I, typename J, typename K>
-// mln_ch_value(I, unsigned)
-// binarize_generic_debug(const I& in, const J& e2, const
util::array<K>& t_ima,
-// unsigned s)
-// {
-// mln_ch_value(I,unsigned) out;
-// initialize(out, in);
-// data::fill(out, 0);
-
-// typedef const mln_value(K)* ptr_type;
-
-// ptr_type ptr_t[5];
-// ptr_t[2] = & t_ima[2].at_(0, 0);
-// ptr_t[3] = & t_ima[3].at_(0, 0);
-// ptr_t[4] = & t_ima[4].at_(0, 0);
-
-
-// const mln_value(J)* ptr_e2 = & e2.at_(0, 0);
-// const mln_value(I)* ptr__in = & in.at_(0, 0);
-// unsigned* ptr__out = & out.at_(0, 0);
-
-
-// // Since we iterate from a smaller image in the largest ones and
-// // image at scale 1 does not always have a size which can be
-// // divided by (4*s), some sites in the border may not be processed
-// // and we must skip them.
-
-// std::cout << in.ncols() << std::endl;
-// std::cout << in.ncols() % (4 * s) << std::endl;
-// int more_offset = - ((4 * s) - in.ncols() % (4 * s));
-
-// if (more_offset == - (4*s))
-// more_offset = 0; // No offset needed.
-
-// std::cout << "more_offset == " << more_offset <<
std::endl;
-// std::cout << "- b1 = " << in.border()
-// << "- b2 = " << t_ima[2].border()
-// << "- b3 = " << t_ima[3].border()
-// << "- b4 = " << t_ima[4].border()
-// << std::endl;
-
-// const int
-// nrows4 = t_ima[4].nrows(), ncols4 = t_ima[4].ncols(),
-
-
-// delta1 = in.delta_index(dpoint2d(+1, -(s - 1))),
-// delta1b = in.delta_index(dpoint2d(+1, -(s + s - 1))),
-// delta1c = in.delta_index(dpoint2d(-(s + s - 1), +1)),
-// delta1d = in.delta_index(dpoint2d(+1, -(s * 4 - 1))),
-// delta1e = in.delta_index(dpoint2d(-(s * 4 - 1), +1)),
-// delta1f = in.delta_index(dpoint2d(-(s - 1), +1)),
-
-// delta2 = t_ima[2].delta_index(dpoint2d(+1, -1)),
-// delta2b = t_ima[2].delta_index(dpoint2d(+1, -3)),
-// delta2c = t_ima[2].delta_index(dpoint2d(-3, +1)),
-
-// delta3 = t_ima[3].delta_index(dpoint2d(+1, -1)),
-
-// eor1 = in.delta_index(dpoint2d(+4 * s, - in.ncols())) + more_offset,
-// eor2 = t_ima[2].delta_index(dpoint2d(+4,- t_ima[2].ncols())),
-// eor3 = t_ima[3].delta_index(dpoint2d(+2,- t_ima[3].ncols())),
-// eor4 = t_ima[4].delta_index(dpoint2d(+1,- t_ima[4].ncols()));
-
-// unsigned pid = 0;
-
-// mln_value(J) threshold;
-// for (int row4 = 0; row4 < nrows4; ++row4)
-// {
-// for (int col4 = 0; col4 < ncols4; ++col4)
-// {
-// // top left 1
-// {
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1f; ptr__in += delta1f;
-// }
-
-// ++ptr_t[2]; ++ptr_e2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1b; ptr__in += delta1b;
-// }
-
-// ptr_t[2] += delta2; ptr_e2 += delta2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1f; ptr__in += delta1f;
-
-// }
-
-// ++ptr_t[2]; ++ptr_e2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1c; ptr__in += delta1c;
-// }
-
-// ptr_t[2] -= delta2; ptr_e2 -= delta2;
-// }
-
-// // top right 1
-// ptr_t[3] += 1;
-// {
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1f; ptr__in += delta1f;
-// }
-
-// ++ptr_t[2]; ++ptr_e2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1b; ptr__in += delta1b;
-// }
-
-// ptr_t[2] += delta2; ptr_e2 += delta2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1f; ptr__in += delta1f;
-// }
-
-// ++ptr_t[2]; ++ptr_e2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1d; ptr__in += delta1d;
-// }
+ int s = atoi(argv[3]);
-// ptr_t[2] += delta2b; ptr_e2 += delta2b;
-// }
-
-// // bot left 1
-// ptr_t[3] += delta3;
-// {
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1f; ptr__in += delta1f;
-// }
-
-// ++ptr_t[2]; ++ptr_e2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1b; ptr__in += delta1b;
-// }
-
-// ptr_t[2] += delta2; ptr_e2 += delta2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1f; ptr__in += delta1f;
-// }
-
-// ++ptr_t[2]; ++ptr_e2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1c; ptr__in += delta1c;
-// }
-
-// ptr_t[2] -= delta2; ptr_e2 -= delta2;
-// }
-
-// // bot right 1
-// ptr_t[3] += 1;
-// {
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1f; ptr__in += delta1f;
-// }
-
-// ++ptr_t[2]; ++ptr_e2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1b; ptr__in += delta1b;
-// }
-
-// ptr_t[2] += delta2; ptr_e2 += delta2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1f; ptr__in += delta1f;
-// }
-
-// ++ptr_t[2]; ++ptr_e2;
-// threshold = *ptr_t[*ptr_e2];
-// {
-// for (unsigned i = 1; i < s; ++i)
-// {
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-
-// *ptr__out = pid++;
-// ptr__out += delta1; ptr__in += delta1;
-// }
-
-// for (unsigned j = 1; j < s; ++j)
-// {
-// *ptr__out = pid++;
-// ++ptr__out; ++ptr__in;
-// }
-// *ptr__out = pid++;
-// ptr__out += delta1e; ptr__in += delta1e;
-// }
-// }
-
-// // bot right -> next top left
-// ptr_t[2] += delta2c; ptr_e2 += delta2c;
-// ptr_t[3] = ptr_t[3] - delta3;
-// ptr_t[4] += 1;
-// }
-
-// // eof -> next bof
-// ptr__out += eor1; ptr__in += eor1;
-// ptr_t[2] += eor2; ptr_e2 += eor2;
-// ptr_t[3] += eor3;
-// ptr_t[4] += eor4;
-// }
-
-
-// // mln::debug::println(out);
-
-// return out;
-// }
-
-
-
-
- unsigned sub(unsigned nbr, unsigned down_scaling)
- {
- return (nbr + down_scaling - 1) / down_scaling;
- }
-
- template <typename I>
- util::array<util::couple<mln_domain(I), unsigned> >
- compute_sub_domains(const I& ima, unsigned n_scales, unsigned s)
+ if (s < 1 || s > 3)
{
- util::array<util::couple<unsigned, unsigned> > n(n_scales + 2);
-
- n(1) = make::couple(ima.nrows(), ima.ncols());
- n(2) = make::couple(sub(n(1).first(), s),
- sub(n(1).second(), s));
- for (unsigned i = 3; i <= n_scales + 1; ++i)
- n(i) = make::couple(sub(n(i - 1).first(), 2),
- sub(n(i - 1).second(), 2));
-
-
- util::array<util::couple<mln_domain(I), unsigned> > out(n.size());
- out(0) = make::couple(make::box2d(1,1), 1u);
- out(1) = make::couple(make::box2d(ima.nrows(), ima.ncols()), 2u);
- out(n_scales + 1) = make::couple(make::box2d(n(n_scales + 1).first(),
- n(n_scales + 1).second()),
- 1u);
-
- for (unsigned i = n_scales; i > 1; --i)
- out(i) = make::couple(make::box2d(2 * out(i + 1).first().nrows(),
- 2 * out(i + 1).first().ncols()),
- 2 * out(i + 1).second());
-
- out(1).second() = std::max(out(2).first().ncols() * s - ima.ncols(),
- out(2).first().nrows() * s - ima.nrows());
-
-// out(1).second() = std::max(ima.ncols() % (4 * s),
-// ima.nrows() % (4 * s));
-
-// out(2).first().ncols() * s - ima.ncols(),
-// out(2).first().nrows() * s - ima.nrows() );
-
- return out;
- }
-
-
-
- bool
- check_args(int argc, char * argv[])
- {
- if (argc < 5 || argc > 7)
- return false;
-
-// int nb_scale = atoi(argv[3]);
- int s = atoi(argv[3]);
-// int q = atoi(argv[5]);
-
-// if (q < 2)
-// {
-// std::cout << "q must be greater than 2." << std::endl;
-// return false;
-// }
- if (s < 1 || s > 3)// || s < q)
- {
- std::cout << "s must be set to 2 or 3."
- << std::endl;
- return false;
- }
-
-
-// if (nb_scale < 1)
-// {
-// std::cout << "Not enough scales." << std::endl;
-// return false;
-// }
-
-// if ((argc - 7) != (nb_scale - 1))
-// {
-// std::cout << "Not enough area threshold."
-// << "There must be nb_scale - 1 thresholds."
-// << std::endl;
-// return false;
-// }
-
- return true;
- }
-
-
- void data_rand(image2d<unsigned>& e2)
- {
- unsigned v = 2;
- mln_piter_(box2d) p(e2.domain());
- for_all(p)
- {
- e2(p) = v++;
- if (v == 5) v = 2;
- }
+ std::cout << "s must be set to 2 or 3."
+ << std::endl;
+ return false;
}
-
-} // end of namespace mln;
-
-
+ return true;
+}
const char *args_desc[][2] =
{
{ "input.pgm", "A graylevel image." },
{ "w", "Window size at scale 1. (Common value: 101)" },
- { "s", "First subsampling ratio (Common value: 2)." },
- { "min_area", "Minimum object area (at scale 2) (Common value:
200)" },
- { "debug", "Display debug/bench data if set to 1" },
+ { "s", "First subsampling ratio (Common value: 3)." },
+ { "min_area", "Minimum object area at scale 1 (Common value:
67)" },
{0, 0}
};
@@ -1327,71 +66,36 @@ int main(int argc, char *argv[])
{
using namespace mln;
using namespace scribo;
- using value::rgb8;
- using value::int_u8;
- using value::int_u16;
- using value::label_16;
-
- typedef image2d<label_16> L;
if (!check_args(argc, argv))
return scribo::debug::usage(argv,
"Multi-Scale Binarization of a color image based on Sauvola's
algorithm.",
- "input.pgm w s area_thresholds output.pbm [debug]",
+ "input.pgm w s area_threshold output.pbm",
args_desc, "A binary image.");
trace::entering("main");
- mln::debug::internal::filename_prefix = argv[1];
+ // Window size
+ unsigned w_1 = atoi(argv[2]); // Scale 1
// First subsampling scale.
unsigned s = atoi(argv[3]);
- // Window size.
- unsigned
- w_1 = atoi(argv[2]), // Scale 1
- w_work = w_1 / s; // Scale 2
-
- // Number of subscales.
- unsigned nb_subscale = 3;//atoi(argv[3]);
+ // Lambda value
+ unsigned lambda_min_1 = atoi(argv[4]);
- // Subscale step.
- unsigned q = 2;//atoi(argv[5]);
-
- mln::debug::quiet = true;
-
- if (argc == 7)
- mln::debug::quiet = ! atoi(argv[6]);
-
-
- if (! mln::debug::quiet)
- std::cout << "Running Sauvola_ms with w_1 = " << w_1
- << ", s = " << s
- << ", nb_subscale = " << nb_subscale
- << ", q = " << q
- << std::endl;
- typedef image2d<value::int_u8> I;
- dpoint2d none(0, 0);
-
- mln::util::timer
- timer_,
- sauvola_timer_;;
-
- // Tmp variable used for timer results;
- float t_;
-
- I input_full;
- io::pgm::load(input_full, argv[1]);
+ image2d<value::int_u8> input_1;
+ io::pgm::load(input_1, argv[1]);
{
- unsigned max_dim = math::max(input_full.ncols() / s,
- input_full.nrows() / s);
- if (w_work > max_dim)
+ unsigned max_dim = math::max(input_1.ncols(),
+ input_1.nrows());
+ if (w_1 > max_dim)
{
std::cout << "------------------" << std::endl;
std::cout << "The window is too large! Image size is only "
- << input_full.nrows() / s << "x" << input_full.ncols() / s
+ << input_1.nrows() << "x" << input_1.ncols()
<< std::endl
<< "Window size must not exceed " << max_dim
<< std::endl;
@@ -1399,324 +103,11 @@ int main(int argc, char *argv[])
}
}
-// I input_full(9,9);
-// mln::debug::iota(input_full);
-
- sauvola_timer_.start();
-
- unsigned lambda_min = atoi(argv[4]);
- unsigned lambda_max = lambda_min * q; // * atoi(argv[7])
-
-
- util::array<I> t_ima;
-
- // Make sure t_ima indexes start from 2.
- {
- I dummy(1,1);
- for (unsigned i = 0; i < nb_subscale + 2; ++i)
- t_ima.append(dummy);
- }
+ image2d<bool>
+ output = scribo::binarization::sauvola_ms(input_1, w_1, s, lambda_min_1);
-
- image2d<int_u8> e_2;
- util::array<I> sub_ima;
-
- // Make sure sub_ima indexes start from 2.
- {
- I dummy(1,1);
- sub_ima.append(dummy);
- sub_ima.append(dummy);
- }
-
-
- timer_.restart();
-
- util::array<util::couple<box2d, unsigned> >
- sub_domains = compute_sub_domains(input_full, nb_subscale, s);
-
- if (! mln::debug::quiet)
- std::cout << "adjusting input border to " <<
sub_domains(1).second()
- << std::endl;
-
- border::adjust(input_full, sub_domains(1).second());
- border::mirror(input_full);
-
-// mln::debug::println_with_border(input_full);
-
- t_ = timer_;
- if (! mln::debug::quiet)
- std::cout << "sub domains computed and adjust input border size - "
- << t_ << std::endl;
-
- // Resize input and compute integral images.
- timer_.restart();
- typedef image2d<util::couple<double,double> > integral_t;
- integral_t integral_sum_sum_2;
-
- if (! mln::debug::quiet)
- std::cout << "sub_domain(2).domain() == " <<
sub_domains(2).first() << std::endl;
-
- sub_ima.append(scribo::subsampling::integral(input_full, s,
- integral_sum_sum_2,
- sub_domains[2].first(),
- sub_domains[2].second()));
-
-// {
-// io::pgm::save(sub_ima[2], "in_50p.pgm");
-// mln_piter_(integral_t) p(integral_sum_sum_2.domain());
-// for_all(p)
-// {
-// std::cout << integral_sum_sum_2(p).first() << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-
-// for_all(p)
-// {
-// std::cout << integral_sum_sum_2(p).second() << ", ";
-// }
-// std::cout << std::endl << " ------- " << std::endl;
-// }
-
-// mln::debug::println(integral_sum_sum_2);
-
- t_ = timer_;
- if (! mln::debug::quiet)
- std::cout << "subsampling 1 -> 2 And integral images - " <<
t_
- << " - nsites = "
- << input_full.domain().nsites() << " -> "
- << sub_ima[2].domain().nsites() << " - "
- << input_full.domain() << " -> "
- << sub_ima[2].domain() << std::endl;
-
-
- for (unsigned i = 3; i <= nb_subscale + 1; ++i)
- {
- timer_.restart();
- sub_ima.append(mln::subsampling::antialiased(sub_ima[i - 1], q, none,
- sub_domains[i].first(),
- sub_domains[i].second()));
- t_ = timer_;
- if (! mln::debug::quiet)
- std::cout << "subsampling " << (i - 1) << " ->
" << i
- << " - " << t_
- << " - nsites = "
- << sub_ima[i].domain().nsites() << " - "
- << sub_ima[i].domain()
- << std::endl;
- }
-
-
- initialize(e_2, sub_ima[2]);
- data::fill(e_2, 0u);
-
- // Compute threshold image.
-
- // Highest scale -> no maximum component size.
- {
- timer_.restart();
- int i = sub_ima.size() - 1;
- unsigned ratio = std::pow(q, i - 2); // Ratio compared to e_2
- t_ima[i] = compute_t_n_and_e_2(sub_ima[i], e_2,
- lambda_min / ratio,
- mln_max(unsigned),
- s,
- q, i, w_work, integral_sum_sum_2);
-
- t_ = timer_;
- if (! mln::debug::quiet)
- std::cout << "Scale " << i
- << " - 1/" << s * ratio
- << " compute t_n and update e - " << t_ << std::endl;
- }
-
- // Other scales -> maximum and minimum component size.
- {
- for (int i = sub_ima.size() - 2; i > 2; --i)
- {
- timer_.restart();
- unsigned ratio = std::pow(q, i - 2); // Ratio compared to e_2
- t_ima[i] = compute_t_n_and_e_2(sub_ima[i], e_2,
- lambda_min / ratio,
- lambda_max / ratio,
- s,
- q, i, w_work, integral_sum_sum_2);
-
- t_ = timer_;
- if (! mln::debug::quiet)
- std::cout << "Scale " << i
- << " - 1/" << s * ratio
- << " compute t_n and update e - " << t_ << std::endl;
- }
- }
-
- // Lowest scale -> no minimum component size.
- {
- timer_.restart();
- t_ima[2] = compute_t_n_and_e_2(sub_ima[2], e_2, 0, lambda_max,
- s, 1, 2, w_work, integral_sum_sum_2);
- t_ = timer_;
- if (! mln::debug::quiet)
- std::cout << "Scale " << 2
- << " - 1/" << s
- << " compute t_n and update e - " << t_ << std::endl;
-
- }
-
- if (! mln::debug::quiet)
- std::cout << "--------" << std::endl;
-// io::pgm::save(e_2, mln::debug::filename("e.pgm"));
-
-
-
- timer_.restart();
- e_2 = transform::influence_zone_geodesic(e_2, c8());
- t_ = timer_;
- if (! mln::debug::quiet)
- std::cout << "influence zone - " << t_ << std::endl;
-
-
-
-// Saving influence zone scale image.
-// io::pgm::save(e_2, mln::debug::filename("e_ext.pgm"));
-// io::pbm::save(bin, argv[8]);
-// io::pgm::save(t, mln::debug::filename("t.pgm"));
-
-// for (unsigned i = 2; i < t_ima.size(); ++i)
-// io::pgm::save(t_ima[i], mln::debug::filename("t.pgm", i));
-
-// {
-// image2d<bool> out_2;
-// initialize(out_2, e_2);
-// mln_piter_(image2d<int_u8>) p(e_2.domain());
-// for_all(p)
-// {
-// out_2(p) = sub_ima[2](p) < t_ima[2](p);
-// }
-// io::pbm::save(out_2, argv[5]);
-// }
-
-
- timer_.restart();
- image2d<bool> out_new = binarize_generic(input_full, e_2, t_ima, s);
-// image2d<bool> out_new = binarize(input_full, e_2, t_ima);
- t_ = timer_;
- if (! mln::debug::quiet)
- std::cout << "Compute bin - " << t_ << std::endl;
-
- t_ = sauvola_timer_;
- if (! mln::debug::quiet)
- std::cout << "Sauvola : " << t_ << std::endl;
-
- io::pbm::save(out_new, argv[5]);
-// abort();
+ io::pbm::save(output, argv[5]);
}
-
-
-// int main(int argc, char *argv[])
-// {
-// using namespace mln;
-// using namespace scribo;
-// using value::rgb8;
-// using value::int_u8;
-// using value::int_u16;
-// using value::label_16;
-
-// typedef image2d<label_16> L;
-
-// unsigned s = atoi(argv[3]);
-
-
-// typedef image2d<value::int_u8> I;
-// dpoint2d none(0, 0);
-
-// I input_full(atoi(argv[1]),atoi(argv[2]));
-// // I input_full(30,20); // Cas pourri
-// // I input_full(30,24); // Cas 'row <<'
-// // I input_full(36,24); // Cas ideal
-// // I input_full(36,20); // Cas 'col <<'
-// mln::debug::iota(input_full);
-
-// mln::debug::println(input_full);
-
-
-// util::array<I> sub_ima;
-// util::array<I> t_ima;
-
-
-// // Make sure t_ima indexes start from 2.
-// {
-// I dummy(1,1);
-// for (unsigned i = 0; i < 3 + 2; ++i)
-// t_ima.append(dummy);
-// }
-
-// // Make sure sub_ima indexes start from 2.
-// {
-// I dummy(1,1);
-// sub_ima.append(dummy);
-// sub_ima.append(dummy);
-// }
-
-
-
-// util::array<util::couple<box2d, unsigned> >
-// sub_domains = compute_sub_domains(input_full, 3, s);
-
-// border::adjust(input_full, sub_domains(1).second());
-// border::mirror(input_full);
-
-// // Resize input and compute integral images.
-// typedef image2d<util::couple<double,double> > integral_t;
-// integral_t integral_sum_sum_2;
-
-// sub_ima.append(scribo::subsampling::integral(input_full, s,
-// integral_sum_sum_2,
-// sub_domains[2].first(),
-// sub_domains[2].second()));
-
-// std::cout << "input border = " << input_full.border() <<
std::endl;
-// std::cout << "subsampling 1 -> 2 And integral images - "
-// << " - nsites = "
-// << input_full.domain().nsites() << " -> "
-// << sub_ima[2].domain().nsites() << " - "
-// << input_full.domain() << " -> "
-// << sub_ima[2].domain() << std::endl;
-
-
-// for (unsigned i = 3; i <= 3 + 1; ++i)
-// {
-// sub_ima.append(mln::subsampling::antialiased(sub_ima[i - 1], 2, none,
-// sub_domains[i].first(),
-// sub_domains[i].second()));
-// std::cout << "subsampling " << (i - 1) << " ->
" << i
-// << " - "
-// << " - nsites = "
-// << sub_ima[i].domain().nsites() << " - "
-// << sub_ima[i].domain()
-// << std::endl;
-// t_ima[i] = I(sub_ima[i].domain());
-// }
-
-
-
-
-
-// image2d<int_u8> e_2;
-// initialize(e_2, sub_ima[2]);
-// data::fill(e_2, 2);
-
-// data::fill(t_ima[2], 30);
-
-// image2d<unsigned> out_new = binarize_generic_debug(input_full, e_2, t_ima,
s);
-
-// mln::debug::println_with_border(out_new);
-// // io::pgm::save(out_new, "out.pgm");
-
-// std::cout << "------------" << std::endl;
-
-// // out_new = binarize_generic_debug(input_full, e_2, t_ima, 2);
-// // mln::debug::println(out_new);
-// }
--
1.5.6.5