last-svn-commit-26-g6db6d75 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. --- 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@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@lrde.epita.fr> + * core/object_image.hh: Make use of mln::labeled_image_base. 2009-12-14 Guillaume Lazzara <z@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
participants (1)
-
Guillaume Lazzara